Welcome, Guest
Username: Password: Secret Key Remember me
  • Page:
  • 1
  • 2

TOPIC: PID on a PIC Microcontroller

Re: PID on a PIC Microcontroller 7 years 1 month ago #16119

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 in-turn 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.digital-diy.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()
' Re-initialises 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
A quick note about the fan - it will be controlled by PWM (0-100%). Between environmental and other factors, the control loop feedback offered by PID should easily (and quickly) resolve error. I have an Excel document for simulating the PID controller, and so far I will likely go with these parameters, Kp=0.1, Ki=0.1, Kd=1 and 500mS interval.

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.

Re: PID on a PIC Microcontroller 7 years 1 month ago #10760

  • MrDEB
  • MrDEB's Avatar
  • Offline
  • User is blocked
  • Thanks received: 14
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://digital-diy.com/electronics-blog ... nsors.html on sensors.

Re: PID on a PIC Microcontroller 7 years 1 month ago #10761

  • Jon Chandler
  • Jon Chandler's Avatar
  • Offline
  • Moderator
  • Posts: 365
  • Thanks received: 352
It's true that thermocouples are non-linear. 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....

Re: PID on a PIC Microcontroller 7 years 1 month ago #10764

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?

Re: PID on a PIC Microcontroller 7 years 1 month ago #10766

  • Jon Chandler
  • Jon Chandler's Avatar
  • Offline
  • Moderator
  • Posts: 365
  • Thanks received: 352
Not much at all Graham. For the sous vide, we had plans for PID control but a simple bang-bang 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.

Re: PID on a PIC Microcontroller 7 years 1 month ago #10771

  • MrDEB
  • MrDEB's Avatar
  • Offline
  • User is blocked
  • Thanks received: 14
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
  • Page:
  • 1
  • 2
Time to create page: 0.260 seconds