So i am working on a bot and am attempting to implement some sort of PID control to match the speed of the wheels in differential drive.
Now, the wheels are diameter 35mm and speeds are between 0-60 RPM. Currently i have encoders on the wheels on either side with 18 state changes on each. My atmega88 polls for a state change and when it happens it increments a counter for each wheel along with the time since the last change in state.
The first approach i took was to run the PID loop each time a click happened and use the time since the last click to determine velocity. Unsuccessful.
the 2nd approach was to run the PID loop a number of times per second and just use that time between PID loops and the numbre of clicks accumulated to figure out the velocity (actually its not velocity, just speed as i dont actually know the direction from the encoders). Anyway both approaches have failed and i can not get this bloody thing to work right. When i want 1rpm the code will send a signal to the PWM that is too low to even move the bot. I think that i may have to create some sort of table because the motors react in a non linear way, ie duty cycle of 30% does not produce 30% of the speed of a 100% duty cycle, etc.
So basically im stuck... with 18 clicks per wheel encoder and speeds of under 60rpm how often should i be running this control loop? i am totally in the dark here, im not even sure how to program it.
as i have it now it goes like this for each wheel
poll encoder and if state changes increment counterA
every 0.1 seconds run PID function
PID function :
avgCounterA = average of current counterA and the previous 4 (as in the CounterA used in the previous 4 PID loops)
//the above line has an array and for loops, etc, to do it right... too long to write here
angular velocity = function of time between PID loops and AvgCounterA
error = wanted angular velocity vs angular velocity
output = oldoutput+ Kp * (error-olderror) + Ki * (error + old error) + Kd* (error - 2*olderror + 2ndolderror)
oldoutput = output
2ndolderror = olderror
olderror = error
counterA=0;
end
i have the average of counterA's because of the very low resolution of the wheel (am i right to do this)
Also i have not used the Integral or Differential code because i cant even get the proportional working right!
anyway, anyone who has ever done a slow robot with low resolution encoder PLEASE opine !!!
should i increase the encoder resolution or can i get away with 18 clicks?
how should i program this?
Oh a note, the range of values i can give the code that does the actual driving is the integer range 0-165, and the output is treated later to be within that range.
this may be too much to ask, but if someone has done something like this already, what is the chances of me seeing the code?
thanks so much