McAleer highlights the critical transition from blind actuators to intelligent, feedback-driven systems through serial communication. Itβs a clear-eyed look at why architectural scalability is the true foundation of modern robotics.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
Why are bus servos better?Added:
So, these two servos are running off a single data wire. They're daisy-chained together and can read back exactly where each one is at any moment. There's no jitter and you know precisely where they are.
Hey robot makers, today we're going to talk about bus servos, specifically the Feetech STS3215.
I'm going to explain what makes this different from the typical hobby pulse width modulation servos they probably used before, how to wire them up, and how to wire them up to a Raspberry Pi and control them with MicroPython. By the end of this video, you'll have servos moving and you'll be able to read their position back and see why they make such a big deal for robotics projects. Let's dive straight in.
Okay, so let's get started with the basics. If you've done any kind of maker projects with servos, you've most certainly used a pulse width modulation servo. These send a pulse width signal and that moves it into position, simple enough. But, there are a few problems.
So, first, every servo needs its own signal wire back to your microcontroller. So, if you've got six servos, that's six GPIO pins. And second, the servo has no way of telling you where it actually is. You're telling it where to go, but you just have to trust that it gets there.
Bus servos fix both of those problems.
The SCS3215 uses serial communication instead of pulse width modulation. You send commands over a single wire using half duplex UART, which means that the same wire handles both sending and receiving.
So, in this case, I think this is the white signal cable here. And because it's a bus, you can daisy-chain as many servos as you like together, again with a single cable. Each servo gets a unique ID and you address them by that number.
So, instead of wiring every servo back to a separate pin, you can connect them all to a single pin and chain them together on one data line. And here's the really good bit. Because there is two-way communication, you can ask the servo where it is and it will tell you.
Position feedback. You can read things like temperature, load, how much force is being applied, and voltage. The servo becomes a sensor as well as an actuator.
So, let me quickly run through the key differences. A standard pulse width modulation servo takes a pulse width signal, it needs one GPIO pin per servo, and gives you no feedback at all. The SCS3215 talks over the serial, lets you daisy-chain everything together on one bus, and gives you full position feedback. It's got 12-bit resolution and that means there's 4,096 steps of precision across the range. For around $14, that's a remarkable value.
So, to wire this up, you'll need a Raspberry Pi Pico. You can use any microcontroller, but in this case, we're all about the Raspberry Pi Pico. You'll need a Waveshare serial bus servo driver board. These are about about 10 quid, about $15. And these are made by the amazing Waveshare. And you'll need a couple of STS3215 servos and a power supply. I bought a power supply so that I can power this board and this can then in turn power the servos themselves. You don't want to be powering your servos from a microcontroller, that makes no sense. So, the SCS3215 runs at 7.4 volts. So, a 2S LiPo or a 7.4 volt DC power supply will work the best. So, here's the wiring diagram. The Waveshare board handles the voltage regulation and the half duplex conversion for you. This makes it a lot easier to use. You can then connect the Pico to the Waveshare board over the UART, the transmit and the receive, and then plug in the servo into the connectors on the board. You can see the board has two connectors and you simply just plug in the servo into one of those two buses.
The Waveshare board has these handy JST connectors that match the plugs on the STS3215 servo and you can just click them into place. To add more servos, you just chain them together. Each STS32 has two ports, one in and one out, and you run the cable from the first servo to the second, second to the third, and so on.
And the power and the data all go through the same cable. Really, really clean. And it also means that you're not stretching those cables that are the furthest away from your microcontroller.
Now, one thing to watch for, each servo has a unique ID on the bus. And out of the box, they are all come set to ID one. So, before you chain them up, you'll want to connect one at a time, change their IDs, and I'll show you how to do that in code in a moment. Okay, so let's get into the code. We're going to use MicroPython on a Pico and the library we need comes from Waveshare.
You can download it from their wiki page. I'll put a link in the description. I've also done my own version of this as well. I'll send you a link to that for the full demo code that we were looking at today. to quickly wire this up and show you how to do this. So, we have the the Waveshare servo adapter board. And we need some power for that. So, I've got my DC power supply. You can see now it's got a little red light showing that it's powered up. And we have the first servo.
And also note on here, note on here, because we're going to be using these pinouts to connect our Raspberry Pi Pico to rather than the USB connector, we need to set both of these yellow jumpers into the top position. You can see there it says A and B, UART to servo and USB servo. So, we want these in UART to servo, which is position A. So, this means pulling these out and putting them into the top position. And then, what we then need to do is correctly wire up our Pico. So, the black is ground. Let's just put the black cable into ground.
Then I have a receive and transmit. So, the blue wire and the purple wire. So, on the Pico, you can see there I've got the purple cable, which is going to the TX, and then the blue cable is going to the RX. So, that's pin zero and pin one.
And then the black cable is going to ground on the Pico. And this is just a regular Raspberry Pi Pico, the first generation. And we can also see our servo's got some power. It's got the little red light on it there. And I've also put a little, call these servo horns, that's in place there as well.
So, we can see that spin round in a moment when we run our code.
So, over here in Thonny, I've gone ahead and I've installed the servo library, which is this STS3215.py.
I've gone ahead and I've uploaded that to the Pico, which I've got attached.
And you can see there we've got the file already sat in our Pico ready waiting to be used. And I've got this simple servo setup, which is like a demo program, just to show you what this can do. So, I'll go through all the bits and pieces in a minute. I just want to actually show you this working.
So, if I go over here to the bench cam, I hit the play button on my code, you can see there we have our servo spinning around nicely.
This is in the position. You can see there.
It's working very nicely. So, it's just sweeping about. You can see there we've got the one cable connected up and the servo's moving around nicely there. One of the benefits of these servos is they have metal gears, so they're very, very strong. And the gearing, you can get different gearings of these. So, on the very back of the box, you'll see that it says that this is a STS3215 C001. I've also got a different model which has a different gearing ratio. So, this is the SCS3215 C044.
So, these have a slightly different gearing ratio and that means that some of them are faster but have less torque.
Some have got more torque, more more pulling power, but less speed. And we're building a robot arm project and because of this, we want the the very base of the robot, which has the most amount of force required, to have more torque and less speed. Whereas the gripper on the other end that has the least amount of stress on it, so that can be a nice fast and lower torque servo. Let me stop that from running. So, this library gives you everything you need to talk to your servos. Once you've copied that across to your Pico, we can actually start to write some code kind of proper. So, first of all, we're going to set up the serial connection. Let me go back over to here. We can see this code. So, the first thing we need to do is set up the serial connection. We use the UART object, which is this variable that we're passing in here. And we set the baud rate. I think actually that the library does all this for us. The the baud rate is like a million baud, which is very, very fast. Means our serial communication will be very, very fast between all the different servos that are connected on that chain. You can see there, so we're using UART zero. The Raspberry Pi Pico has a couple of UARTs that you can use. Because we're using pins zero and one, then that means that that's ID one. The ID of the servo, because we've just got this out of the box, it's going to default to servo ID one. If we want to put them in a chain and have more than one servo connected together, what we'll have to do before we chain them up is we'll have to change that ID. We'll do that in a second to set up a couple of these.
We can then define minimum and maximum positions. So, if we're building a robot arm, here's one I'm currently working on. Got this fully connected up yet.
They have a gripper.
We have a wrist which can turn. We have the wrist which can go up and down. And then we've got this kind of forearm. And then this will be connected to to a base piece. So, we've got several degrees of freedom. I think we have six degrees of freedom on this one. We'll have to set up the servo ID of each of these before we go ahead and make this move. Because otherwise, they're all set to one. If we send a command, all of them will be responding as if they're the same servo, as well as the same ID. So, we'll do that in a moment. So, you can see in this code as well, we've also got these goal positions. This just defines the minimum and maximum position that we want our arm to move to. These servos can go a full 360 degrees, unlike the little hobby servos which tend to be limited to about 180-ish degrees. So, because of that, we might want to limit the amount of travel our arm does. So, this this, for example, can spin round all the way, but it has got a cable. And if we spin that round too many times, the cable will rip off. And similar with this this piece that moves up and down, there is a maximum position that this goes to, zero degrees straight up and 180 degrees straight down. So, we don't want to go too much further than that.
So, we can define those as a minimum and maximum positions. And then the goal positions just mean these are the the ranges that we can move between. And then we've got this index of zero. So, we want to print out what the servo model number is, so you can just see what that is there. We can then ping the servo, so we do servo.ping. If it finds it, if it gets a value back, then we can continue, otherwise we can say no response from that particular ID that we've passed in. And then we can start the move loop. So, the goal positions we set the goal to be those goal positions, and the index is zero. And it says there, moving to position, and then whatever the goal currently is. And then we do servo.move, that actually moves the servo, makes it start moving that position. You can see there we pass in the ID of the servo we want to move in chain, the speed that we're moving at, and then the moving acceleration. So, you can see there we've got move command sent, position, speed, and acceleration.
And then we How many times we want to poll Is it at that position yet? So, while true, we read in the position, and the speed from the servo. So, we speed read position and speed. We pass in the ID of that. Moving then equals the reading moving ID. We can then print out the the poll count, the position, the speed, and moving. And then we increment that poll count by one. So, if moving equals zero or moving is none, then we can say the read return none, no response. Otherwise, we can say the movement is complete. We're checking this every tenth of a second. And then the target goal position index equals one minus index. And then we sleep for a second. So, we run this again, you can see the positions that are being reported. So, it's going from the top position, and it's going about I think it's doing a whole 360Β°. We can actually put a little arrow on there, let's do that.
You see there, it's spinning round a complete 360Β°.
It's very accurate as well at doing that. These are very positionally accurate. And that's it for basic control. You can move a servo, you've got the full closed loop feedback. Let me show you one more thing before the demo. We can set the limits. It's a good idea to set minimum and maximum position limits on your servos, especially if they're mounted to a mechanism where you don't want them to go the full range.
You can do this in the code by clamping the target position, or you can write limits directly to the servos internal memory. That way the servo knows itself, and won't go past those bounds, even if you accidentally tell it to. And to change the servo's ID, remember they come set to position one. You can connect a single servo to a bus, and then call the right ID function, give it a new number, and then from now on that servo responds from that new address.
Let's try that in our demo now.
So, let's write a quick program to set the ID. I'm just going to go over here, and I'm going to copy that first block of code, just so we don't have to type that out twice. So, we're just bringing in the the library. We're setting up the servo on the UART zero, the transmit pin on zero, and the RX pin on one. And then we simply say servo.setid, and then we need the current ID equals one, and the new ID is going to be two.
And just to test that this works, we can do print servo.ping.
We pass in one, which is our first The first time we run this, it'll be on ID one. And then after we changed it, we can say servo.ping.
We can do ping one to check that it isn't on that anymore, and we can also prove that it's working on servo ID two.
So, servo.ping ID two. So, we should get a true, false, and true if we run this code.
True, false, and true. So, it's now set on ID two. We can try and run that again, you'll see we get false, false, true, because it isn't on pick on ID one anymore. We can't set it from ID one to ID two, because it's already on ID two.
So, when we run the servo.ping on one again, we can see we got that second false. And then we When we ping ID two, we get true, because it's now detected on that address. So, what I need to then do to make my robot arm move is go ahead and set all those different positions, and then we can have these robot arms actually move. It's as simple as that.
Right, let's put it all together with a little demo.
So, I've got two servos here. I just need to check Do these have Yes, they have the gearing ratio on the top there.
So, that one is 1.345, and this one one is 191. So, there's our second one. So, I'm going to plug this cable into the front, and I'm just going to daisy chain into the second one there, like so. So, we've now got two red lights. These servos are now connected together in a nice daisy chain.
So, I've got this little program that I've written. You can see here what this does. This is a I'm going to use the two servos that we've connected up, daisy chained together with IDs one and two.
Servo one's going to sweep backwards and forwards. Servo two's going to follow through the short delay, producing like a wave-like motion. We can get live feedback on position, and that's going to be printed out to the terminal. So, we're going to import the library as before. We're going to bring back the position to degrees. The positions are in that between zero and 4096. So, we want to change that to two degrees, just so it's easier for us to understand. And then we can then center the the servos.
That's half of the 4096, so 2048. The amplitude, so that's the the 88Β° around the center, move our wave through.
Steps, 60 steps, 60 samples for a full sweep cycle. Step delay is 40 ms. Then we've got the lag, which is six, so it's going to be six steps behind. And then the speed is going to be 2400, and the acceleration's going to be 50. So, the sweep position is going to go through steps from the center and the amplitude, and it's going to have a nice sine wave kind of motion, so that these sweep back and forward, rather than harsh, jagged kind of movement. They're going to be nice and smooth. And then our main program here, that's going to define the bus. Because we've got multiple servos on there, we can call that a bus. You can see there we've got UART zero, transmit and receive is the pins we used before. And then we're putting in the 1 million baud rate, so it's very, very fast. And then for the servo ID, servos one and two, we can set the torque. So, we can set that to true. Torque means it kind of enables them, switches them on.
You can have them loose and just provide feedback. So, if you want to have a We'll do this in the follow-up video. If you want to have a robot arm where you can teach another arm where to be, you want that to be kind of loose. You don't want that want to be powered. So, if you want it to be loose, you can turn the torque off, and therefore you can move it into position, you can read the positions of those servos without them actually being powered. So, that's what the torque does. Next, we park both the servos at the center before the sweep.
So, bus.move servo one to the center, the speed we set to the speed, the acceleration to the acceleration. And then we do the same for servo number two. And then we sleep for half a second. We set the targets. So, these list of sweep positions, the step, the center, the amplitude. And then we then start the wave demo. And it says there, press control C to stop. That'll just come out of the loop.
And then we've got the normal kind of loop. So, try I equals zero, while true, targets with I modulus of steps. So, a modulus just returns the value without a floating point number. And we do a similar kind of thing for the targets of the second one. So, it's I minus the follower lag that we've provided, which was six steps, and then the modulus of steps. And then the bus.move, we must we move the servo one to the target position using the speed and acceleration. And then we do the same for bus servo number two. And then P1 is position one and position two. So, we read the actual positions of both of those. And then we can print all that on one nice long line that's been got some formatting applied to it. We've also got some keyboard interrupt. So, once we've pressed control C, when the demo ends, it will say stopping, releasing the torque. So, then it moves them to the center position. It then waits for a half second, and then sets the torque again to be false. So, removes the power from the servos, so they're not holding their position. And then we've got this format position, which is just a format helper. And then if name equals main, we just run the main program. So, let's run this and get this on our overhead camera here. Let's move these so we can actually see them. If I hit the play button now to start the script, you'll see they start to move around, and there's six steps between them, which is why the the one on the right looks slightly behind the one on the left. You see that's the one that's got the the first one in our series, which is number one.
And this is number two. If I put them right next to each other, you can see they're slightly out of phase, which is the six steps behind that we've designed for this particular project. Very, very nice and simple. So, the next step for me is to is to set the ID numbers on my robot arm, so that they start from the very tip, from the the grabber hand, that'll be one. The wrist that rotates will be two. The rotation of the wrist will be three. The forearm will be four.
And then the base and the elbow, I think I might call that, they will be five and six. So, where is all this going? Well, I'm working on a robot arm project. So, this is a robot arm. I downloaded these files from Printables. I'm not 100% happy with how they look and how they 3D print, so I'm going to make these my own. I've actually mocked these up in Fusion 360, so I can make them my own.
They're quite a lot of caliper readings of the the lengths in various different positions, and I even had to model the SCS3215 in Fusion 360, so that it's possible for me to then include that as a component in all my different models. But I do like the design of this. You can see here this isn't quite attached, which is why I'm holding that very carefully. And this does take a full six of these servos. What I find interesting is that they're all different gearing, so the top three are the kind of default gearing for these motors. And then the the the final three have different values. So, uh you have two of them slightly more torque, and then the third one, which is the one that's taking all of the torque, the whole weight of the robot arm, anything it's holding, that has to have the most amount of torque for it to be able to have that amount of power. It just means it's slightly slower in moving around. Well, this robot arm will give me plenty of motion. I'll be able to do lots of different things, and it's all 3D printed, which is pretty neat. And because they're all bus servos, the actual wiring is nice and simple, and there is essentially just one continuous data bus and power line going from the very tip to the very base of the robot arm. All programmed, of course, in MicroPython. So, I'm not going to make any promises of a timeline when this robot arm's going to be ready. I was hoping to have it ready for this video, but it takes quite a lot of time to do the 3D design, to print them out, test them, make sure everything fits okay.
But I'll be documenting the whole build.
If you want to follow along with that, do make sure that you're subscribed to the channel, cuz you don't want to miss that one. That's bus servos. Seriously, using pulse width modulation servos and you've been frustrated about the the lack of feedback, the messy wiring, the jitter, then give the SCS 3215s a try. I bought mine through AliExpress, so you can get them pretty cheap. You don't have to buy them necessarily off Amazon and pay the full price for them. I paid about $10 for each of the servos. So, they are about 10 times more expensive than the hobby servos, but you get what you pay for. And I genuinely think with that feedback, it makes all the difference. I'll put links to everything in the description, the servos, the Waveshare board, the code, the 3D printable parts for my robot arm project. If you found this useful, give it a thumbs up. It really does help the channel and I'll see you in the next one. Bye for now.
>> [music] [music] [music] [music]
Related Videos
U.S. Military Just Flexed The Most Dangerous Aircraft Ever Built The F-47
MaxAfterburnerusa
11K viewsβ’2026-05-29
Heating Staying On On The Hottest Day Of The Year
PlumbLikeTom
507 viewsβ’2026-05-29
λ°μ ν¨μ¨μ λμ΄λ νμκ΄ μΆμ μμ€ν μ κΈ°μ μ μ리 #곡ν #곡μ #νμκ΄ #μκ³ λ¦¬μ¦ #μ¬μμλμ§
μ°νμ₯κΈ°μ
2K viewsβ’2026-05-29
μ§κ΄ λ° κ³‘κ΄ λ°°κ΄ κ²°ν© κ³ μ μμ #worker #process #fabrication #pipework #clamp
μλμ΄μ΄
2K viewsβ’2026-05-30
Wire To Wire Connection Trick | Strong And Secure Electrical Joint #shortvideo #wireworks
ElectricianTips-b1h
5K viewsβ’2026-06-02
Peterborough to Newark Northgate Driver's Eye View aboard an InterCity 225 - East Coast Main Line
TrainsTrainsTrains
822 viewsβ’2026-05-31
AI turbine design: hypersonic cooling leap #shorts #ai #hypersonic
bobbby_rn
671 viewsβ’2026-05-31
How Far Can A Tomahawk Missile Actually Travel?
WarCurious
13K viewsβ’2026-05-28











