Temperature Controller

Homebrew Talk - Beer, Wine, Mead, & Cider Brewing Discussion Forum

Help Support Homebrew Talk - Beer, Wine, Mead, & Cider Brewing Discussion Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.

Jared311

Well-Known Member
Joined
Feb 28, 2008
Messages
500
Reaction score
2
Location
Columbia, MD
Sorry for the long post, you might want to top off your beer again before sitting down to this one. I have a habit of confusing others with my poor wording.

So I have designed my first revision of a temperature controller board. It connects to 8 mini temperature sensor boards I designed. Each one sits in a custom made thermal well that can be threaded into a 1/2" coupling that has been welded into the keg wall. This is going to allow me to monitor the mash temperature and see any temperature differentials. Yeah, I know... its overkill, but I actually enjoy building custom hardware. My board communicates with my laptop via USB and I have already wrote software that takes in the temperatures and determines what duty cycle the heating element should be running at. Then the computer talks back to the temperature controller and tells it what duty cycle it should generate. This is where I am stuck. I am not sure yet what frequency I want to pulse width modulate the 220VAC relay which will apply power to my heating element. I was thinking of starting around 1Hz and seeing how well that works. However I am worried that I will burn out my relays pretty fast if I am firing them twice a second. Anyone know what frequency their PID controllers work at?
 
I use an Arduino board with a PID algorithm. The PID algorithm uses a 10 sec calculation window (right now-may go longer).

Every second, I do some calculation and find out if the power should be on or off. This next step is important - If the state doesn't change, don't change the output.

I would not try and PWM the SSR's. I think you would find the life pretty short. Instead, think duty cycle.
 
I use an Arduino board with a PID algorithm. The PID algorithm uses a 10 sec calculation window (right now-may go longer).

Every second, I do some calculation and find out if the power should be on or off. This next step is important - If the state doesn't change, don't change the output.

I would not try and PWM the SSR's. I think you would find the life pretty short. Instead, think duty cycle.

Did your brew day work well with the program? Still interested in finding out more about your RIMS.
 
pid.Compute(); ///This sets the hltPower to a value between 0 (off) and 10000 (On for 10 secs)

//turn the output pin on/off based on pid output millis() is the #ms it has been running.

if(millis()-windowStartTime>PID_INTERVAL) windowStartTime+=PID_INTERVAL;

if( (hltPower > millis()-windowStartTime ) || (hltPower >= PID_INTERVAL) )
{
if ( hltHeatLastState != HIGH)
{
digitalWrite(hltHeatPin,HIGH);
lcd.print("ON",1,13);
hltHeatLastState=HIGH;

}
}
else
{
if ( hltHeatLastState != LOW )
{
hltHeatLastState = LOW;
digitalWrite(hltHeatPin,LOW);
lcd.print("OFF",1,13);
}
}
 
That looks like a simple proportional control routine, where is the integral and derivative functions. Here is part of the PID program in the phase 2 control program for an example

public int CalculateGain (double position) {
System.out.println("pos: " + position + "setpoint: " + Setpoint);
double error = Setpoint - position;
System.out.println("error: " + error);
ErrorSum += error ;
System.out.println(ErrorSum);
if (ErrorSum >(IntegralLimit / KIntegral)) {
ErrorSum = (IntegralLimit / KIntegral);
}
System.out.println("KP: " + KProportional + ", error: " + error);
ProportionalGain = KProportional * error;
IntegralGain = KIntegral * ErrorSum;
if (java.lang.Math.abs(IntegralGain) > IntegralLimit) {
if(IntegralGain > IntegralLimit)
IntegralGain = IntegralLimit;
else
IntegralGain = -IntegralLimit;
}
DifferentialGain = KDifferential * ( error - PrevError );
PrevError = error;
Gain = ProportionalGain + IntegralGain + DifferentialGain;
System.out.println("P: " + ProportionalGain + ", I: " + IntegralGain + ", D: " + DifferentialGain);
return (int)Gain;
}
 
Yes, kladue, that is right. We are probably using nearly identical code for that portion. The return specifies the number of seconds out of the period to be on, my timer math just figures out how whether to turn it on or off.

For the uninformed, a PID circuit works like a cruise control in your car, providing a proportionate amount of power to maintain a set speed. When it falls off by 2 mph, add 3% power instead of full throttle.

kladue- What are you using for t-couples? If using the LM34, did you use a fixed value like analogRead(hltTempPin) * .488, or did you find that each one had some variance in temperature readings?
 
I use opto22 hardware for thermocouple and PT100 RTD interface, then apply a scale and offset value to the result to correct any calibration problems. The scale and offset values are reached through a hardware settings GUI in the control application for on the fly calibration. The PID control loops each have a calibration GUI for initial tuneup and values are retained in the SQL database for later use in manual/auto control modes.
 
Thanks lrr81765 and kladue for posting your algorithms. I am in the process of researching PID algorithms to get a better feel for them and then I am going to read through your codes. I will keep you guys updated as I get around to it and let you know if I made any significant changes.
 
One of the components not shown in the PID code was the calculating cycle delay, to short and not enough error difference to make integral and derivative functions work. This was made into a variable that could be adjusted to get needed performance in each application.
 
As for the LM34CAZ, I am using 3 and one is dead-nuts and the other 2 are within 1 or 2 tenths of a degree. I think you will find they are quite a bit more accurate than your run-of-the-mill TC with the exception of the RTD.
As for the freq of your output, I started toying with 1 Hz and went to 40 Hz. First thing to do it toss out your relay and get an SSR with a good heat sink.
The SSR will always be on for multiples of half-cycles (multiples of 8.3 ms). Even with a random turn-on SSR, you have similar issues in that it stays on until a zero crossing. I would consider a PWM frequency more like 1 Hz where you increment the duty-cycle by multiples of 1.667%.

Just my $.02.....
 
Hi Jared311.

Another interesting variation on the PID algorithms previously posted is a slight twist on the Derivative term. It uses the position instead of the error in the D term calculation. This seems to work slightly better in practice, although each system is unique.

Code:
double UpdatePID(SPid * pid, double error, double position)
{
  double pTerm,
  dTerm, iTerm;
  pTerm = pid->pGain * error;   
  // calculate the proportional term
  // calculate the integral state with appropriate limiting
  pid->iState += error;
  if (pid->iState > pid->iMax) pid->iState = pid->iMax;
  else if (pid->iState < pid->iMin) pid->iState = pid->iMin;

  iTerm = pid->iGain * iState;  // calculate the integral term
  dTerm = pid->dGain * (position - pid->dState);
  pid->dState = position;
  return pTerm + iTerm - dTerm;
}

This code is taken from PID Without a PhD. The author explains his reasoning behind the difference from more traditional PID algorithms. This is the approach that I took with the BCS-460 control loops. I believe that the PID code in the Aurdino Playground takes a similar approach.
 
Back
Top