PID

QuIcK

Senior Member
Yes, im mad and crazy.
but I have implemented a very basic PID loop to control the position of a motorized P&G fader (PGFM3200).
Code:
setfreq m8
symbol kP = 40	'/20  gain of 2
symbol kD = 10	'/20  gain of 0.5

symbol correction = w0
symbol PrevErr = w1
symbol Err = w2
symbol ErrSum = w3
symbol temp = w4

'where we wanna be
symbol target = b20

'just to make it do something
symbol counter = b21

'setup pwms
pwmout c.1, 49, 0
pwmout c.2, 49, 0

target = 0

start:
'something to make it move
inc counter
if counter > 128 then
	target = 220
else
	target = 100
end if

'get current position
readadc 0, Err

'calculate error
Err = target - Err

'proportional
correction = kP * Err 
correction = correction / 20

'differential

temp = PrevErr + Err
temp = temp * kD
temp = temp / 20
correction = correction + temp

PrevErr = Err

temp = correction MAX 200 'correction modulous

if temp > 8 then 'stops low level movements
	if correction > $1000 then 	'negative correction
		pwmduty c.2, temp
		pwmduty c.1, 0
	else
		pwmduty c.1, temp 'positive correction
		pwmduty c.2, 0
	end if
else
	pwmduty c.1, 0
	pwmduty c.2, 0
end if
goto start
this runs fairly well on 8mhz 28x2. however my h-bridge keeps on overheating... i think its because of the pwm frequency, but my pic squeels if i lower the pwm frequency.

its a bit sluggish around the target area. this is because the integral term is missing. however, the integral term didnt work at such low sample rates, creating oscillations.

First off, any optimisations or improvements? to make it run faster at 8mhz

most importantly tho, where can i find a 40mhz crystal to clock the 28x2 up to its potential?
 
To clock it at 40MHz you need to have a 10MHz external resonator, not a 40MHz. The X2 chips have an interal x4 multiplier, that's why. You can find them in many places, futurlec for example (go for the three pin ceramic resonator version, that way you won't have to add capacitors to the crystal)
 

eclectic

Moderator
Last edited:

QuIcK

Senior Member
oh yeh, now i remember about the pll.

@ Andrew: nope, picaxe is wired straight to an L2930, which is, in turn, wired to the motor. is a driver required?

just purchased a resonator. cheers for that!
 

QuIcK

Senior Member
ok, 10 bit version. with a few more comments. It seems to be constantly overshooting by 8mm, but it corrects to +/- 1.5mm (ish) which is a 3% accuracy on a 100mm fader. As this is more of an indicator than an actual signal controller, 3% accuracy is fine for my purposes.

If anyone has suggestions to reduce the overshoot, i'm all ears.

Run on a 28X2 with 4mhz ext clock (16mhz)
Code:
setfreq em16
symbol kP = 7	'/10  gain of 2
symbol kD = 5	'/20  gain of 0.25
symbol kI = 10	'/20
'(kp/kd/ki)
'20/0/20 FOR 8BIT
'12/0/5 for stable(ish) 10 bit
'7/5/5 med overshoot, 2mm accurate
symbol correction = w0
symbol PrevErr = w1
symbol Err = w2
symbol ErrSum = w3
symbol temp = w4
symbol dir = w5

'where we wanna be
symbol target = W6

'just to make it do something
symbol counter = b21

'setup pwms
pwmout c.1, 39, 0
pwmout c.2, 39, 0

target = 0

start:

inc counter
if counter > 128 then
	target = 735
else
	target = 100
end if

'get current position
readadc10 0, Err

'calculate error
Err = target - Err
'store direction for later
dir = Err
'make the Err positive only (2s compliment)
if Err > 512 then
	Err = not Err
	Err = Err & $3ff '$ff 'for 8bit
end if

'proportional
correction = kP * Err / 10

'differential
temp = Err + PrevErr
temp = temp * kD / 20
correction = correction + temp

'integral calc. Changed to average error to reduce oscillations
Errsum = Errsum + Err
Errsum = Errsum / 2

'intergral
temp = Errsum * kI / 20
correction = correction + temp

'differential calc
PrevErr = Err

temp = correction MAX 160 'max pwm value
'uncomment to reduce low level osc
'if temp > 5 then

	if dir > $1000 then 	'negative correction
		pwmduty c.1, temp
		pwmduty c.2, 0
	else
		pwmduty c.2, temp 'positive correction
		pwmduty c.1, 0
	end if
'else
'	pwmduty c.1, 0
'	pwmduty c.2, 0
'end if
goto start
there are some big improvements over the 8bit code. mostly, actually using negative numbers. I think thats why I had a lot of trouble tuning the PID.
I have left in the code to change it to 8bit, however the errors etc need to be Words in orderd to have 8bit accuracy, with negative numbers (-255->255). with some changes, it could run on Bytes, but the accuracy would drop to 7bit which could have disasterous effetcs.
 
Last edited:

QuIcK

Senior Member
Im trying to get this to work with the hpwm command to use with a 20x2 (cheaper chip :D)
The documentation is a bit unclear, and I cant find the "hpwm tutorial" that is referred to. I searched the forum, but nothing came up that made sense.

it looks to me like you can only set the duty cycle on the fly, and not which ones are driving, unless you need to re-set the hpwm?

how would i use the hpwm and hpwmduty to control a motor bidirectional with speed?
 

hippy

Ex-Staff (retired)
Microchip's 18F14K22 has a section (13.4) on Enhanced PWM which is perhaps the best reference for using HPWM to drive H-bridges directly using a 20X2.

I don't have any experience of PID so cannot comment on this particular application.
 
how would i use the hpwm and hpwmduty to control a motor bidirectional with speed?
Just an observation, by going bidirectional then your 10bit accuracy goes to 9bits in plus minus direction. You would control direction in software presumably at the midpoint reading of 512. And preferrably with an off time of some 10's of milliseconds when transitioning between directions.

Know little about PID either, but shouldn't some sort of sample period (pause) be instituted, like say X number of ms? Do not know what the execution time of the maths may be, so may not be a problem. In other words, the feedback loop never gets resolved and the HPWM (and driver chip) is switching all the time, not good, and will create heating.
 

QuIcK

Senior Member
the driver does get toasty! might have a look at that.
the adc is 10-bits, but the variables are 16. theres 6 bits there not being used by the adc, so i could use those 6 bits to describe its direction in 4d-space/time.

cheers, hippy. ur a legend, I think i have it sorted now!
 
the adc is 10-bits, but the variables are 16. there's 6 bits there not being used by the adc, so i could use those 6 bits to describe its direction in 4d-space/time.
Aha, I stand corrected, didn't think about the overhead available and software intervention.
 
Top