Let's Make Robots!

Software speed control

Okay, here's the deal. I am trying to think of a way, to control the speed and acceleration of my robot.


Firstly, what data I will have would be form the encoders and I am also able to control the pwm to the motors. With these I have to tackle two things. Knowing the actual speed and controlling it. andd controlling the acceleration. Details on the gearing and encoders first.

I have a 12 tooth pinion gear on the motor shaft which interlocks with a 48 tooth spur gear with the 30mm wheel infront. As for the encoders, they are 512 clicks per revolution (Faulhaber 1717) . I know the gearing will affect the encoder counts etc, but idk how.. hope you guys can help with that. 

So on to speed.

I have a very very very VERY  rough idea on how to... wait. i dont. hence i need your help :)

As for acceleration. I have a better idea on how to. Using the formula accel = (finspd  - initspd)/time taken

say i want accel to be 5000m/s/s and i know the final and initial speed. Thus I am able to find the time taken. And with that. I divide the increase in pwm (to whatever speed i want) evenly. Will it work or is there a better and more efficient way? 



Comment viewing options

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

I have found (for hobby-style robots) that it is not really needed or easy to keep an eye on your wheel speed(s) whilst also trying to do navigation etc. What I have done in the past is to start with a routine to sync your motors. Before the robot gets into it's main routine, you have it do a series of simple fwd/back moves at different speeds. During this test, the robot can note what PWM "speed" is being sent and the actual speed of the wheel (how many clicks in a given time) is noted as well. From these numbers, you can easily calculate the "offsets" you will need to add/subtract from the motors to keep them going the same speed. The motors I use fall out of sync (one goes faster) more and more as the speed increases so when I do my "syncing" process, I test multiple times at different speeds --I.e. the offsets must be bigger as the robot goes faster. Again, once these offsets are stored in memory, they are simply looked up and added/subtracted to the speed requested when in your main routine.

When you finish this "pre-routine" at the start of your run, you will not need to do it during the "main routine" thus leaving valuable thinking space. Yes, as your drive batteries get low, these values may change and the motors may "fall out of sync" but unless you are doing some hard-core mapping etc. it should not be a problem. This "pre-routine" not only gives you your offsets to adjust the motors, but will also give you good numbers on what PWM duty cycle = what final speed. Now, when you want a given speed, you already have all your numbers --just do a little converting from the numbers and you can project what you are going to need for a given speed.

Now, at 512 clicks per revolution, I am unsure how well your uC is going to keep up. I know that Glen (glena of bahbots.com) has done a lot of work using interrupts for his encoders (instead of watching for the clicks in a regular loop) --and I actually think he uses the same motors. He has had great results, you may want to search his name and take a look at his robot for inspiration.

Im working on a micromouse(think ud know what it is) so the precision is quite needed. Any ideas how?

As for the encoders, I have an external Quadrature counter which is connected through SPI. That is pretty much handled. Im using a dspic so its pretty powerful. I'll be checking out this guy. Seems quite infromative.

"I have a 12 tooth pinion gear on the motor shaft which interlocks with a 48 tooth spur gear with the 30mm wheel infront. As for the encoders, they are 512 clicks per revolution "


To spin your wheel once, the motor has to spin 4 times, and the robot will travel 94.25 mm. In other words 1 motor turn = 23.56 mm

And each encoder click means 0.046 mm (assuming the encoder are attached to the wheel axels)


From experience I recommend only controlling speed, and with what chris said in mind, not using the main mcu to do so (or if you do, use interupts). Very few application require controlling acceleration and speed. Most times, all that is needed is putting limits on the acceleration. Like this:


if |velocityCommand - currentVelocity| /time >= maxAccleration

   velocityCommand = a value closer to currentVelocity


Calculating your current speed is straightforward - sample your encoder count at two points with a fixed time interval between them. The difference between the two encoder count samples, multiplied by your mm/count ratio, gives the distance travelled during that period. Speed is then the distance travelled divided by the sample time interval.

Now that you've got some feedback you can look at controlling your speed. You could build a 'look up table' or formula that generates a PWM duty cycle to suit the desired speed based on empirical data, or you can construct something a bit more robust like a PID control loop. In this case just a proportional loop should work, and you can always expand on it if you need more control.
Building a basic proportional control loop is an easy and tidy way to handle speed control. Subtract your current speed from your desired speed (to get the 'error' signal), and multiply the result by your proportional gain constant (usually called Kp). Add the new value to your current PWM duty cycle value. Repeat the loop every time you calculate one or more new speed samples.

Adding basic acceleration control is easy from here, since your acceleration is proportional to the rate at which you change your PWM duty cycle. After calculating the amount to change your PWM duty cycle by, check if it's within the maximum limit. If the change is outside the limit, set it equal to the limit, then add the value to your PWM duty cycle as per normal.
Most likely you'll start off with no limit, and then bring the limit down gradually until there is no wheelspin/sliding/etc. Likewise your Kp value will mostly be determined by experimentation.