Monday, August 21, 2006
DC Motor Programming Madness
Example Computer output to Comms/PIC:
Each line here represents a 'job' in this program
(X movement, Y movement, Speed (in pulses per second)
All this data is in Pulses. Software translates positional data to # of pulses needed. On DC motors each pulse represents an encoder slit.
RepRap Variables in this example, mostly generated from original vector coords=
JobX=200 ' how far to move on X
JobY=50 'how far to move on Y
TotalTime=200 'Total pulses needed for the job. (Always equals largest absolute value of jobX or jobY)
Time=0 'current pulse # in job
dX=0 ' desired pulse position in job
dY=0 ' desired pulse position in job
X=0 ' actual position (in pulses)
Y=0 ' actual position (in pulses)
(Keep these in buffer so it knows what is up next. So it can prepare speed changes beforehand:)
RepRap Pseudo-IO in this example:
XmotorPWM, sends a 0-100% duty cycle for motor X
YmotorPWM, sends a 0-100% duty cycle for motor Y
Example Settings for the equations below:
Speed=100pps (speed in desired pulses per second)
MaxSpeedX=200pps (speed of motor at 100%PWM)
MaxSpeedY=200pps (speed of motor at 100%PWM)
Overshoot=9 (average overshoot in # of pulses at 100%PWM)
Correction=20 (1-100, represents rate of per-cycle motor speed corrections.)
Every Predicted Pulse (On PIC would be every (1/Speed) seconds. In example it is every 1/100th second)
dX=JobX * (Time/Totaltime)
dY=JobY * (Time/Totaltime)
XmotorPWM=(Speed*(JobX/Totaltime) /MaxSpeedX). Will return 0-100% for PWM speed. Needs to be modified in case it falls behind/ahead.
XmotorPWM=(Speed*(JobX/Totaltime) /MaxSpeedX)+ ( (dX-X)/100 * Correction ) Correction=10 will modify the motor by 1% per pulse
Now, to account for next-job-speed-prediction, you need to modify it further when it nears the end of it's job:
if Time >= Totaltime - ( Overshoot * (Speed/MaxSpeedX) ) then
Calibration needed to make it work:
MaxSpeedX,Y (total pulses measured after 1sec full-speed movement)
OvershootX,Y (overshoot measured in pulses, from going 100% to 0%
Correction (value from 0-255, sets the ferocity in which motor speeds are adjusted to keep it within its desired position. 10=1% correction, 100=10%, etc)
Programming note: The extra variables in memory like dX and dY can be trimmed out and replaced with more equations, I just used them to make it look nicer.
Other Programming note: Murphy's law dictates there is at least one malformed equation in a pseudoprogram this long.
I hope some of this makes sense. Again, I mostly wanted to show that it was possible to have PWM control with dynamic adjustment of speed to keep in-line with pulses just as a stepper motor would. That, and being able to change speed a few cycles early, using the difference in speeds and a set ratio to determine how early to change.
I remember digging into 6502 assembly and figuring out how they did the floating point operations years and years ago (I was just a kid at the time). Pretty amazing work. It seems you see less of that kind of engineering, and more dependance on faster hardware and more memory these days.
Links to this post: