PID Motor control using Baby-O

Hello,

I am quite new at this so I would like some advise on the following. I have a Baby Orangutan B-328 Robot Controller in a micro robotic project and I want to implement a PID motor control using the encoder and motor functions from the Pololu AVR C/C++ Library. for feedback I am using a 60-slot encoder and the Hamamatsu P10210 differential encoder module. For motors I am using the Solarbotics Planetary Gear Pager DC Motor.

Do you ave any examples or even better ready code on how to do that?

Any help will be valuable…

Thx
Akis

Hello,

You could try using the code in the Pololu Wheel Encoders section of the Pololu AVR Library, which should work up to a few kHz. We provide various functions for tracking the counts and an example application, but the PID is going to be up to you to implement.

-Paul

Hello again,

First of all thank you for your answer to my request. Now there are 2 ready made PID implementations that I could use as a guideline and these are:

  1. uoxray.uoregon.edu/orangutan/#PID_code (a PD implementation for the ATmega8 controller using GCC)
  2. AVR221: Discrete PID controller on tinyAVR and megaAVR devices (a PID implementation using the IAR compiler)

I am using the GCC (utilizing your library). Which one of these two would you suggest is the most proper one to start working with?

Thank you again,

Akis

Hello,

We actually have a PID example for the 3pi robot that uses the AVR Library and might be a better starting point for you. It is designed for line-following, which is not what you are doing, right? But there is really not much to PID itself if you know how to control your motors and read your sensors, so I think you will be able to modify that code to do what you want. I do not really know what you want to do with PID, so I cannot say much more than that.

-Paul

Ok I see… Thank you very much Paul… I have a few ideas in my mind on how to use a time interrupt in order to have regular motor speed updates. I am a little bit confused in motor speed transformations but I will find it eventually… :slight_smile:

In any case thank you for your time.

Akis

Ok I have done some research and programming and I am thinking to implement a Timer1 interrupt (does not conflict with Pololu library) to have regular updates of 100ms period and control the speed of DC motor. However, I am a little bit confused with the transformations and scaling (CPS to PWM). Because of this I the following more specific questions:

According to the DC-motor datasheet at 3V-160mA (about 160 PWM), the motor gives me a 850rpm (rated values). In my robot configuration, I have a 9/60 reduction gearbox arrangement, which gives me a 128 rpm of the wheel and a 128 cps (7680cpm) of the encoder attached to the wheel. I need to operate the motor between voltages 1.34V to 4V (70PWM to 210PWM). Now for Tsample=100ms interrupt period, I have calculated the MIN_PULSE=6 at 70PWM the MAX_PULSE=17 at 210PWM. My question is this:

  1. I see that I have quantization errors. Shall I a) control the drive command motor PWM value directly with PID using PWM reference values or b) control drive command motor PWM using Target_encoder_count reference values?

  2. Do you think a 60-slot encoder provides adequate resolution for this kind of PID implementation?

  3. In case b) is the Count to PWM transformation equation something like this: PWM_value= ((Target_encoder_count *MAX_PWM)/MAX_PULSES)/100

  4. In case a) is the Count to PWM transformation equation something like this: PWM_value= ((Wheel_encoder_count *MAX_PWM)/MAX_PULSES)/100

Thank you for your time,

Akis

Hello,

I do not understand all of what you are asking - you seem to be referring to variable names like “MIN_PULSE” and “Target_encoder_count”, but I do not know where you are getting those. Are they from some example code somewhere?

Also, I do not think that the expressions you have in questions 3 and 4 represent anything that would be called “PID”. What would correspond to P, I, and D in those equations?

-Paul

Ok let me rephrase it!

According to the DC-motor datasheet at 3V-160mA (about 160 PWM), the motor gives me a 850rpm (rated values). In my robot configuration, I have a 9/60 reduction gearbox arrangement, which gives me a 128 rpm of the wheel and a 128 cps (7680cpm) of the encoder attached to the wheel. I need to operate the motor between voltages 1.34V to 4V (70PWM to 210PWM). Now for Tsample=100ms interrupt period, I have calculated the encoder MIN_PULSE=6 at 70PWM the MAX_PULSE=17 at 210PWM. My question is this:

I see that I have quantization errors. Shall I control the drive command motor PWM value directly with PID using PWM target command values? In that case tha PID loop would be:

PWM_measured_value= ((Wheel_encoder_count *MAX_PWM)/MAX_PULSES)

error=PWM_target_value-PWM_measured_value

integralPart = integralPart + error;

if(integralPart > antiWindUpLimit) then
integralPart = AntiWindUpLimit;

if(integralPart < -antiWindUpLimit) then
integralPart = -AntiWindUpLimit;

actuatorValue = actuatorValue +pGainerror + dGain(error - previousError) + iGain*integralPart;

setActuator(actuatorValue);

Do you think a 60-slot encoder provides adequate resolution for this kind of PID implementation?

Thank you,
Akis

Hello,

I still do not think you have PID right. Are you copying this from some example code somewhere?

-Paul

Hi Paul,

Well I have searched in various resources like this PID document:
dprg.org/tutorials/2003-10a/motorcontrol.pdf

I believe that the PID loop I am stating in my previous message is correct. What I am not sure, is if the equation to translate measured encoder pulses to PWM speed ( PWM_measured_value= ((Wheel_encoder_count *MAX_PWM)/MAX_PULSES) ) is the proper one, or if it’s better to implement something else. Furthermore I am not quite sure if the 60-pulse resolution encoder could provide me adequate PID speed-control in my situation.

As for the MIN_PULSE=6 at 70PWM the MAX_PULSE=17 at 210PWM values, my calculations were the following:

At 3V from motor datasheet and due to reduction gearbox (9/60) I have:

9*850rpm/60= 128rpm

Moreover, at 3V I have a 160PWM command value. Now I calculated the encoder counts per minute at 128rpm as follows:

128rpm * 60counts(encoder resolution) = 7680cpm= 128cps

Having a sampling period of 100ms=Tsample, at 4V we have:

(4V*128cps)/3V=171cps

and one count takes:

1/171cps =5,85ms

for the Tsample period of 100ms I will have:

100ms/5,85ms=17,09 ~ 17 encoder counts, which is the MAX_PULSES!

Please let me know of what you think,

Thank you,
Akis

Hello,

I do not think that is a particularly good example to follow (did you look at the one I linked you to?), and I think you are fundamentally confused about something starting with your first line:

Why are you calling something a “PWM measured value”? You know what the PWM value is - it is whatever you set it to. What you measure with the encoders is the speed of the wheels. So you should instead be doing something like

error = Wheel_encoder_count - target;

You should set the target to the number of counts that you are trying to achieve per cycle - this calculation that you keep posting about how PWM corresponds to speed is not relevant, because the whole point of PID is to automatically adjust the PWM to get the speed you want, not to use a pre-computed PWM value.

The other thing that I do not like about what you are doing is that you are integrating an extra time with

I think that you just got the from the example - I recommend taking out the “actuatorValue +” part unless you really know that you need it.

-Paul

Ok… now I am getting it… :))

Thank you Paul!