Robot Status Report – Maxwell
It feels pretty good to have Maxwell up, communicating, and actually moving around - even if he does hiccup from time to time. After my last post, I spent some time improving his motion, and cleaning up my code. After about an hour of tuning, he now makes repeatable moves, right angle (or really close to right angle) turns, and can spin in circles.
Experimentation with the program/servo timing highlighted the need to spend some time focused on two inter-related challenges-
- motor timing/control
Maxwell's design is basically a symmetrical "wheelchair" model with the motion provided by two servos that have been modified for continuous rotation. He is relatively light - especially since I am haven't mounted a battery pack on his chassis yet and am still running him from a wall wart. But, as light as he is, the basic laws of physics still apply. It's really obvious from the testing and examining the videos that momentum/inertia is a factor that can not be realistically ignored.
To move Maxwell forward the program sends a series of balanced PULSOUT commands to the drive servos. Although the servos are mounted along the same axis, the orientation of their cases and drive shafts are exactly opposite each other. They have to turn in opposition (one clockwise and the other counterclockwise) at equal rates for Maxwell to move forward in a straight line. And, since their zero set values are slightly different, the values the program sends need to be offset to compensate for the difference. This is a simple calculation, easy to build into the program at a low level so that we don't have to take it into consideration later.
When Maxwell is 'at rest' - i.e. stationary, assuming that there are no external forces working on him, he is 'stable.' When the program generates a forward move from his stable state, he appears to start moving in a clean fashion and travels forward in a straight line.
The initial program ignored inertia. That approach worked fine for the initial move, but ran into problems as soon as Maxwell needed to stop. His mass is high enough that the friction/braking inherent in the servos isn't enough to stop him quickly. Testing revealed a small but not insignificant amount of overshoot.
In actual operation Maxwell will be reacting to his surrounding environment and changing course accordingly, so in most cases it might be acceptable to ignore this type of small error. Still, it would be best if his 'dead-reckoning moves match his real world moves as much as possible.
Quite a few of the competitors in the All Japan Micromouse competition had problems with dead-reckoning. They started off fine, but after a lot of traveling, turns, and retracing, they got confused about their orientation and sometimes ran into the maze wall. In order to re-establish their orientation some of them used a special move sequence that involved backing into a maze wall several times. This worked only because their rear surfaces were flat, and because hitting the wall in reverse isn't considered to be a 'touch'. I was told that a Korean competitor came up with this creative strategy several years ago. While that approach is certainly workable, it doesn't strike me as being a good engineering solution to the problem. It works for the Micromouse competition, but it probably wouldn't be workable in other contests or for exploring the real world outside the maze. Besides, I can't imagine trying to explain to my wife why Maxwell needs to hit his butt on the wall....
First, improve his movements as much as possible, then implement a sensor based orientation strategy.
When Maxwell needs to turn the program sends the servos another set of matched PULSOUT commands, only this time they are instructed to turn the same way - i.e. both clockwise or both counterclockwise. Assuming that both servos are fairly closely matched, and that there are no wheel traction issues, Maxwell should be able to rotate smoothly around his own centerpoint.
What really happens, however, is a little thing called rotational inertia...
Maxwell continues to turn slightly after the program thinks he has already stopped. Of course, the program could be modified to take the overshoot into account - perhaps by the addition of a small fudge factor. Unfortunately fudge factors have a bad habit of melting into sticky goo after a while.
If it's at all possible, it would be much better to figure out an approach that eliminates the inertial overshoot. This will probably involve using proportional or ramped signals to the servos to handle accelleration and decelleration as a part of the movement sequences.
Going back to the issue of dead reckoning, one of the programs to test Maxwell required him to run around a square.
The sequence was forward, turn left, forward, turn left, forward, turn left, ... etc. until he completed the square. If he executed everything perfectly he would end up exactly where he started with the same orientation.
He ran the first leg fine but overshot the end slightly. The first turn was a little more than 90 degrees - not much, but enough to be noticeable. Naturally, the same errors continued and accumulated as he completed each leg of the square.
I haven't tried it yet, but it's easy to imagine what would happen if I put him into a long loop running around the course-
Fantastic, if you're building a Spirograph... Not so fantastic if you're building a working robot...
There are several reasons why a better motor timing/control approach seems to be necessary. First, given the discussion above, the program control design needs to be capable of managing the servo motor accelleration and decelleration.
Second, everything I've read on the internet and in books recommends that servos work better if they receive a fairly constant control signal stream. If they go for a while without seeing a control pulse then they stop actively controlling the motor position. It may be a good design approach to send the servos control signals, even when no movement is required. Early in Maxwell's testing he would perform well but infrequently, almost at random, he would hiccup. Instead of rapidly spinning his wheels in the direction I expected, he would turn them slowly, sometimes in the opposite direction. However, when I modified the driver program so that the servos were always being sent a control signal, his errant behavior disappeared.
Third, and possibly more important, servos weren't designed for continuous use as drive motors. It seems to be common for servos used as robot motors to be pushing up daisies after about 100 hours of use. If the motor control program can treat the servos in a 'kinder, gentler' fashion, then they will probably live longer - and give the robot's owner fewer ulcers.
Maxwell's first driver programs were very binary. They used a PULSOUT using 500, 750, and 1000 values to command the servo to turn CCW, stop, or turn CW. While it worked, and Maxwell scooted around the desktop, it was obviously pretty hard on the servos. The servos made a lot of crunching noise, and the power LED on Maxwell's brain board would dim. A normal servo in an R/C or model plane application might react like this-
The green square wave represents the request from the control program (not the actual control signals that are generated.) For example, the operator throws his R/C model car joystick hard over to the right. The unmodified servo control circuitry generates an error signal and drives the motor until it gets the error signal back to zero. The red line above represents the relative servo position as it responds to the request. Its motor is only drawing significant current when the error signal is non-zero. Overlaying the two curves and looking at the area between them (red/yellow bottom curve) we can get a rough feel for how they interact, and how much power is pumping through the servo.
When the servos are modified for use as continuous drive motors their internal feedback link is deliberately disabled, and we replace it with software program control. If we just drive the servo in a simple fashion - full forward, stop, full reverse, then we're probably giving it a huge amount of stress and decreasing it's useful life. On the other hand, if the program can be designed to implement accelleration and decelleration curves, the servos will probably last longer. At least that's my current thinking.
You might also enjoy: