Let's Make Robots!

What do you like in a SOFTWARE Motor Controller?

CTC & I were shouting and the topic came to smart motor control.  Strangely, I have was working on a motor control software interface, and thought, what a great opportunity to ask, "What would you desire in motor control?"

My interface commands currently looks like this :

  • attach (controller, directionPin, powerPin)  - attaches the motor to a specific power & direction pin on a controller
  • detach () - detaches motor from controller
  • move (speed) - speed is a float  1 <-> -1, 0 being stopped, 1 to -1 so that all motors have a concept of full tilt = 1 and full tilt in the opposite direction = -1
  • moveTo (position) - this will be controlled by a feed back device (encoder, halls effect, etc) - position is absolute
  • incrementSpeed(value) - allows you to speed up or slow down an incremental value +/-
  • incrementPosition (value) - allows incremental moves to position
  • stop() - stops motor 
  • stopAndLock() - stops and locks motor, so no other commands can affect it until the lock is removed
  • unlock() - unlocks motor

It supports 2 bit motors (heh).
There are 2 simple ways to make h-bridge controllers for motors

  • smart H-Bridge is where 1 line control power (pwm typically) and 1 direction
  • the other is Burnable - where 1 line controls each side of the H-Bridge - setting both bits/lines on will give you shoot through - not the best hardware solution, but if used - your software should never allow the "smoke" condition

I thought about adding ramping - but have not implemented it yet, something where you set the ramping parameters and enable it so that all other commands like "moveTo" do ramping if setup once.

What do you think?  Got a good idea?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Performance, feedback, revision.

I have been thinking about this one and robots and Walter and the whole idea of a "rebuild". I have also been thinking of the idea of "skipping ahead" --One is asking about step 487 when on step 3. Add to that more thoughts on good code. One mark of good code is how universal it is. If pin numbers are declared in the beginning as variables (or constants) instead of calling the actual pin number when it is needed, another user can more easily swap out his pins for yours rather than going through all the code to change them individually. Same goes for threasholds (i.e. sonar danger zones) etc.etc. Good code can also deal will all kinds of data coming in and even funny data including stuff that is formatted wrong or missing a byte or does not pass a checksum.

Move on to foundations. When building a house, each thing added to the build is indeed added to what has already been built. If the foundation is crooked, the floor is crooked or you must shim and adjust the next level to deal with the mistakes of the last level. This rings true with robots (and skipping ahead). Although I have not "skipped ahead" much myself, I am finding more and more that as I added more layer of code to say, Walter, I without knowing it, had been shimming and adjusting a lot of stuff to deal with previous layers that were not exactly plumb, level and square.

Lastly, add a 1977 Toyota Landcruiser FJ-40 with a Chevy 350 V8 stuffed inside. I had one and I converted to the small block Chevy after rebuilding this motor (from a bare block). I reused the stock radiator and had overheating problems... or so I thought. I kept seeing the stock toyota guage (now connected to the chevy motor) and it was indeed, higher than normal. I flushed the radiator, changed thermostats, adjusted timing and even removed the vacuume advance from the distributer. All had little or no effect on the overheating. After weeks, a moment of clarity hit and I realized that while it was hotter than "normal", the toyota really only had an "idiot" guage which is a guage only having H and C and lacking any numbers. It was in this moment of clarity that it finally clicked: I have no idea if this engine is hot or not. I have no guage with degrees on it! I have been revising and revising with no feedback --or-- with feedback that didn't really relate to anything. 18 bucks later, I had an after-market guage installed (with degree markings) and quickly found that yes, the engine was running hot, but only 6 or 8 degrees higher than "normal". --A systematic, step-by-step approch, with good data is what solved my problem.

Back to robots. The more my code gets complex, the more I find I need solid (TRUSTABLE) numbers from one of the previous "layers" of the code. Some of these layers were written long ago, the data is very stale and it is simply "assumed" that these old layers are not overheating. Then again, I have never attached a guage to many of them.

I am starting over. I am going through all of my sub-systems and rebuilding from scratch (in terms of software and sometimes hardware) and while rebuilding, gathering (and properly recording!) good, solid data. During this rebuilding and testing, my goal is to not move on until I am confident that each "layer" is as solid, bug-free, universal (to be easily added to any code), plumb, level and square. Right now I am back to encoders. I will use this as an example of what I have been talking about and what I am working with now.

I am working with only one GM-x motor and one encoder. First off, the encoders. I spent about 3 hours just working on the pull-up resistor. I want a solid 1 or 0 with a good low and a nice high. I attached a measure thingie as well as a debug (serial monitor) and checked and rechecked. Only after 3 or 4 hours was I truly happy with the value of that one resistor however, the testing was not done. I moved on to Frit's audio o-scope and checked the pattern. Well, it was not exactly a row-of-top-hats square wave, but I was able to see the length of each pulse (and I was happy enough with the wave-form). I used this information to adjust the width of the reflective segment of the gear that is being "watched". I re-confirmed that my pulses were even with a pulseIn command. Then I started putting "batches" of pulse readings together, averaged them and checked the data again. I wrote all of this information down, neatly on paper including the resistor values, pulse widths, etc. etc. etc. In the end, now, I have a paper with some of the most solid numbers I have ever had. The hours of testing I put in, led to the confidence that I can build on these numbers, anywhere with any code and they will remain solid. I should not have to shim or adjust anything that is build using these numbers, period.

Already, I am enjoying the fruits of my labor: For fun and just to get an idea of how it would work, I wrote some test code to see if I could maintain a speed (to be later used to "balance" the motors). I added a pot to the motor so I could manually reduce the speed and yes, the motor is small and the plain-jane radio shack pot handled it with no blue smoke. As I forced the motor to slow, the code noticed the change and adjusted the PWM to compensate. It worked great. It was also coded very easily in the fact that I was building on such a solid foundation. Again, my earlier tests and data were solid and trustworthy and I built on them with ease and confidence. Actually, with this data, I was able to quickly notice that the reaction time of my "keep an even speed" code was not what I wanted and that it would work better if I had 4 white stripes for my encoder to watch rather than my current 2. I made this change and again, found it super easy to adjust my data, retest and was left with data as good as I had in the first place. --The time I put into the foundation, I have already gotten back. It seemed kinda silly to spend 3 hours picking one pull-up resistor, but without doing so, and having such clean 1's and 0's, I would not have clean pulses to check etc. etc. etc.  --Gotta slow down to speed up.

To the point of the motor driver. To me, I think the features and systems I/we will use on this motor controller will become clear as I work to the final goal. Really, this is a lesson of life: Be here now, enjoy the moment, live in the moment etc. etc. As with everything, you want to see the final product and always want to get to the next step. This is why most paint jobs look like shit --no patientce to wait for each coat to dry and no sanding between coats. Painting is a good example as painting is 80% prep and 20% moving paint. It is only the prep (that you never really see) that leads to a kick-ass finish that you do see.

This is my new thought process. I don't think I am going to be "adding more" to anything I got going right now. I think I want to back up to the beginning again and do it all over... right this time.

Whew....

I definitely would like to see the ability to accept inputs from an encoder with the aim of treating a motor like a servo. Tell it what position you want it to go to and have it's speed ramp down as it approaches. The ability to check limit switches would also be required. Note that the encoder could be a quadrature encoder or a pulse encoder that relies on the software to know which direction the motor should be turning in.

Here is what I've been experimenting with my own MotorController.

I wanted a controller that would deal with the motors just like a lower spine, so the brain go about doing it's more complicated stuff (image processing, mapping, etc.). After thinking what I would like a motor controller to do, I came up with this list:

  • execute received commands 
  • report status when asked - collisions, power, working, arrived at destination, etc
  • keep track of traveled distance - in roaming mode
  • monitor a close proximity area (collisions) - bumpers, IR proximity
  • monitor power (voltage, current) - to detect stall or free wheel spinning (lost contact with the ground)

I thought it should have precise command mode and a roaming mode, so I came up with this commands list:

1. precise commands:

  • Forward(setSpeed, distance)
  • Reverse(setSpeed, distance)
  • Left(setSpeed, angle) - turn in place
  • Right(setSpeed, angle)
  • ArcLeft(setSpeed, angle) - turn with a large radius, or spin around a stopped wheel
  • ArcRight(setSpeed, angle)

2. roaming mode:

  • Drive(speedLeft, speedRight)
  • Turn(speedLeft, speedRight)

And the general commands:

  • Stop()
  • ReportDistance()
  • RepostStatus()

