L'Hexapod: New servo controller commands
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 new 64 channel ATMega168 serial servo controller accepts the following commands. All successful commands are echoed back. Parameters are validated and errors are indicated with an error response of [0xFF] [badParamIndex] [Command echo] where badParamIndex is a 1 based index of the parameters in the command and indicates which parameter failed validation.
- Set Servo Position [0x41] [servo] [position] - This command operates in the same way as the standard SSC compatible servo command that the original servo controllers supported. That is the servo specified is moved directly to the position specified. The servo index should be between 0 and the number of servos that the controller supports (up to 64) and the position should be between 0 and 254. A position of 127 sets the servo to the centre.
- Delayed Set Servo Position [0x42] [servo] [position] [stepSize] - This command will cause the servo to move from where it currently is to the desired position in steps of the specified size. A step is taken each time the PWM pulse refreshes, so 20 times per second. If the servo is currently at position 0 and you want it to move to position 100 and you specify a step size of 1 then it will take around 5 seconds to reach the final destination. With a step size of 2 it would take around 2.5 seconds, etc. Note that the actual time taken will be affected by the speed of the servo. If you specify a step size of larger than the distance between the current position and the desired position then the servo moves to the new position straight away. The command is echoed once it is actioned and an asynchronous ‘move complete’ notification is generated once the servo arrives at its desired destination. The move complete notification is in the form: [0xFE] [servo] [position]. At any time between starting the move and the move completing you can send a stop command to stop the servo at the point where it currently is.
- **Delayed Set Servo Position **with step frequency control [0x43] [servo] [position] [stepSize] [stepFrequency] - This command is the same as the command above except that the frequency of steps can also be controlled. The command above is equivalent to this command with a stepFrequency of 1. If the servo is currently at position 0 and you want to move it to position 100 and you specify a step size of 1 and a frequency of 2 then it will take around 10 seconds to reach the final destination.
- Stop Servo [0x44] [servo] - This command will stop the servo moving if it is currently moving as part of a delayed move command. The current status of the servo at the time it was stopped is returned in a servo stop response which is sent after the stop servo command has been echoed and actioned. The servo stopped response is in the form:** [0xFD] [servo] [currentPos] [stepFrequency] [targetPosition] [stepSize]** where the current position is the position of the servo after it has stopped and the stepFrequency is the frequency with which it was moving before it was stopped. If the stepFrequency is zero then the servo was already stationary.
- Stop Servos [0x45] [numServos] [servo1] [servo2] … [servoN] - This command will stop all of the servos specified and will generate a servo stopped response for each one.
- Stop All Servos [0x46] - This command stops all of the controller’s servos and generates a servo stopped response for each one.
- Query Servo
- [0x47] [servo] - This command will query the current position of the specified servo and return it as a servo query response after the command echo. The servo query response is identical to the servo stop response except the response code is 0xFC rather than 0xFD. Note that if the stepFrequency is zero then the servo is stationary. If the stepFrequency is non zero and the currentPos is not equal to the targetPos then the servo is moving.
- Query Servos [0x48] [numServos] [servo1] [servo2] … [servoN] - This command will query all of the servos specified and will generate a servo query response for each one.
- Query All Servos [0x49] - This command queries all of the controller’s servos and generates a servo query response for each one.
As you can see, this controller gives me much more control over the movement of the servos attached to it. The main thing being that I can stop servos in mid move if required and that I can move servos at slower than maximum speed. This paves the way for being able to simplify the logic in the actual microcontroller that generates the movement sequences required to move the legs whilst still being able to monitor for collisions and stop the servos in mid step if the sensors on the legs indicate that it’s necessary.
Of course, first I actually have to build more than one leg, but before I move on to that there are a couple more servo controller commands to implement. The first being the ability to set several servos to move to new positions in such a way that they arrive there at the same time. This was the reason for the stepSize and stepFrequency elements of the delayed move commands. Ideally the servo controller will do the calculations required which means that the ‘gait generator’ just needs to know where to put the feet rather than how to move each servo at the right speed so that the foot ends up in the right place at the right time… Next will be the ability to provide a mapping table between ’logical’ servo indexes and physical servos, this is so that if it happens to be difficult to get all of the tracks on the board to end up in the right places I can adjust which logical servo is controlled by which pin. This will involve accessing the eeprom of the ATMega168… Once that’s done it would be useful to have the ability to set the ‘default starting position’ for each servo, so that they can start at positions other than 127 without there being a race between the controller starting up and the servos all ending up in odd positions. Finally as a safety feature being able to set a minimum and maximum position for each servo would be useful.
Source code for the current version of the controller will be available soon.