#include <LiquidCrystal_I2C.h>
#include <PID_v1.h>
#define I2C_ADDR 0x27
#define LCD_COLUMNS 16
#define LCD_LINES 4
#define tempSensorPin A0
#define relayPin 2
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
int WindowSize = 5000;
unsigned long windowStartTime;
double setpoint, temperature, output;
//Specify the links and initial tuning parameters
PID pidControl(&temperature, &output, &setpoint, 10, 5, 5, DIRECT);
void setup() {
// Init
lcd.init();
lcd.backlight();
pinMode(tempSensorPin, INPUT);
pinMode(relayPin, OUTPUT);
// Print something
// lcd.setCursor(3, 0);
// lcd.print("Hello, world!");
lcd.setCursor(2, 1);
lcd.print("Wokwi Online IoT");
lcd.setCursor(0, 2);
lcd.print("Current T");
lcd.setCursor(10, 2);
lcd.print("Output %");
// lcd.setCursor(7, 3);
// lcd.print("Enjoy!");
windowStartTime = millis();
//initialize the variables we're linked to
setpoint = 60;
//tell the PID to range between 0 and the full window size
pidControl.SetOutputLimits(0, WindowSize);
//turn the PID on
pidControl.SetMode(AUTOMATIC);
}
void loop() {
float value = analogRead(A0);
float temperature = readTemperature();
lcd.setCursor(0, 3);
lcd.print(temperature, 1);
pidControl.Compute();
double outputPercent = 100. * output / 5000.;
lcd.setCursor(10, 3);
lcd.print(outputPercent, 1);
lcd.setCursor(0, 0);
lcd.print(output, 1);
/************************************************
turn the output pin on/off based on pid output
************************************************/
unsigned long now = millis();
if (now - windowStartTime > WindowSize)
{ //time to shift the Relay Window
windowStartTime += WindowSize;
}
if (output > now - windowStartTime) digitalWrite(relayPin, HIGH);
else digitalWrite(relayPin, LOW);
}
double readTemperature() {
const float BETA = 3950; // should match the Beta Coefficient of the thermistor
int analogValue = analogRead(A0);
double celsius = 1 / (log(1 / (1023. / analogValue - 1)) / BETA + 1.0 / 298.15) - 273.15;
return celsius;
}