Like you meen I was rewrite
Hi Henrik,
Yes I was today put all in one interrupt (TMR1 , 16bit and make little trick)
Interrupt fire at 10KHZ but I have counter variable wich increment every interrupt jump and if it not 10 then servo not operate over jump servo and pwm update but when that variable mach 10 servo will operate and reset variable to zero, that meen I have 10khz interrupt with 1khz servo drive.
After that all work almost perfect but problem is still here and maybe it is in PWM update or I don't know - simple I am near it.
We will see soon...
Regards
/Robert
PID with no negative values
I need to get a simple PID application going using a PIC, and this PID include looks to be ideal for what I need to do.
The system I'm working with doesn't incorporate an output device that accepts a direction bit. Everything is a positive variable i.e. the setpoint value, feedback value, and the output to the process (a value that I'll plug into a hardware PWM channel). Specifically, everything operates within the span of a WORD variable, 0-1023.
If I'm properly interpreting how the routine works, I'll need to edit the include file to make the sign indicator passed to the include, currently B.0, a bit variable, and then do a sign determination in the main calling program to indicate if the error signal that I pass to the PID sub is below or above the setpoint.
Likewise, I'll need to take the output of the PID include that gets passed back to the main process, and add/subtract the new output with the last output based on the direction bit, currently B.15.
OR
Can I simply make the direction variable passed to the PID a constant 1, and ignore the sign information returned from the routine?
OR
Do I have this all wrong?
Thanks in advance for the help!
Mike
1 Attachment(s)
New version of incPID available.
Hi,
First, bugfix....
I've discovered a bug/problem with the original incPID routine. When there's a persistant error present at the filter input the integrator for the I-term is supposed to accumulate and over time produce an output that will drive the error away. However, a small error in conjunction with low I-gain may actually never accumulate enough to produce an output signal like it's supposed to. This was due to truncation of the numbers during calculations. This version implements a fix for this issue.
Be careful if you move from the previous version to this as the I-term may behave quite differently depending on how your particular application is set up. I've tested it here and it seems to work but please let me know if you find any problems.
Second, new feature...Feed-forward
While a PID filter by itself works on the difference between the "setpoint" and the "target" feed-forward works directly on the command signal. Let's say you're controling the speed of a motor, the friction in the bearings, brushes and in the load the motor is driving causes it to need a certain "baseline" amount of power for any given speed in order to compensate for its mechanical and electrical losses. Feedforward can provide this "baseline" which helps the actual filter and can increase the overall system response.
There are three new "external" variables that you need to use with feed-forward:
pid_Vel_Kff This is the velocity feedforward gain.
pid_Acc_Kff This is the acceleration feedforward gain
pid_Velocity_cmd This is the actual command signal.
As motor control is my personal use for the incPID routine I've used the terms velocity and acceleration but it's applicable to whatever you are controling. Lets take an example where we want to control the temperature in an oven.
By imperical testing you have determined that in order to maintain your desired temperature (lets say 150 degrees) under normal/optimal/stable conditions you need an "output" of 800 to your "powerstage". If you set pid_Vel_Kff to $0600 and pid_Vel_cmd to 150, this will result in a "baseline" output of 800. Then you calculate the difference between the setpoint (150) and the current temperature and send it to filter in pid_Error. The output from the actual PID-filter then gets added to or subtracted from that 800 number in order to compensate for any disturbances that occurs.
The acceleration feedforward works in the same way as the derivative term of the PID filter but instead of acting on the derivative (ie. the difference) of pid_error it acts on the derivative of pid_Vel_cmd.
More info is available in the file itself.
I've tested this quite a bit but as always I'm sure there are things I've overlooked. If you have problems, please post in the thread and we'll try to work it out. If you don't have problems and it just works that's always nice to hear as well ;-)
Sincerely,
/Henrik.
(Change file extension from .txt to .pbp and place it in your project folder or in the PBP installation folder).
Example of what can be done with incPID.
Hi,
For anyone interested in motor control, here's a link to a Youtube video showing my latest project based on the PID code available in this thread. It's HP-UHU servo drive on which I've replaced the original UHU servo processor with my own "servo module" that I've made pin-compatible with the original chip.
http://www.youtube.com/watch?v=U-jrxK7u_34
<object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/U-jrxK7u_34&hl=en_US&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/U-jrxK7u_34&hl=en_US&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object>
/Henrik.
Re: PID-filter routine (2nd try).
Cool Henrik, I think I may have a use for this :)
Ok, this is a whole new area to me, here's what I think I've grasped wrt how this works ....
You have a desired value (setpoint), you take an incoming ADC reading & subtract it from your desired value....the PID sub routine then gets called & it returns a value of pid_out ?
Am I right so far?!!
Ok, what to do with pid_out?
For my intended use, I want to control a 256 step digital SPI pot (which alters the magnitude of an analog signal - an AGC in essence)...I have a 'desired value' ADC sample (a simple 8 bit ADC sample of the wiper from a std analogue pot ittingt between VCC & Gnd) that I want the signal to 'hit', but obviously the digital pot needs to either increment or decrement towards getting the signal to meet the desired value - I'm wondering how I translate the "Direction = pid_Out.15" to be increment/decrementof thedigital pot ...or does it not matter - ie will the value of pid_out just be a value that I can write direct to the digital pot?
What do I need to tweak with this bit...
Code:
Main_Loop:
gosub adc
pid_Error = Setpoint - ADValue 'Calculate the error
Gosub PID 'Result returned in pid_Drive
Direction = pid_Out.15 'Set direction pin accordning to sign
pid_Out = ABS pid_Out 'Convert from two's comp. to absolute
how to control the digital pot here?!!!
Pause 10 'Wait....
Goto Main_Loop '...and do it again.
I’m controlling my digital pot like thus…
Code:
write_VR1:
LOW CS
SSPBUF = VR1_Select 'put the command byte into SSPBUF
gosub letclear
SSPBUF = VR1_Position 'put the data byte into SSPBUF
gosub letclear
high CS
RETURN
letclear:
IF PIR1.3 = 0 Then letclear ' wait for SPI interupt flag
PauseUs 10 ' 25uS fudge factor
PIR1.3 = 0 ' clear buffer full status
Return
I’m figuring it’s just a case of something like GOSUB write_VR1 & then within there having the data byte be pid_out?
Hand holdng warmly accepted!