How to PID Temperature Control with Arduino & Sensors

In many applications, precise temperature control is essential—whether for industrial processes, 3D printing, or even home brewing. One of the best ways to achieve accurate temperature regulation is by using a PID (Proportional-Integral-Derivative) controller. In this guide, we’ll build a DIY PID temperature control system using an Arduino, a K-Type thermocouple with a MAX6675 amplifier, and an LCD 16×2 display to monitor the temperature.


🔹 Components Required

Before we dive into the project, here’s what you’ll need:

  1. Arduino Board (Uno, Mega, or any compatible board)
  2. K-Type Thermocouple with MAX6675 Amplifier (for temperature sensing)
  3. 16×2 LCD Display with I2C Module (for displaying temperature)
  4. Relay Module (to control the heating element)
  5. Heating Element (such as a resistor, nichrome wire, or heater)
  6. Cooling Fan (optional) (for active cooling in both heating/cooling applications)
  7. Push Buttons or Potentiometer (for manual tuning, if desired)
  8. Power Supply (as per the heating element requirements)
  9. Connecting Wires & Breadboard

🔹 Understanding PID Temperature Control

PID stands for:

  • Proportional (P): Corrects errors proportionally.
  • Integral (I): Reduces steady-state errors.
  • Derivative (D): Reacts to rapid changes.

Using the PID library in Arduino, we can fine-tune these parameters to maintain a stable temperature around the setpoint.


🔹 Wiring Diagram

Connections

K-Type Thermocouple with MAX6675 to Arduino

MAX6675 PinArduino Pin
VCC5V
GNDGND
SCKD13
CSD10
SOD12

16×2 LCD with I2C Module to Arduino

LCD I2C PinArduino Pin
VCC5V
GNDGND
SDAA4
SCLA5

Relay Module to Arduino

Relay PinArduino Pin
VCC5V
GNDGND
IND9

🔹 The heating element is connected to Relay COM (Common) and NO (Normally Open) terminals, while the power source is linked accordingly.


🔹 Arduino Code

We’ll use the PID Library and MAX6675 Library to handle temperature control.

Install Libraries

Before uploading the code, install the following libraries in the Arduino IDE:

  1. PID Library (PID_v1.h) – for PID control.
  2. MAX6675 Library (max6675.h) – to read the thermocouple.
  3. LiquidCrystal_I2C – for LCD display control.

Complete Code

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <max6675.h>
#include <PID_v1.h>

// LCD setup
LiquidCrystal_I2C lcd(0x27, 16, 2); 

// MAX6675 setup
#define SCK 13
#define CS 10
#define SO 12
MAX6675 thermocouple(SO, SCK, CS);

// PID Variables
double setpoint = 100.0; // Target Temperature
double input, output;
double Kp = 2.0, Ki = 5.0, Kd = 1.0; // Tune these values

// Relay control
int relayPin = 9;
PID myPID(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);

void setup() {
    Serial.begin(9600);
    lcd.begin(16, 2);
    lcd.backlight();
    
    pinMode(relayPin, OUTPUT);
    digitalWrite(relayPin, LOW);

    myPID.SetMode(AUTOMATIC);
}

void loop() {
    // Read temperature from the thermocouple
    input = thermocouple.readCelsius();
    
    // Compute PID output
    myPID.Compute();
    
    // Control relay based on PID output
    if (output > 50) { 
        digitalWrite(relayPin, HIGH);
    } else {
        digitalWrite(relayPin, LOW);
    }

    // Display on LCD
    lcd.setCursor(0, 0);
    lcd.print("Temp: ");
    lcd.print(input);
    lcd.print("C  ");

    lcd.setCursor(0, 1);
    lcd.print("Set: ");
    lcd.print(setpoint);
    lcd.print("C  ");

    Serial.print("Temperature: ");
    Serial.print(input);
    Serial.println(" °C");

    delay(1000); // Update every second
}

Arduino Code for PID Temperature Control and Display


//LCD config (i2c LCD screen, you need to install the LiquidCrystal_I2C if you don't have it )
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F,16,2);  //sometimes the adress is not 0x3f. Change to 0x27 if it dosn't work.

/*    i2c LCD Module  ==>   Arduino
 *    SCL             ==>     A5
 *    SDA             ==>     A4
 *    Vcc             ==>     Vcc (5v)
 *    Gnd             ==>     Gnd      */

#include <SPI.h>
//We define the SPI pìns
#define MAX6675_CS   10
#define MAX6675_SO   12
#define MAX6675_SCK  13

//Pins
int PWM_pin = 3;


//Variables
float temperature_read = 0.0;
float set_temperature = 210;
float PID_error = 0;
float previous_error = 0;
float elapsedTime, Time, timePrev;
int PID_value = 0;



