PID heater help
TC
Posts: 1,019
Hello all,
I am building a reflow oven, and I am trying to get it to heat up right. I can get it to heat to a set point, but it insanely over shoots (20-40°C). But when it stablizes, it is within 1°C. I know it is my PID that is doing it. The code gets updated about once a second.
I have Pterm, Iterm, Dterm, CV, set_value, & current_value displayed on my display so I can see what is going on.
Here are the gain values I have, I have been changing them one by one to try to get it to work.
Starting from a cold start(32°C), I notice Iterm will max out real fast(that's good I think), but it will stay like that until the temp goes past the set point. So I use Dterm to counter Iterm and try to slow down the PWM before the temp gets to the set point.
I don't know much about PIDs,I know what they are, and what they do. But I don't fully understand how they work. Wikipedia is not much help to me. I have never learned advance math, so the equations Wikipedia has mean nothing to me.
I found a post on control.com, that looked promising. So I copied it for the prop.
Could someone please take a look at it, and tell me if there is something wrong. Or do I have to keep trying different gain settings. Or if you might have a better option.
Thanks
TC
I am building a reflow oven, and I am trying to get it to heat up right. I can get it to heat to a set point, but it insanely over shoots (20-40°C). But when it stablizes, it is within 1°C. I know it is my PID that is doing it. The code gets updated about once a second.
VAR long error long last_error long Pterm long Iterm long Dterm long CV PUB PID (set, current, Pgain, Igain, Dgain) '=== This algorithm must be executed at a consistent guaranteed periodic rate (such as once/second) to function correctly === 'set = value you want 'current = current value 'Pgain = Proportional gain value, use "0" if not needed 'Igain = Integral gain value, use "0" if not needed 'Dgain = Derivative gain value, use "0" if not needed '*** Find Error *** error := set - current '*** Find Proportional Value *** Pterm := Pgain * error '*** Find Integral Value *** Iterm := Iterm + (error * Igain) #>0 <#100 'anti-windup '*** Find Derivative Value *** Dterm := (error - last_error) * Dgain '*** Save current error *** last_error := error '*** Sum PID values *** '''' If set_value is off (0) make CV off if set == 0 CV := 0 else CV := Pterm + Iterm + Dterm #>0 <#100 ' output limiting
I have Pterm, Iterm, Dterm, CV, set_value, & current_value displayed on my display so I can see what is going on.
Here are the gain values I have, I have been changing them one by one to try to get it to work.
P = 1 I = 10 D = 30
Starting from a cold start(32°C), I notice Iterm will max out real fast(that's good I think), but it will stay like that until the temp goes past the set point. So I use Dterm to counter Iterm and try to slow down the PWM before the temp gets to the set point.
I don't know much about PIDs,I know what they are, and what they do. But I don't fully understand how they work. Wikipedia is not much help to me. I have never learned advance math, so the equations Wikipedia has mean nothing to me.
I found a post on control.com, that looked promising. So I copied it for the prop.
Could someone please take a look at it, and tell me if there is something wrong. Or do I have to keep trying different gain settings. Or if you might have a better option.
Thanks
TC
Comments
We just had a good long discussion on temperature control here : http://forums.parallax.com/showthread.php/153551-Modifying-an-old-thermostatic-chamber-can-t-get-precise-temperature-control.
Lot's of tips and pointers re: PID and temperature control in there.
it will over shoot by 12°C, and hover around -1°C and -14°C from the set point.
With values of
it will over shoot by 35°C and hover around -5°C to 10°C from the set point.
Iterm is still going to 100 right out of the gate, and stays there until the current > set. then it starts decreasing. but by that time, it is to late. That is why I had such a large I gain, to make the decreasing faster.
To understand PID, you need a method to see the effect of the output versus an error. Without fully understanding each element, you can't tackle the more complicated issue of summing the elements in a useful manner. I would think it is not easy to grab an PID examples off the nest and immediately apply to a custom project. I spent countless hours looking at examples for motor control, but only when I started viewing each component and the sum did it all start to come together.
What do you think my best option is? should I toss out what I have, and go floating point? Becaus I tried
I got no change.
I started at P = 1, then seen what happend on my display. Then went from there. Adding more to P, and seeing what happend. Then I started on I, same way. then D. Until I came up with what I had in my first post. As I said in my first post, I can see the values of SET, CURRENT, Pterm, Iterm, Dterm, and PID output
Don't mind the set value and the current value, that is not what the PID sees. If you take the value/25 that is the value the PID sees. IE 17500 / 25 = 700. The thermocouple adapter outputs in .25°C per bit. I just have the display converting so I can understand it.
I am using a home built SSR. It works great, no problems. I am using a Spin object for the PWM, that waits for the AC to zero-cross so it knows when to turn off the Triac.
I agree, why do you think I have the display.
When you want 1 store it as 1000 and so on.
Then you can add and subtract as normal.
If you want to multiply just multiply but divide by a thousand afterwards.
e.g. For 10 x 10 you have stored them multiplied by a thousand so you now have 10,000 x 10,000 = 100,000,000.
Which needs dividing by 1000 to get the correct scaled result of 100,000 which is 100 in back in the real world.
Now you can multiply by 0.5 which is stored as 500.
Don't forget you numbers are scaled when you come to print them out or use them.
If you actually need this in your PID is another matter. Perhaps all the required scaling can be done on the error measurement input and the output drive.
I have a device that outputs .0625 c per bit. You may be able to look at this and see if this can be adjusted and used for your temp sensor.
It would be useful to see on the screen:
Error =
P =
I =
iMax =
D =
Output =
I tried that, but I am getting some strange results.
Lets say current error = 1, and Pgain = .5
1 * .5 = .5
now lets adjust the scale;
1 * 1,000 (error * 1,000) = 1,000
.5 * 1,000 (Pgain * 1,000) = 500
1,000 * 500 = 500,000
500,000 / 1,000 (bring back to real world) = 500
Now lets say my PWM has a range of 0 to 1000, the PWM would have a 50% duty cycle at an error of 1
I'm still thinking this through. I was hoping by me writing it down, i would see the answer.
I was thinking of changing the real world 1,000 to 100,000
Sorry, perhaps I'm confusing you.
When I talk about scaled arithmetic I mean that when you want the value 1 in your program you write 1000.
If you want a half it's:
You cannot use Spin's floating point assignments like:
That will set "a" to some floating point representation of 0.5 which is not what we want.
Just imagine that all your variables are representations of multiples of 1/1000 rather than just 1 as normal.
I honestly don't know, if I am over thinking it, or I am just wrong.
I have
that gives me an error of 1_000
500 * 1000 = 500_000
so now Pterm = 500_000
500_000 + 0 + 0 = 500_000
500_000 / 1_000 = 500 <
this should be 0.5 in the real world (scaled)?
Am I wanting a value of 5, instead of 500? Because I could just do
This is why I wish I could understand the PID equation on Wikipedia, I could check my work.
I'm afraid we are getting into a confusion between the PID, which you need, and fixed point arithmetic, which you may or may not need to get the PID to work.
Anyway, an example. I want to calculate 5 * 6 using fixed point arithmetic:
At the end of that code sequence "c" equals 5000 * 6000 / 1000 equals 30,000. Which is 5 x 6 if we are counting in "one thousandths" rather than "ones".
My oven overshoots too. Some of this is really not possible to control without some form of data transformation control (ie some manual feedback from a table). The time lag between turning the element on or off has an effect that I would expect a normal PID loop to be unable to control properly.
I notice my oven shuts off the temp before it reaches the temp, then uses shorter bursts to get it up to temp.
Hope this helps.
BTW my thermocouple wire only goes to ~200C and I thought this was typical of that form of thermocouple??? I understand a probe will have a time lag.
For my gains I am using
For the code I did what Heater suggested, I changed the scale of the values. Here is the code
With this setup, I can go from 35°C to 225°C in no time. I have little to no overshoot. And the temperature will hover +1°C to -1°C.
Thank you everyone.
That is a great result. Temperature control is not so easy and you seem to have it very well under control.
I haven't looked at the code so had but this caught my eye:
Seems to be missing some scaling.
For example we have gain = 3 and error = 6 so Pterm should be 18. In real world numbers. So in the code I would have:
Now Pterm is 1800 which is the correct scaled value of the real world value of 18.
You are missing that divide on all your multiples so I wonder how this works. Perhaps you input and output scaling is taking care of it though.
I was saying around the same lines as you. Things were not adding up, I was not getting the scaling that I thought I should've had. I did not think of adding the scaling to everything, just to the input and output. I think it would be better anyway to leave the scaling high through all the formulas, then bring it back down once everything is calculated. To me, it would be less chance of clipping the result.
You can do the scaling wherever you like that works.
But be careful. If you start working with more complex formulae you might have problems. For examble:
x := a * b
Is 100 times to big in our scaled world. Which you might take or on output. But:
x := a * b * c
Is now 10000 times to big. And so on. Overflowing what can fit in a 32 bit integer is a possibility.
Also:
x := a * b
x := x + c
Goes a bit weird as after the first statement x is 100 times to big. If you scale back after the second statement then the effect of adding c is 100 times to small!
So I like to keep the scaling correct at every step of the way.
Hi TC,
I saw on another post you were working on a reflow oven and I'm lucky I've stumbled upon this thread. Awesome insight from lots of helpful people.
Is your code and oven still performing the way you want to? Can you expand on how you solved your overshoot issues? I'm having the same exact problem.
Also, if you don't mind, could you post your most recent PID control code for me to use/look at please?
Thanks a ton!
Try a bit less P and a bit more D.
Duane J
And so I am wondering if I really need PID for heater control. I certainly appreciate PID with motor control for tight positioning and tight rate control. It is just hard for me to believe I need that tightness with heat regulation.
Hello nathantrantham, and welcome to the forums.
As Duane said, more D....
It is still a work in progress. I keep changing things because I find A better idea. When I get home tonight, I will post the heater control I was using. The heater control works in another COG and all that would have to be done is to pass the set temperature value. it does assume A zero cross circuit is used, because at the time I was going to make my own SSR's.
The object would read the temperature from a MAX31855, calculate the CV (control value) from the PID, then do a very simple PWM. It is very dirty, and I found a couple things I could make better. So instead of patching what I had, I started new.
TC - yes, that's how I have mine setup too. Did you keep the scaling method? Or move to floating point? I'd still be interested in seeing your code if you would be so kind.
Thanks.
Yes, I scaled mine up by 1000.
I included the code. I am in no way saying that this code is perfect, so use it at your own risk.
PID for dummies.
proportional-integral-derivative
Lets think about the old fashioned round Honywell thermostat.
P=proportional
The power delivered to the house, the rate heat is added from the furnace, is proportional to the the difference between the set point on my T87 and the room temperature.
A P controller must have an error to output power. The gain factor defines how much error there will be.
So, when its cold outside the room temperature will be colder than the set point.
A P controller should be fast acting to track quick changes in the heat load.
However, with high gain factors the system may go into oscillation and overshoot.
I=integral
On that cold night when I feel a bit chilly I may slowly adjust the set point on my T87 to compensate for the set point error.
This is integration. A slow fudging of the dial until there is minimal error.
In this example I am the I for the T87.
I should be slow acting.
D=derivative
Ok, my house has settled down and I am comfortable but somebody opens the door and a bunch of heat escapes.
Since the thermostat will sense this immediately the P controller would try to turn the furnace on immediately and strongly which can cause the P and I controllers to go unstable.
However, the whole house has a lot of thermal mass and really doesn't need to change much.
The D derivative controller watches the changes in the room temperature. D reduces the power output caused by the D controller.
Essentially D is a limiting factor, the higher the D gain the less power that can be delivered.
The faster the sensed temperature changes the less power delivered by the furnace.
Don't go to high as D can not control the temperature.
Unfortunately the T87 has no I nor D function but electronic thermostats do.
Generalizations:
System with high thermal mass can use hi P, low I, and low D.
Systems with low thermal mass can use low P, hi I, and hi D.
Systems with long time constants can use low P, low I, and hi D.
Tuning:
1. Start with pure P and increase the gain until it oscillates then back off the gain. There will be error, were just looking for stability.
2. Add some I until the error is acceptable.
3. Cause a transient heat load. Add some D to limit overshoots. You may need to reduce P.
This should at least get the controller going.
I keep meticulous notes when tuning PIDs as it can be very confusing with 3 interacting unknowns.
Duane J
Say we have to heat something to X degrees. The heater is on up to X-certain value (say 10). Time taken to get it to that temperature is measured. Then heater is off, and time for it's cooldown to say X-20 is also measured. According to these timing values, initial PWM percentage is calculated and heater is PWMed with decreasing percentage while it reaches the desired X value. Kinda tricky, but no overshoot.