Random header image... Refresh for more!

Stop! Stand there where you are, before you go too far…

I spent some time last night diving back into the world of Lego Mindstorms, trying to solve one of the outstanding problems from the Pong Robot that I built a few weeks ago.  If you recall, one of the biggest problems I had was with precision movement of the servo that was rotating the paddle knob.  It would consistently overshoot the mark or simply not move at all.  This was very frustrating, and I tried several different movement techniques before coming across one that worked well enough…  Until I recharged the batteries.

One of the problems I had was that I couldn’t tell the motor how far to rotate.  I had to tell it to turn on, then, sometime later, tell it to stop.  This meant that processing delay could have been the cause of most of the overshoots.  By the time the stop message had gotten to the motor, the paddle had gone too far, leading the movement processor to send a command telling the paddle to move the other direction, where it promptly overshot the mark heading in the other direction.  What I needed was to tell the motor exactly how many degrees to turn.

Now, I tried the degree method before, sort of.  Unfortunately, I was limited to fixed angles that were set up in the Lego Graphical Program that I wrote (If you can call drag and drop programming “writing”…), so it didn’t end up working that well.  In general, it overshot worse using these angles.  And movements got stacked up in the queue, so it kept moving long after it should have stopped.  All in all, a failure.

I eventually bypassed the program altogether and moved to using the Mindstorms Direct Command API, which lets you send commands to the NXT over Bluetooth.  Using Direct Commands, I had slightly more control over when to start and stop, although the primary benefit was turnaround time.  All of my logic was centralized in the same C# application, rather than being spread between C# and the Lego Graphical Program.  I could tweak a setting and run and see what it did, rather than drag a couple of program bricks around, redeploy, run the program on the NXT, then run the desktop app, only to find out it didn’t work at all.  However, what I didn’t find was any way to provide a movement angle at all.  There were all sorts of settings, like power, braking mode, even some used for twin motor locomotion.  But no “rotation angle”.  So, I made do with simply adjusting the power.  The “success” of the robot was less a factor of going where it was supposed to go than luck in having it correct from its mistakes fast enough to hit the ball.

Obviously, luck wasn’t going to cut it.  The robot would perform reasonably at the standard speed, but as soon as you bumped up the speed a notch, it didn’t stand a chance.  I could tell that it would have problems if I wanted to expand to games like Breakout, where the speed is variable in normal play, and there was no way that the current movement would work for games like Kaboom!, where you have to have pinpoint movement control and be thinking five moves ahead to have any kind of hope of survival.

Yesterday, I decided to look at the problem again.  In reading what other people had written about the Direct Command API, I discovered that the semi-obscurely named “Tacho Limit” parameter that I’d been ignoring was actually the number of degrees to rotate with the movement command.  Great!  That’s precisely what I needed.  Except for the minor fact that this Tacho Limit was obeyed like someone on a crotch rocket obeys the speed limit.  Somewhere around the Tacho Limit the motor would sort of decide to stop moving, but would then coast for another random length of time.  At full power, this random length of time tended to mean somewhere in the neighborhood of 720 degrees.

Two full revolutions past the mark is not my idea of precise.

And then, on top of that, there’s a counter in the motor that keeps track of how far you’ve wanted to go and how far it’s actually gone and won’t move again until you’ve told it to move past where it landed.  Which means, if you tell it to rotate 360 degrees, and it goes 1080, the motor won’t go anywhere at all until you’ve told it to move more than the difference of 720 degrees.  And then, it only travels the difference over the error.  So, needless to say, quite frequently, I was telling to move and it refused to go anywhere, and when it finally did decide to move, it didn’t move anywhere near the distance I wanted it to go.

Basically, I would have gotten more precise movement if I’d handed the paddle to a three-year-old that I’d pre-loaded with PixyStix.

I don’t understand it.  I’ve seen the motor move fast and stop with such force that the entire assembly shudders.  Why is it just gradually coasting to a stop now when it should be moving precisely 30 degrees.  Not 34, not 37.  30.

I’m back in the graphical environment now, trying to drag and drop a program that’ll give me more control over the rotation, but which will hopefully cause the motor to actually stop when it’s supposed to stop.  I’m debugging using a happy face icon and a bunch of sleepy ZZzzzs.  This is all I will ever be able to think about the next time someone tries to show me a UML diagram.

And speaking of stopping, I really need to stop now, given that I happen to have something that could be described as “work” in the morning.   Just like the motor overshoot, this could easily continue for another hour or two if I let it.   When I’m half asleep at the morning meeting, I don’t think the excuse “I was playing with Legos all night” is gonna fly…


There are no comments yet...

Kick things off by filling out the form below.

Leave a Comment