//PID constants 
int kp = 9.1;   int ki = 0.3;   int kd = 1.8;

//int kp = 9.1;   int ki = 0;   int kd = 0;

int PID_p = 0;    int PID_i = 0;    int PID_d = 0;



void setup() {
  pinMode(PWM_pin,OUTPUT);
  TCCR2B = TCCR2B & B11111000 | 0x03;    // pin 3 and 11 PWM frequency of 980.39 Hz
  Time = millis(); 
  lcd.init();
  lcd.backlight();
}


void loop() {
 // First we read the real value of temperature
  temperature_read = readThermocouple();
  //Next we calculate the error between the setpoint and the real value
  PID_error = set_temperature - temperature_read;
  //Calculate the P value
  PID_p = kp * PID_error;
  //Calculate the I value in a range on +-3
  if(-3 < PID_error <3)
  {
    PID_i = PID_i + (ki * PID_error);
  }

  //For derivative we need real time to calculate speed change rate
  timePrev = Time;                            // the previous time is stored before the actual time read
  Time = millis();                            // actual time read
  elapsedTime = (Time - timePrev) / 1000; 
  //Now we can calculate the D calue
  PID_d = kd*((PID_error - previous_error)/elapsedTime);
  //Final total PID value is the sum of P + I + D
  PID_value = PID_p + PID_i + PID_d;

  //We define PWM range between 0 and 255
  if(PID_value < 0)
  {    PID_value = 0;    }
  if(PID_value > 255)  
  {    PID_value = 255;  }
  //Now we can write the PWM signal to the mosfet on digital pin D3
  analogWrite(PWM_pin,255-PID_value);
  previous_error = PID_error;     //Remember to store the previous error for next loop.

  delay(300);
  //lcd.clear();
  
  lcd.setCursor(0,0);
  lcd.print("PID TEMP control");
  lcd.setCursor(0,1);
  lcd.print("S:");
  lcd.setCursor(2,1);
  lcd.print(set_temperature,1);
  lcd.setCursor(9,1);
  lcd.print("R:");
  lcd.setCursor(11,1);
  lcd.print(temperature_read,1);
}



double readThermocouple() {

  uint16_t v;
  pinMode(MAX6675_CS, OUTPUT);
  pinMode(MAX6675_SO, INPUT);
  pinMode(MAX6675_SCK, OUTPUT);
  
  digitalWrite(MAX6675_CS, LOW);
  delay(1);

  // Read in 16 bits,
  //  15    = 0 always
  //  14..2 = 0.25 degree counts MSB First
  //  2     = 1 if thermocouple is open circuit  
  //  1..0  = uninteresting status
  
  v = shiftIn(MAX6675_SO, MAX6675_SCK, MSBFIRST);
  v <<= 8;
  v |= shiftIn(MAX6675_SO, MAX6675_SCK, MSBFIRST);
  
  digitalWrite(MAX6675_CS, HIGH);
  if (v & 0x4) 
  {    
    // Bit 2 indicates if the thermocouple is disconnected
    return NAN;     
  }

  // The lower three bits (0,1,2) are discarded status bits
  v >>= 3;

  // The remaining bits are the number of 0.25 degree (C) counts
  return v*0.25;
}

🔹 How It Works

  1. The thermocouple measures the temperature.
  2. The MAX6675 module sends temperature data to the Arduino.
  3. The PID algorithm processes the data and adjusts the heating element accordingly.
  4. The relay module controls the heater based on the PID output.
  5. The LCD display shows the current temperature and the target setpoint.

🔹 Tuning the PID Controller

To achieve stable temperature control, you’ll need to tune the PID parameters (Kp, Ki, Kd). Here’s how:

  • Start with Kp (proportional gain). Increase it until the system reacts quickly but doesn’t overshoot too much.
  • Gradually adjust Ki to minimize steady-state error.
  • If temperature fluctuations occur, fine-tune Kd to reduce oscillations.

📌 Tip: If you are not using LCD for display, use the Serial Monitor to observe temperature changes and adjust PID values accordingly.


🔹 Applications of PID Temperature Control

  • 3D Printing – Maintain consistent extrusion temperature.
  • Reflow Ovens – For precise PCB soldering.
  • Incubators – To control temperature for hatching eggs or lab experiments.
  • Home Brewing – For fermenting or distilling at exact temperatures.
  • Industrial Processing – Ensuring stable thermal conditions in manufacturing.

🔹 Conclusion

In this project, we implemented a PID-based temperature control system using an Arduino, a K-Type thermocouple with MAX6675, and an LCD 16×2 display. This method allows for precise and automated temperature regulation, making it useful for a wide range of applications.

Next Steps: Try integrating buttons or a rotary encoder to adjust the temperature setpoint dynamically!

Have questions or ideas for improvement? Drop them in the comments below! 🚀


Leave a Comment