leJOS user unroller posted this thread on the leJOS forum pointing to his blog entry which describes an interesting comparison of motor drivers. The motor drivers in his test are a Java version of the the Lego firmware driver, and the current (build 4037) leJOS driver. Interestingly the tests did not use an actual motor and run on the NXT instead they ran in a simulated environment. By a happy co-incidence I had been doing a little work on a simplified motor driver to address some problems I had found when using low acceleration rates. As i wanted a way to evaluate my driver it seemed to me that a great thing to do would be to try running the same tests as described by unroller on the real hardware and to compare the results.
For my version of the tests I've used three different motor drivers:
- The Lego firmware driver (as used in version 1.29 of the Lego firmware).
- The current leJOS driver (svn 3933 snapshot 4089)
- My experimental driver (not currently released)
The leJOS drivers used a set of simple Java test programs using the leJOS remote console API to log the speed/tachometer readings every 50ms. The Lego firmware driver tests used a short program written in NXC, with the same sample rate, but with the results being written to a file on the NXT.
The no load tests, and acceleration tests simply used a standard Lego motor (attached to port A), with nothing being driven. To apply a load to the motor I built a rather Heath Robinson contraption combining a cotton reel, Lego motor, a plastic jug and a number of spanners (to provide the variable weight), which was basically my version of Philo's motor test rig. This seemed to work pretty well and surprised me with just how powerful the Lego motors can be.
The first set of tests run the motor first in one direction, for two seconds then in the other, again for two seconds. The acceleration values used for the leJOS drivers was 9000 degrees/s/s which is a close match for the built in acceleration used by the Lego driver (and may well in effect be the maximum acceleration that can be used). When a load is being applied the load is such that initially the load is being dropped (so the motor is actually controlling the speed the load falls), then after the direction changes the load is being lifted by the motor,
No load run
The initial test is with just the motor alone, no load applied:
The Lego driver shows a short delay before the motor starts to run and then has a small overshoot, interestingly this is not corrected until a second or so after the start of the test. Following the direction switch we see a more pronounced overshoot again followed by a one second plus period before the speed settles correctly. The standard leJOS driver starts well and controls the initial speed nicely. However as predicted by the simulation results, there is a large overshoot after the direction switch and this is not very well damped. The new driver shows a small overshoot in both cases, but this is well damped and the correct speed is obtained within about 300ms in both cases.
In this test I used a small collection of spanners (which provide a load of 0.73Kg)! The procedure was the same as above:
This time the Lego driver struggles to control the initial load and oscillates a little before finally obtaining the target speed. After the direction change you can again see the speed oscillating but this time it never really settles. The standard leJOS driver handles the initial load well, after the direction change there is a small overshoot and this is not corrected during the duration of the test. The new driver shows the characteristic initial overshoot, but again this is well damped. After the direction change this is again a small overshoot which takes around a second to be fully corrected. You can also see how the acceleration curve with the current leJOS driver deviates from the other two.
High load test
This test is pretty hard on the drivers. It basically pushes the motor into an almost unregulated state. basically the motor is not powerful enough to maintain the requested speed when lifting the load (which this time is 1.35Kg).
As can be seen the Lego driver really struggles with this load. The initial overshoot and oscillation is pretty bad and it struggles to gain speed after the direction is reversed. I had to modify the current leJOS driver to disable the stall detection system. But once this has been done it makes a pretty good job of handling the load. The new driver has a different stall detect mechanism which this test does not trigger, and other than the initial overshoot the performance is very similar to the current driver.
Variable load and position holding
So far I've not worked out a good way to reproduce the variable load and hold tests with real hardware so I have no graphs for these tests. However I did perform some simple static load, hold tests with some interesting results.
Firstly I modified the leJOS driver to allow hold values other than 30% to be used. This did not work well. It turns out that using values above 30% will cause the built in thermal cut out to trigger which reduces the power supplied to the motor and so the hold no longer works. It is possible to use less than 30% but this just results in a lower holding power.
I also tested the new driver. This uses a different way of performing the hold function. The existing driver has a specific hold mode that basically supplies the specified hold power if the position moves more than one degree away from the hold point. You can clearly see the effect of this in unrollers "LeJOS locking diagram. Variable external load" test which shows the way that this can cause oscillation. The new driver uses the same mechanism as used for speed control to hold position applying an increasing power setting proportional to the error distance and time spent away from the set point. This should in theory produce a best of both worlds with the small errors allowed by the Lego driver being removed without adding in the oscillation, but this has not yet been tested.
This group of tests examines two things. The first is the way the driver handles acceleration from one speed to another, the second is the type of acceleration curve used. The reason why I created the new motor driver was because of problems I encountered when trying to use slow rates of acceleration so this set of tests was particularly to me. The new driver places smooth acceleration as one of the central goals of the design.
Unfortunately the tests below do not include data for the Lego driver. It would seem that with the standard firmware there is not an easy way to control the rate of acceleration (unlike the Java version of the Lego driver tested by unroller), at least if there is I couldn't find it. I think it is possible to do but it requires the user code to closely watch the motor state looking the end of the ramp up state and then switch the state of the motor. Similarly the user code has to decide when to start the ramp down phase used for deceleration.
Acceleration test one
This test simply sets the acceleration to be 300 degrees/s/s and then sets the motor to run first at 300 degrees/s for 2 seconds, followed by changing the speed to 600 degrees/s for 2 seconds finally setting the speed to 100 degrees/s.
The results can be seen above. As predicted by the simulation the current leJOS driver resets and stops the motor every time the speed is changed. The new driver provides smooth acceleration between the selected speeds and the speed control seems to be well behaved. The difference in the two acceleration curves can also clearly be seen. The current driver uses an exponential based curve, the new driver a simple linear one.
Acceleration test two
The second acceleration test combines a series of speeds and accelerations. The initial acceleration is set to be 50 degrees/s/s and the target speed is set to 600 degrees/s, after 2 seconds the acceleration rate is changed to be 300 degrees/s/s then after 6 seconds the target speed is changed to be 100 degrees/s finally after 8 seconds the target speed is set to 600 degrees/s.
As can be seen above the reset of the current controller prevents it from tracking this sequence of accelerations and speeds. The new controller tracks them with no problem.
The original unroller tests did not include any test of positioning. I wanted to evaluate the new code when performing this operation so I've added a very simple test. The motor is simply commanded to move to 400 degrees then after 2 seconds it is commanded to move back to 0 degrees. The default acceleration is used and the speed is set to 600 degrees/s.
The graph above shows the velocity during the move operation. As can be seen the Lego and the current leJOS controllers seem to suffer from overshoot problems and take a while to settle down. The new controller seems to be relatively well damped and moves quickly between the positions.
The final graph shows the actual tachometer counts during the move. Here the overshoot can clearly be seen along with the time it takes the controllers to settle. It can also be seen that the Lego controller seems to be slower to perform the move and does not position the motor exactly to the requested points having a small number of degrees error in the final position.
unroller has added an additional acceleration test to the set he has been using. I wanted to duplicate this and I also added a couple of other tests to explore what happens with lower acceleration. So on to the new test. This test basically duplicates the no load test above but with an acceleration setting of 300 degrees/s/s. So the motor is driven first in one direction for a fixed time, then reversed. As I explained above doing no default acceleration with the Lego firmware is tricky, so I've only run the test on the two leJOS drivers.
As we can see some very bad things happen with the current driver when the motor is reversed. My new driver works fine (and requires no special code to handle the change in direction). The way the current driver operates pretty much matches the predicted behaviour from unroller's simulation. However because of the exponential acceleration curve the current driver did not reach the target speed, so perhaps that could be causing some of the problems? To find out I ran the test again using an acceleration of 500 degrees/s/s.
This time the motor does attain the target speed. But as we can see the problem when the direction changes is still the same. We can also see another problem, there is a spike as the driver switches from acceleration mode to to constant speed mode. This is actually the problem that prompted me to write the new driver, I saw this spike as a glitch in the movement of my robot when driving in a straight line.
Finally I wanted to see what would happen when the motor was under load. So I re-ran the medium load test but this time using lower acceleration figures. I adjusted the acceleration used for the two drivers so that both came up to full speed after approximately the same time (just over 1s). So I used an acceleration of 2000 for the current driver and 500 degrees/s/s for the new driver.
These results are interesting,. The new driver works as expected with nice smooth acceleration in all cases. However the current driver shows the expected exponential curve for the initial acceleration, and the same glitch as it switches mode. However when the drive changes direction something odd seems to happen. We don't seem to be using the acceleration curve at all! However the shape of the plot for the direction switch is different to that in the high acceleration test, so something different is happening.
Position under load
Following further discussion I wanted to explore what happens when moving to a target position while under load. For these tests I used my load test rig, this time raising the 0.73Kg load for a fixed amount of rotation. The target speed was set to be 600 degrees/s and the accleration 300 degrees/s/s. In the initial test the target rotation was set set at 400 degrees.
The first graph above plots the velocity against time during the move. As we can see the new driver acclerates smoothly up until half distance before decelerating smoothly to stop at the correct point (actually the motor stopped at 401 degrees, the small blip seen later is the hold logic correcting this small error). With the current driver the acceleration curve is different as expected. However for some reason the curve does not decelerate the motor to zero and when the stop point is reached the motor is still turning at about 180 degrees/s. The small overshoot that can be seen is probably due to a combination of the stop at position logic and having to apply the lock function once rotation has stopped. The load in this test is such that without application of lock it will cause the motor to rotate. The new driver does not have this problem as the default action at the end of a move is to hold position.
The second graph simply plots position against time. From this we can see that both controllers stop the motor at the correct position. In both cases there is a small error. The current driver stops and holds the motor at 398 degrees, the new driver stops at 401 degrees and later corrects this to 400 degrees.
The next test performs a similar test but this time the target rotation is 2500 degrees. The aim here is to allow the motor to reach the target speed and to provide more time for any integral wind up in the controller to show through. 2500 degrees is the maximum rotation that I can easily achieve with my load test rig.
These results are more interesting. Firstly the new driver performs well. With both smooth accleration and decleration and stopping exactly at the target point with a velocity of zero. With the current driver things are a little more complex. The red trace above shows the results with an acceleration of 300 (the same as for the new driver). Unfortunately this is too low for the exponential curve to reach the target speed of 600 degree/s. Possibly as a result of this we again see that the velocity has not fallen to zero as the end point is reached.
To investigate a little further I re-ran the test this time using an acceleration of 800. This is shown by the yellow plot. This time the target speed is reached. However we can clearly see the glitch caused by the switch over from acclerating to holding a constant speed. In this case the extra load on the motor seems to make the glitch much worse. We can also see a couple of problems as the motor reaches the target. For some reason the deceleration code brings the motor to a halt at 2488 degrees (rather than 2500), this may be related to the previous glitch but I'm not sure. Following this we see a large spike in the velocity as the final position code kicks in and moves the motor on to the correct finishing point of 2500.