#include "PID_RT.h"
PID_RT PID;
const int PWM_PIN = 3; // UNO PWM pin
const int INPUT_PIN = -1; // Analog pin for Input (set <0 for simulation)
const int SETPOINT_PIN = A1; // Analog pin for Setpoint Potentiometer
const int SETPOINT_INDICATOR = 6; // PWM pin for indicating setpoint
const int INPUT_INDICATOR = 5; // PWM pin for indicating Input
int op = 0;
float input = 0;
#include <LiquidCrystal_I2C.h>
#define I2C_ADDR 0x27
#define LCD_COLUMNS 20
#define LCD_LINES 4
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
if (SETPOINT_INDICATOR >= 0) pinMode(SETPOINT_INDICATOR, OUTPUT);
if (INPUT_INDICATOR >= 0) pinMode(INPUT_INDICATOR, OUTPUT);
PID.setPoint(125);
PID.setOutputRange(0, 255); // PWM range
PID.setInterval(50);
PID.setK(2, 5, 1);
PID.start();
lcd.init();
lcd.backlight();
Serial.println("Setpoint Input Output");
op = analogRead(A0);
}
void loop()
{
float heaterWatts = ((int)op) * 20.0 / 255; // 20W heater
if (INPUT_PIN > 0 ) {
input = analogRead(INPUT_PIN);
} else {
float blockTemp = simPlant(heaterWatts); // simulate heating
input = blockTemp; // read input from simulated heater block
}
if (PID.compute(input))
{
op = PID.getOutput();
analogWrite(PWM_PIN, op);
PID.setPoint(analogRead(SETPOINT_PIN) / 4); // Read setpoint from potentiometer
if (INPUT_INDICATOR >= 0) analogWrite(INPUT_INDICATOR, input);
if (SETPOINT_INDICATOR >= 0) analogWrite(SETPOINT_INDICATOR, PID.getSetPoint());
}
report();
reportLCD();
}
void report(void) {
static uint32_t last = 0;
const int interval = 1000;
if (millis() - last > interval) {
last += interval;
Serial.print("SP:");
Serial.print(PID.getSetPoint());
Serial.print(" PV:");
Serial.print(input);
Serial.print(" CV:");
Serial.println(op);
}
}
void reportLCD(void)
{
static uint32_t last = 0;
const int interval = 250;
if (millis() - last > interval) {
last += interval;
lcd.setCursor(0, 0);
lcd.print("PV:");
lcd.print(input, 3);
lcd.print(" CV:");
lcd.print(op, 3);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print("SP:");
lcd.print(PID.getSetPoint(), 3);
lcd.setCursor(0, 2);
lcd.print(" ");
lcd.print(" Reyhaneh");
lcd.setCursor(0, 3);
lcd.print(' ');
lcd.println();
}
}
float simPlant(float Q) { // ورودی حرارتی به وات (یا ژول بر ثانیه)
// شبیهسازی یک بلوک آلومینیومی به ابعاد 1*1*2 سانتیمتر با یک هیتر و خنکشدن محیطی سرد
float C = 237; // W/mK thermal conduction coefficient for Al
float h = 15 ; // W/m2K thermal convection coefficient for Al passive
float Cps = 0.89; // J/g°C
float area = 1e-4; // m2 area for convection
float mass = 10 ; // g
float Tamb = 25; // °C
static float T = Tamb; // °C
static uint32_t last = 0;
uint32_t interval = 100; // ms
if (millis() - last >= interval) {
last += interval;
float Qconv = (T - Tamb) * area * h;
T = T + (Q - Qconv) * interval / 1000 / mass / Cps ;
}
return T;
}
255°
Setpoint
0°