# Motor controller software design

I have to design a PID controller for a differential drive robot.

• The hardware board consists of a AVR atmega168 running at 16mhz.
• Driven by two 24v scooter motors with 256 CPR encoders
• The motors spin roughly at about 4700 RPM and has a 51.56:1 gear ratio

So far I can read the encoder direction and the tick count. But I have no idea how to convert this to speed. And eventually a PID controller. I also want to be able to rotate the robot at a given angle. Can someone please help me to get started ?

Currently I am having problems figuring out a suitable timer calculation for this.

-
well .. you can differentiate position to get speed; if you measure the angle at say, 50 times per second, then you know how far it's turned in 1/50th of a second, so 50 times that would be degrees (or whatever angular unit you use) per second. –  JustJeff Nov 19 '11 at 1:00
change in count/angle over time? –  kenny Nov 19 '11 at 1:02
Are the encoders before or after the gearboxes? (Presumably before, but ...) –  Russell McMahon Nov 19 '11 at 9:57
please break up into separate specific questions –  Jason S Mar 30 '12 at 11:40
For a PID controller: you may wish to read this pair of blog entries I wrote: embeddedrelated.com/showarticle/121.php –  Jason S Mar 30 '12 at 11:41

Thanks everyone for the useful comments.

I achieved what I wanted by implementing a simple velocity PID controller.

Through two interrupts (for each encoder) I calculated how much encoder ticks have been accumulated at a given time interval. The interval i used was 10ms and this was achieved by using the timer compare feature on timer1 of the AVR mcu. Encoder ticks were calculated by taking the difference of the previous encoder ticks and the current ticks. This was then used as the velocity PV of the PID controller. The PID controller sampling rate was also done at 10ms. Just to keep things simple.

I wrote a simple MATLAB gui to graph the SP, PV of the step response of the PID controller. This is how I manually tuned the PID controller. It may not be the best way but certainly the simplest way I could think of to tune the controller.

I will document this on my blog post when I get a chance and will put a link to it on this post so it will be helpful for anyone.

-

Your question is a little ambiguous. Are you asking how to use a timer on the microcontroller, or are you asking how to calculate angular speed given the count from an encoder and elapsed time given by a timer?

The atmega168 should have at least two timers on it. If my memory serves me correctly there are two 8-bit timers and one 16-bit timer. These are integrated peripherals in the micro which can run in the background leaving your micro's CPU free to do other stuff.

One way to do this is: (a) Initialize and start the timer and reset the encoder counter (b) write an interrupt service routine (ISR) that gets called when as the timer ends, restarts the timer, and calculates angular speed. (c) Write another ISR that is triggered by the encoder output tick and that increments a global tick counter. (d) in the timer ISR you know the elapsed time since the last call since when you initialized the timer you specified this. You have the number of encoder ticks since the last timer ISR call. Therefore, you can calculate the ticks per unit time. You should know from the mechanical details of your robot the number of ticks per unit angle of wheel rotation, thus, you should be able to calculate the angular speed of the wheel. Reset the tick counter within the timer ISR after performing the speed calculation so that next time the timer ISR is called you will have the new count of encoder ticks.

This gets you the average angular speed within the timer period. Adjust the period of the timer to work well for your application.

This is only one way of doing this. I can imagine others. I found this algorithm worked well for me before however.

-