Welcome,
Guest



While I enjoy slow cooked beef prime rib or smokey pork ribs, it's a tedious task to maintain temperature over several hours (with charcoal smokers such as the Weber Smokey Mountain).
So a new project is in order; a device that controls the flow of oxygen which inturn controls BBQ temperature. Some high temperature ducting connected to the BBQ inlet, a fan on the other end and a thermocouple in the BBQ, well, I'm sure you've pieced it together. I have dabbled with methods to control the fan while I wait for the hardware to arrive. A crude if 'if temperature is low, increase the fan speed' method would work, but would have issues given the many variables that affect the BBQs temperature. So I've brushed up with PID controllers. D.Rossel developed what appeared to be a decent pascal library (a basic version was made as well, but lacked a few features). I've written a Swordfish module and implemented some improvements which should prove a useful PID controller. The code is heavily commented, I would honestly appreciate any feedback or improvement ideas for the module. Module PID
'  '
'  PID library with fixed calculation time interval  '
'  '
' Graham Mitchell
' www.digitaldiy.com
' Translated from original Pascal and Basic code from D.Rossel
'Public Sub Init(Kp, Ki, Kd, MinOutput, MaxOutput As Float)
' Initialises the PID engine
' Kp = the "proportional" bias
' Ki = the "integrated value" bias
' Kd = the "derivative" bias
' MinOutput = the minimal value the output value can have (should be < 0)
' MaxOutput = the maximal value the output can have (should be > 0)
'Public Sub Reset()
' Reinitialises the PID engine without change of settings
'Public Function Calculate(Setpoint, InputValue As Float) As Float
' To be called at a regular time interval (e.g. every 100 msec)
' Setpoint: the target value for "InputValue" to be reached
' InputValue: the actual value measured in the system
' Functionresult: PID function of (SetPoint  InputValue),
' a positive value means "InputValue" is too low (< SetPoint), the process should take action to increase it
' a negative value means "InputValue" is too high (> SetPoint), the process should take action to decrease it
Dim PID_Kp, PID_Ki, PID_Kd As Float
Dim PID_Integrated As Float
Dim PID_Prev_Input As Float
Dim PID_MinOutput, PID_MaxOutput As Float
Dim ErrAbs, PID_Prev_AbsError As Float
Dim PID_First_Time As Boolean
Function AbsReal(val1 As Float) As Float
Dim Tmp As Float
Result = Val1
If Result < 0 Then
Result = Result
EndIf
End Function
Public Sub Reset()
PID_Integrated = 0.0
PID_Prev_Input = 0.0
PID_First_Time = true
End Sub
Public Sub Init(Kp, Ki, Kd, MinOutput, MaxOutput As Float)
PID_Kp = Kp
PID_Ki = Ki
PID_Kd = Kd
PID_MinOutput = MinOutput
PID_MaxOutput = MaxOutput
PID_Integrated = 0.0
PID_Prev_Input = 0.0
PID_First_Time = true
PID_Prev_AbsError = 0
End Sub
// returns 1 for positive, 0 for negative
Function Sign(pVar1 As Float) As Byte
result = 1
If pVar1 < 0 Then
result = 0
EndIf
End Function
Public Function Calculate(Setpoint, InputValue As Float) As Float
Dim TheErr, ErrValue, DiffValue As Float
// calculate the error
TheErr = SetPoint  InputValue
// calculate proportional value 
ErrValue = TheErr * PID_Kp
// minimise integration lag
If Sign(TheErr) <> Sign(PID_Integrated) Then
PID_Integrated = 0
EndIf
// calculate integrated value
PID_Integrated = PID_Integrated + (TheErr * PID_Ki)
// limit it to output minimum and maximum
If PID_Integrated < PID_MinOutput Then
PID_Integrated = PID_MinOutput
End If
If PID_Integrated > PID_MaxOutput Then
PID_Integrated = PID_MaxOutput
End If
// calculate derivative value
If PID_First_Time Then
PID_First_Time = false
PID_Prev_Input = InputValue
End If
DiffValue = (InputValue  PID_Prev_Input) * PID_Kd
PID_Prev_Input = InputValue
// check if error becomes smaller (stop differentiation)
ErrAbs = AbsReal(TheErr)
If ErrAbs < PID_Prev_AbsError Then
DiffValue = 0
EndIf
PID_Prev_AbsError = ErrAbs
// check if error has resolved (remove residual)
If ErrAbs = 0 And PID_Prev_AbsError = 0 Then
DiffValue = 0
PID_Integrated = 0
Result = 0
Exit
EndIf
// calculate total
Result = ErrValue + PID_Integrated  DiffValue
// limit it to output minimum and maximum
If Result < PID_MinOutput Then
Result = PID_MinOutput
End If
If Result > PID_MaxOutput Then
Result = PID_MaxOutput
End If
End Function In anycase, I'm not going to spend countless hours tuning the parameters! Between a trial run and WAG methodology, I'm sure the system will work fine. 


Curious why not use an RTD sensor as it is more accurate and linear as compared to a thermocouple plus you won't need the interface chip? that is required (Jon posted an article on using a thermocouple and interface chip?
great reading http://digitaldiy.com/electronicsblog ... nsors.html on sensors. 


It's true that thermocouples are nonlinear. I used a lookup table for linearization which is pretty simple to implement. A mathematical approach is also doable but a 4th order equation is required as I recall which may be a bit microprocessor intensive.
As far as "more accurate"... well, the thermocouple produces a known voltage at a given temperature. Connect the circuit and you're reading accurate temperatures. An RTD may be capable of better accuracy, but the output depends on the current supplied and the measurement circuit. To know what the temperature is, an RTD system must be calibrated. And to the hardware... the thermocouple circuit I showed uses 1 chip and a cap to get accurate results. How many parts does your RTD circuit use MrDEB? And what's the final resolution of the system? Once again, there are many ways to achieve the same results and there are certainly reasons why an RTD or a thermocouple may be more appropriate for a given task but I don't think you've justified it very well this time.... 


K type thermocouples are very easy to get hold of, and they are cheap! Here's an eBay search for 1 meter thermocouple leads which are prefabricated and ready for use.
I'll be running the lead straight into the BBQ, so the 500+ degree rating of fibreglass insulation is a welcomed feature. Have you had much exposure to PID control with your line of work, Jon? 


Not much at all Graham. For the sous vide, we had plans for PID control but a simple bangbang approach seems to work well and maintain the water bath to about ±1°F which is adequate for the task.
One thing I haven't been able to quite wrap my head around. The output of the PID routines I've looked at is a scaler value (that is, a positive or negative value of some magnitude). In the simplest form, I guess a negative value means "heat on" and a positive value means "heat off." I guess a better approach would be to use the value as a PWM multiplier  a bigger value means a high PWM duty cycle. With out sous vide system, I'll probably have to resort to PWM although it's kind of a slow duty cycle. The heater is on about 1 second out of 19. Looking forward to seeing what you achieve Graham. 


Information that might be helpful?
use a quality charcoal in that Weber Smokey Mountain such as KINGSFORD. This is all I ever use for dutch oven cooking in camp. NOTE each briquet is good for 25degrees F Hopefully blowing air across the charcoal won't create a gray haze on the food product? 
The following user(s) said Thank You: Graham Mitchell