The motor controller should use PID to make sure the wheels turn with the same speed so the robot drives straight (in precise command mode) and use a Trapezoidal control mode that ramps up to the setSpeed, drives until close to distance, then ramp down until the distance is reached and stops there, same for turns in place. The trapezoidal control is a mixture between ramping and PID control. Also, the controller should check an external I2C compass sensor to check the turns and heading (driving straight) as there may be uneven ground (look at PatrickMcCabe's code for his AWD bot).

The roaming mode would just set the motors to go and keep track of traveled distance. A ramping up to the set speed would be nice too, to reduce the wheel slippage. The Stop command may initiate a ramp down in this mode.

Ok, this sums up what I've been thinking. part of it I implemented already, part is in the works. Any thoughts?

Sometimes it takes me a while to catch on, but I think I asked the wrong question.  I asked the same question 2 years ago, and I have been really excited about the outcome.  The results were a plethora of great designs, with the BOA-Robologist MOD being a sweet spot of simplicity, few parts, great power and small expense.  We have all benefitted from this collaberation of knowledge.

What I really want to be asking this time is :

Now that we have several great DIY hardware designs, what would be the ultimate software design?

I am searching for a standard which will have a similiar "sweet spot" of ease of use over flexibity, control, & complexity.

Standards can be very desirable, as CTC pointed out - what if everyone had a standard for servos - then I wouldn't have to slice & splice servo wires for boards that don't have the 3 pins in the correct order.

Imagine what you would desire, without the context or syntax of a language to muddle things up.  The example I was giving may be a little Javasque but all languages could support it of some form.  Arduino has a "Servo" object but no "Motor" that I know of at the moment.  So I'm not interested in the specifics of the language, but of how the perfect Motor interface should look.

What things would you want it to support? Ramping?, attaching a feedback device for positioning? Safety? Angles?  What would be the notation to make it simple and intuitive?  If we have some form of standard then the motors and different software has a better chance of being modular & swappable for different applications. Walter might not suffer as much when upgrading his brain.  We might be able to exchange software and have it work without re-writing everything.  Just a thought.. 

Are we talking about a motor controller that most people are likely going to be needing? Or one that can accomodate all desires?

Never mind. I am working with a cool (...) motor controller right now: the Wild Thumper controller. It has the ability to speak different serial languages. Each "mode" (RC, I2C, RS232, RIK434) is a plugin routine. User chooses which mode to use. It does a few things very well:
- PWM two motors in two directions (full H-bridge per motor)
- monitor battery voltage and motor currents
- reporting back to main brain (all there is to know, or specific metrics)

It exposes enough arduino pins to add more functionality. That makes it a nice compromise between 100% DIY and 100% ready made. Things I would like to add:
- simple feedback: just angular speed by some encoder, direction not needed, I know what direction I ordered it to go
- fancy feedback: absolute angular position by a HES reading a magnet (read supermodified CR servo)
- changing the PWM frequency (singing DC motors are all the rage)

That is in no way the answer to your question. Apart from the requirement for hackability. Without the requirement that the user should hack anything to get some basic functionality.

Great idea and intuitive too. Maybe for security reason a watchdog timer would be great, when using an extra hardware motor controller. To stop the motors when the main controller failed. Of cause this is not needed on a software controller.

What about a turn(degree) command? To turn the robot on place at a given angle. Maybe too complicated, because the controller needs info about wheel diameter and wheel distance from mid point.

I was just going to post the exact same thing!

I am curious to see how this conversation goes, I am just now working on my flow-charts of how the control "system" will work.

I would like to use the smallest amount of sent data to get the biggest bang. I.e. if I want the motors to ramp-up or ramp-down to speed, I don't want the main brain controlling that, instead I just want to send R:ramp_speep:total_speed and "GO". That is 4 bytes to send and the main controller can then forget about the whole thing while the motor controller chip takes care of the ramping and maintaining the desired speed. Also, there is of course the question of how much you want to have the motor conroller talk back to the robot brain.

I am excited about this one. All the serial motor controllers off-the-shelf suck and I do not like thier command system --I am stoked to build both hardware and software to exatly my wants.

I thought they might be intuitive, but my intuition often is completely "wrong"....

"I am excited about this one. All the serial motor controllers off-the-shelf suck and I do not like thier command system" - why?

I'm trying to make an interface which would still be effective/intuitive/powerful for someone who didn't know all the details yet (4 bytes here, 4 bytes there...)

So, imagine you were not the bleeding edge robot builder you are, and you just got thrown software that controls a motor ... what would you expect/like ?