Arduino Development Thread

Australia & New Zealand Homebrewing Forum

Help Support Australia & New Zealand Homebrewing Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.
looks good dan, I'm still learning the language myself the code is only readable because of the advice of Zizzle, now he knows his coding .

cheers steve
 
Did a test run today, the unit performed well electrically and thermally, the heatsink only got about 20deg above ambient so I happy there, the PSU was running the unit and a 15w pump and that was all good too.

heat_test.JPG

heat_test2.JPG

what I wasn't happy with was the PID, even when I had Kp set to my MAX value which was 200 it still couldn't get oscillation, when I introduced the Ki I would then get overshoot and a slow response and no amount of Kd would stop the overshoot. Basically the heat would stay hard on until it actually went over temp and the it would start to ramp down, the best I could get was about 0.5 deg swing each way. I have a few ideas one of them is the sample time, it was set to the default of 0.1 sec. I think that with a ramp rate of about 1.5 deg/min and a resolution of 0.0625, it is allowing the I to ramp up without any input from the D.

I = I+((Ki x sampletime_in_sec)x error)

and

D = (Kd/sampletime_in_sec) x (input - lastinput)

with a temp rise of 1.5 deg/min this would give a temperature change of 0.0625 about every 3 seconds which would allow the I to change 30 times before D can be used to pull it back. My window size was set to 1 second, I was thinking of setting the sample time to the window size which would then reduce the amount of times that the I could change without D holding it back.

what are others experience with the PID library in the arduino

cheers 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
 
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
 
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

thanks again Arnie for the advice, I'll keep it in mind, if this all gets to complicated then I might just do that.

cheers steve
 
yeh, I've done a bit of reading on the theory of PID temp control and figured I would first approach temp control with a simpler method with the aim of KISS.

At this stage I am thinking of some percentage based formula. The closer the temp is getting towards target (smaller % difference) then shorter duty cycle on the heating element. I figure it will need some improvements when the mash gets added as that will confuse things a bit. Or maybe not?

Once the target has been met, switch it over to smaller percentage difference triggering the heating element. Adding insulation to the pot should help reduce the amount of temp maintenance needed.

Sounds good in theory. ;)
 
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
 
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
 
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

thanks mate, I probably could have used 2 PID setting but that would mean adding more menus and that's just too much f'ing around so I went with this idea, what I would like to do is to have a separate I term limit so I can limit it to a percentage of the output, then I could put an agressive Ki in and it would only affect the lower power settings which would be good to bring the temp up to the set point after the P has dropped away, but that would mean changing the library.

anyway HERE is the code, to see the change I have done click on the history button then click on the rectangle up the top right with all the numbers in it

cheers steve
 
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
 
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
 
just incase you haven't seen it on the other thread

The Brauduino ZIP

the zip contains the manuals,programs and eagle files I used to make the brauduino

cheers steve
 
I have been playing with the PID library and have added a function called SetITermClamp which will allow you to clamp the ITerm to stop it winding up

View attachment PID_Iclamped.zip

I hope it works I complied a small bit of code with it included and didn't bring up any errors, this is the first time I have played with a library so I could have stuffed it up, when I get a chance I'll try it out on my test rig.

to set the ITerm clamp the code would be

myPID.SetITermClamp(0,20);

which would hold the ITerm between 0 and 20, hopefully this will help stop the overshoot and oscillation problems.

I have been playing with a spreadsheet, its really rough but I have been working on some options

View attachment pid1.xls

the options are a 1 second sample rate with D being subtracted from ITerm instead of the output , a 5 second sample rate with ITerm clamped to 20 and a 1 second sample rate with ITerm clamped to 20.

cheers steve
 
I loaded up the library to my unit this afternoon, it does clamp I so I'm happy about that, I would suggest clamping ITerm to just above the percentage of the output required to keep a constant temperature at the maximum temperature required for the mash, basically what your losses are. This would stop I term from causing an overshoot but allow it to remove the constant error that persists with P drive only, if you are getting a bit of overshoot you could ramp up D to hold it back.

cheers steve
 
after having a look around, I came across this PID library

View attachment PID_Beta6.zip

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
 
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
Thanks Steve, I will check it out when I progress with my hbBM.
 
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 PID_V102.zip

there is nothing to do but use the library instead of the standard library.

cheers steve
 
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
That sounds like the best solution. Good idea!
 
Back
Top