Closed-loop Temperature Controller with Arduino

Here I am redesigning the closed loop temperature controller with Arduino that I had I designed and illustrated in Building an Automatic Temperature Controller Using Arduino and a PID Algorithm. While the circuit works, I wanted to make some improvements.

Circuit Diagram/Hardware

Following shows the circuit diagram of the improved version of the closed loop temperature controller with Arduino Uno.

Closed-loop Temperature Controller with Arduino

The following shows the previous circuit that was working fine but needed improvements.


In my previous design shown above, I relied on a simple 9V battery to power the Arduino, which was a weak point for long-term use. To solve this, I integrated an LM2595 Buck Converter to pull power directly from the main 12V supply. By stepping this down to 5V, I eliminated the need for a second battery and improved the overall efficiency of the system.

I also upgraded the switching stage. While the IRF540N used previously is powerful, it isn't a "Logic Level" MOSFET and doesn't fully activate at the 5V provided by the Arduino. I swapped it for an IRLZ44N, which is designed specifically for 5V logic. This change ensures the MOSFET conducts fully and stays cool, allowing the bulb to receive maximum power.

To clean up the power delivery, I added a filtering network using 220µF and 120µF capacitors. These smooth out voltage spikes and ripples from the regulator. I also included a 1N5822 Schottky diode—a critical addition because its fast-switching speed and low forward voltage are essential for the high-frequency operation of the buck converter.

Finally, I stabilized the temperature sensing by powering the LM35 directly from the regulated 5V output. In the older version, the sensor shared a rail with a fluctuating battery; now, it has a rock-solid reference voltage for more accurate readings. I also added a gate resistor network (R1 and R2) to ensure the MOSFET gate discharges properly, preventing the load from staying partially active.

Code for the Temperature Controller

Below is the code for the PID-based temperature controller. This will measure the temperature from the LM35 sensor and adjust the power to the heating element to maintain a set temperature (25°C) using a relay.

// Pin Definitions
const int tempSensorPin = A0; // LM35 Temperature Sensor connected to A0
const int heaterPin = 9;      // Heater connected to PWM pin 9

// Parameters for optimal control
float Kp = 2.5; // Proportional gain
float Ki = 0.5; // Integral gain
float Kd = 0.1; // Derivative gain

// Variables for control
float setPoint = 30.0; // Desired temperature in °C
float currentTemp = 0.0; // Current temperature reading
float error = 0.0;       // Error value
float previousError = 0.0; // Previous error for derivative term
float integral = 0.0;    // Integral accumulator
float output = 0.0;      // Output PWM value

void setup() {
  Serial.begin(9600);
  pinMode(heaterPin, OUTPUT);
  Serial.println("Automatic Temperature Controller");
}

void loop() {
  // Read temperature from LM35 sensor
  int sensorValue = analogRead(tempSensorPin);
  currentTemp = (sensorValue * 5.0 / 1023.0) * 100.0; // Convert to Celsius

  // Calculate error
  error = setPoint - currentTemp;

  // Calculate integral term
  integral += error;

  // Calculate derivative term
  float derivative = error - previousError;

  // Compute control output
  output = Kp * error + Ki * integral + Kd * derivative;

  // Limit output to PWM range (0-255)
  output = constrain(output, 0, 255);

  // Apply control to heater
  analogWrite(heaterPin, output);

  // Update previous error
  previousError = error;

  // Print for monitoring
  Serial.print("Temperature: ");
  Serial.print(currentTemp);
  Serial.print(" °C, Output: ");
  Serial.println(output);

  // Delay for stability
  delay(1000);
}

How the Code Works

This code implements a PID (Proportional-Integral-Derivative) control algorithm to maintain a target temperature of 30°C. It begins by reading the analog signal from the LM35 sensor, converting that value into a Celsius temperature, and calculating the error—the difference between the desired setpoint and the actual reading. The script then computes three distinct terms: the Proportional term reacts to the current error, the Integral term accounts for accumulated past errors to eliminate steady state offset, and the Derivative term predicts future error trends to prevent overshoot. These components are summed to generate a control signal, which is constrained to a 0–255 PWM range and sent to the heater via pin 9, effectively adjusting the heat output in real-time to achieve a stable temperature.

Video : How I made the circuit in Proteus




Related:

Post a Comment

Previous Post Next Post