L'Hexapod: Moving multiple servos at once
This article was previously published on lhexapod.com as part of my journey of discovery into robotics and embedded assembly programming. A full index of these articles can be found here.
The final command for my serial servo controller is the most complex. The idea behind it is that with a hexapod leg you will want to be able to move the leg to a new position where the new position requires all three of the servos that manage the leg to move to potentially new locations. Ideally you want the “foot” to arrive at the final resting place in such a way that all of the servos complete their moves at the same time. Since each servo will likely have to move a different distance from where it is now to where you want it to be and since I don’t want to have to burden the code that determines how the legs themselves move with this kind of knowledge I decided to build the functionality into the servo controller. My design decision was validated somewhat when I discovered that the SSC-32 servo controller can do this.
I have all of the pieces in place to be able to do this, but as always, the devil is in the detail. To be able to move several servos from one place to another so that they arrive at the same time I first implemented commands that allow me to move servos at less than their maximum speed. This resulted in the two “delayed move” commands that are present in the current version of the servo controller. The idea is that you can have the servo controller take a target position and a step size and a step frequency and it will deal with moving the servo gradually from its current position to the target position (and then notify you when the servo has completed the move). This works well and the functionality is essential for getting the multiple servo “move as one” command to work.
With the multiple servo command I need to take several new target positions and then calculate the required step sizes and step speeds for each of the servos so that they can all arrive at their target positions at the same time. For example, if we have two servos, both currently at position 0, and we wish to move servo A to position 100 and servo B to position 50 it’s fairly obvious that B has to move half the distance that A has to move and as such if A were stepping 1 step every cycle then B needs to step 1 step every other cycle for them to arrive at their target positions at the same time. It’s less easy to see that if servo B needs to move to position 77 then it needs to step with a step size of 3 every 4 cycles and that we need to fudge its start point by one step (of 3) to ensure that it actually arrives at the target (rather than at position 75).
Essentially we’re interested in calculating the smallest common factors between the maximum distance that needs to be moved (by the servo that needs to move farthest) and the distance that this particular servo needs to be moved. I’ve currently got a spreadsheet that can calculate the required step size and frequency values for given distance pairs, which is a start. Translating that into assembly shouldn’t be too hard now that I understand what’s needed.