Monday, August 21, 2006


DC Motor Programming Madness

I have here a pseudo-PIC program for driving a DC motor using PWM and an encoder. This non-working example might serve as a base for an all-out DC driver. This example has overshoot prediction and dynamic speed-adjustment for correcting tiny errors. I Apologize for this disjointed posting.. can never seem to post programming related material without it becoming a bit chaotic.

Example Computer output to Comms/PIC:
Each line here represents a 'job' in this program
X+200,Y+50, 100
X+100,Y+50, 100
X+10,Y-10, 100
X-20,Y+50, 100
(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
XmotorPWM=(NextSpeed*(NextJobX/NextTotaltime) /MaxSpeedX
end if

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.

Have fun.


This comment has been removed by a blog administrator.
Biggest problem you'll have in pic code is multiplication and division. This is difficult to do in limited memory and instruction space (And very inefficient, to boot -- division of 16 bit integers will probably need to execute on the order of 200+ total instructions to perform the calculation.)

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.
Post a Comment

Links to this post:

Create a Link

<< Home

This page is powered by Blogger. Isn't yours?

Subscribe to
Posts [Atom]