Arduino PID Update

I wrote a post a few months back detailing my Arduino PID controller approach.  Based on some feedback, I realized the code in that post was overly complicated as well as had some errors in it.  I am now going to detail a much simpler approach.

Previously, I used a PID controller to schedule temperature over a fixed amount of time, such as to have precise ramp up time, hold time, and cool down time.  It is worth noting that a PID controller is also useful for indefinite time control, like a thermostat.  By varying the coefficients, you can customize how fast the system reacts and not damage any equipment (this is a consideration when using mechanical relays that don’t like fast switching).

Below is my Arduino C code for maintaining a set temperature like a thermostat with a PID controller.  The MAX31855 and the PID_v1 libraries can be found on my Github page.

#include "SPI.h"
#include "MAX31855.h"
#include "PID_v1.h"

//Arduino Pins
//CSB of MAX31855 thermocouple. By using separate CSBs, multiple devices can use the same SPI bus.
byte thermo1_csb = 7;
//Pin to control relay that switches the heating element
byte temp_relay0_Pin = 0;

//PID calculation parameters
//Value read by thermocouple sensor
double temp_read1;
//Temperature that system is currently maintaining
double temp_set1 = 95;
//Control value resulting from PID calculation
double Output_T1;

//Library Objects
MAX31855 thermo;
PID PID_temp1(&temp_read1, &Output_T1, &temp_set1, 1, 5, 0.5, DIRECT);

void setup()
   //Initiate thermocouple

   //Initiate heating element relay
   pinMode(temp_relay0_Pin, OUTPUT);
   digitalWrite(temp_relay0_Pin, LOW);

//This function reads the thermocouple sensor and translates the value into temp_read1
void read_sensors()
   temp_read1 = thermo.thermocouple_temp*1.8+32;

//This function computes the output control value from the thermocouple reading and current set point
//and then turns the heating element on and off accordingly
void run_PID()
   uint16_t low_WindowSize = 0;
   uint16_t high_WindowSize = 1000;
   uint32_t windowStartTime = millis();

   //Specify the links and initial tuning parameters
   PID_temp1.SetOutputLimits(low_WindowSize, high_WindowSize);
   //PID_temp1.SetTunings(Kp, Ki, Kd);


   //This section controls the heating element
   while(millis() < (high_WindowSize-low_WindowSize) + windowStartTime) 
       if(Output_T1 > (millis() - windowStartTime))
          digitalWrite(temp_relay0_Pin, HIGH);
         digitalWrite(temp_relay0_Pin, LOW);

void loop()


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s