/********************************************************
PID Basic simulated heater Example
Reading analog input 0 to control analog PWM output 3
********************************************************/
// This code simulates a 20W heater block controlled by a PID algorithm.
// It allows you to vary the temperature setpoint with a potentiometer and observe how the PID controller responds to drive the heater to reach the desired temperature.
//
// This example can be simulated using the link provided below:
// Simulation at https://wokwi.com/projects/358122536159671297
//
// This code is inspired and can be referenced with other projects on Wokwi:
// Based on previous simulations:
// https://wokwi.com/projects/357374218559137793
// https://wokwi.com/projects/356437164264235009
#include "PID_v1.h" // Include the PID library, available at https://github.com/br3ttb/Arduino-PID-Library
// Define Variables for PID Control
double Setpoint, Input, Output; // Variables to hold the setpoint, the actual temperature, and the PID output
// Specify the initial tuning parameters for the PID
double Kp = 17, Ki = 0.3, Kd = 2; // PID constants for proportional, integral, and derivative terms
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, P_ON_E, DIRECT); // Initialize the PID object
// Define pin assignments
const int PWM_PIN = 3; // Pin connected to the PWM input of the heater
const int INPUT_PIN = -1; // Analog pin number for reading the actual temperature (set <0 if in simulation)
const int SETPOINT_PIN = A1; // Analog pin connected to the potentiometer for setting the desired temperature
const int SETPOINT_INDICATOR = 6; // Optional: PWM pin to indicate setpoint level
const int INPUT_INDICATOR = 5; // Optional: PWM pin to indicate input level
void setup() {
Serial.begin(115200); // Begin serial communication at 115200 baud
Serial.println(__FILE__); // Output the filename to the serial monitor
myPID.SetOutputLimits(-4, 255); // Set output limits for the PID
// Configure pin modes for the indicator LEDs if applicable
if (SETPOINT_INDICATOR >= 0) pinMode(SETPOINT_INDICATOR, OUTPUT);
if (INPUT_INDICATOR >= 0) pinMode(INPUT_INDICATOR, OUTPUT);
Setpoint = 0; // Initialize the setpoint to 0
myPID.SetMode(AUTOMATIC); // Turn the PID to AUTOMATIC mode
if(INPUT_PIN>0){
Input = analogRead(INPUT_PIN); // Read the initial temperature
}else{
Input = simPlant(0.0,1.0); // Simulate initial heating
}
Serial.println("Setpoint Input Output Watts"); // Print header for serial output
}
void loop() {
// Simulate or read actual heater data
float heaterWatts = (int)Output * 20.0 / 255; // Convert PID output to Watts
if (INPUT_PIN > 0 ) {
Input = analogRead(INPUT_PIN); // Read the actual temperature from sensor
} else {
float blockTemp = simPlant(heaterWatts, Output>0 ? 1.0 : 1 - Output); // Simulate heating
Input = blockTemp; // Update input with simulated value
}
// Compute PID values and update outputs
if (myPID.Compute()) {
analogWrite(PWM_PIN, (int)Output); // Update the heater control pin
Setpoint = analogRead(SETPOINT_PIN) / 4; // Read and scale the setpoint from potentiometer
// Update the indicators if applicable
if (INPUT_INDICATOR >= 0) analogWrite(INPUT_INDICATOR, Input);
if (SETPOINT_INDICATOR >= 0) analogWrite(SETPOINT_INDICATOR, Setpoint);
}
report(); // Function to report PID values and statuses
}
void report(void) {
static uint32_t last = 0;
const int interval = 1000; // Reporting interval
if (millis() - last > interval) {
last += interval;
// Output the current PID values and statuses
Serial.print(" SetPoint:");
Serial.print(Setpoint);
Serial.print(" Feedback:");
Serial.print(Input);
Serial.print(" Plant:");
Serial.print( Output);
Serial.print(" Integral:");
Serial.print(myPID.GetKd());
Serial.print(" Diff:");
Serial.print(myPID.GetKi());
Serial.println();
}
}
float simPlant(float Q,float hfactor) { // Function to simulate the heater plant
// Constants for the simulation: thermal properties, area, mass, and ambient temperature
float h = 5 * hfactor ; // Variable thermal convection coefficient
float Cps = 0.89; // Heat capacity
float area = 1e-4; // Surface area for heat transfer
float mass = 10 ; // Mass of the heater block
float Tamb = 25; // Ambient temperature
static float T = Tamb; // Static variable to hold the block temperature
static uint32_t last = 0;
uint32_t interval = 100; // Time interval for simulation updates
if (millis() - last >= interval) {
last += interval;
// Simple model for heat transfer in a solid block
T = T + Q * interval / 1000 / mass / Cps - (T - Tamb) * area * h; // Calculate the new temperature
}
return T; // Return the new block temperature
}
255°
Setpoint
0°
PID_v1 with Heater Simulation
SP___PV___CV
°C___°C___Watt