Hi Steve,Ok so I have been giving this some thought and have realized that with a window size of 1000 millis and a gain of only 200 on the P, the error would have to be 5 deg for the output to be 100% on P only. So what I think was happening yesterday was the P term was dropping off too early and then the I term kept ramping because of the constant error. The I term is reduced by the D term in proportion to the rate of change or by the error going negitive (overshoot) , so with the slow rate of change and the lack of P control near the setpoint then I term was bound to oscillate.
So the plan is:
1. increase the sample rate time because of the slow rate of change
2. increase the bandwidth of the P term gain to a 500 limit ( from 200)
3. set the window time to 500 millis and just mutilply the output to get a longer window time if needed
the reason for the last point is that the I term is limited by the window size, so fixing it to 500 hopefully it doesn't take too long for the I term to be reined in.
cheers steve
Hi Steve,
I've decided the PID is not needed in my rig. The reason is that the amount of mash liquor being heated directly at any one time is quite small compared to the thermal mass of the grain and liquor in the pipe. I just have a simple on/off heater control for mashing (boil I can set % power) and measuring the temp of the liquor flowing over the top of the pipe shows it is pretty much rock solid at target.
I like the idea of PID but my tendency is to over complicate things. I've decided this is one bit that was more complex than it needed to be.
Again kudos for all your development work - an impressive bit of kit and offering to the brewing world.
cheers, Arnie
void PID_HEAT (void){
if((Setpoint - Input)>5){
digitalWrite(Heat,HIGH);
}
else{
myPID.Compute();
unsigned long now = millis();
if(now - windowStartTime>WindowSize)
{ //time to shift the Relay Window
windowStartTime += WindowSize;
}
if((Output*(WindowSize/100)) > now - windowStartTime) digitalWrite(Heat,HIGH);
else digitalWrite(Heat,LOW);
}
}
so with a bit more thought and playing around with a spreadsheet I have decided to have the heat on until the temperature is 5 degs from the set point then the PID takes over. I just tried it out on 20l with a 2400w element and it ramped up and settled on the setpoint without any overshoot.
Code:void PID_HEAT (void){ if((Setpoint - Input)>5){ digitalWrite(Heat,HIGH); } else{ myPID.Compute(); unsigned long now = millis(); if(now - windowStartTime>WindowSize) { //time to shift the Relay Window windowStartTime += WindowSize; } if((Output*(WindowSize/100)) > now - windowStartTime) digitalWrite(Heat,HIGH); else digitalWrite(Heat,LOW); } }
I also increased the sample time to 5 seconds, divided Ki by 100 and limited the output to 100. the setting I used in the trial today was Kp = 50, Ki = 0.01 , Kd = 10 and with a window size of 500ms. The change over between ON and PID is a bit messy with the element being off for about 10 sec whilst the PID ramps up so I'll look into the pid manual/pid auto command to see if that will help and if the setpoint only changes by 1 deg it takes a while for the pid to respond.
cheers steve
That's a good idea Steve. I found with my current Auber PID it was slow to ramp, but controlled at the setpoint well, which led to me manually controlling my mash steps till i reached setpoint. I overcame this with a similar idea of driving the heater on with a deviation alarm, which negated the need for more aggressive PID settings.
Cheers
void PID_HEAT (void){
if((Setpoint - Input)>5)
{
digitalWrite(Heat,HIGH);
if ((Setpoint - Input)<6)
{
myPID.Compute();
}
}
else{
myPID.Compute();
unsigned long now = millis();
if(now - windowStartTime>WindowSize)
{ //time to shift the Relay Window
windowStartTime += WindowSize;
}
if((Output*(WindowSize/100)) > now - windowStartTime) digitalWrite(Heat,HIGH);
else digitalWrite(Heat,LOW);
}
}
So after discussing this with Dmac last night I have come up with this
Code:void PID_HEAT (void){ if((Setpoint - Input)>5) { digitalWrite(Heat,HIGH); if ((Setpoint - Input)<6) { myPID.Compute(); } } else{ myPID.Compute(); unsigned long now = millis(); if(now - windowStartTime>WindowSize) { //time to shift the Relay Window windowStartTime += WindowSize; } if((Output*(WindowSize/100)) > now - windowStartTime) digitalWrite(Heat,HIGH); else digitalWrite(Heat,LOW); } }
this should give the P time to wind before the change over to PID up but not let I term go too far, I haven't tried it yet but it should work.
cheers steve
Looks good Steve,
If i get my **** together over the weekend and finish mine i'll give it a test.
Cheers
Thanks Steve, I will check it out when I progress with my hbBM.after having a look around, I came across this PID library
View attachment 55366
it is the library that the Brewtroller uses, it was written by the same guy that wrote the PIDv1 library but it looks like it has a better algorithm for stopping I from running away. I don't think will use it but thought I might post it for others if they want to play with it.
cheers steve
That sounds like the best solution. Good idea!hey Edak to make that library compile you have to change the #include wiring.h to wiring.c in the .cpp file but it seems pretty good.
I have been playing with the standard library and while the clamp worked OK it wasn't very practical. After looking at the PID beta6 library there was a bit of code that stopped the I from intergrating if the output was at max or min, so I tried putting that into the library. It worked really well for the first step but on the second step ITerm was already ramped and caused overshoot. So after some discussion with Bonj, I have changed the library so that if P is above output max Iterm is set to zero and if its under output min then Iterm is reset to zero. I tried it out today and it worked really well with no overshoot.
View attachment 55523
there is nothing to do but use the library instead of the standard library.
cheers steve
Enter your email address to join: