/*// ---Have in mind---
*This code is a first version for the reflow hot plate project.
*Tutorial here: http://electronoobs.com/eng_arduino_tut161.php
*Please be careful working with "High Voltage" and double check everything.
*Only use this project with supervision, never leave it plugged.
*You can use this code at your own risk. I don't offer any guarantee that you
*will get the same results as I did and you might have to adjsut some PID values */
//* RAM: [=== ] 29.5 % (used 604 bytes from 2048 bytes)
//* Flash : [=== ] 32.1 % (used 9864 bytes from 30720 bytes)
#include <Arduino.h>
#include <thermistor.h> // miguel5612/ThermistorLibrary@^1.0.6
thermistor therm1(A0, 0); // The 3950 Thermistor conencted on A0
// LCD config
#include <Wire.h> // Included by Arduino IDE
#include <LiquidCrystal_I2C.h> // marcoschwartz/LiquidCrystal_I2C@^1.1.4
LiquidCrystal_I2C lcd(0x27, 16, 2); // Define LCD address as 0x27. Also try 0x3f if it doesn't work.
//* Inputs and Outputs
int but_1 = 12;
int but_2 = 11;
int but_3 = 10;
int but_4 = 9;
int SSR = 3;
int buzzer = 6;
int Thermistor_PIN = A0;
//* Variables
unsigned int millis_before, millis_before_2; // We use these to create the loop refresh rate
unsigned int millis_now = 0; // use
float refresh_rate = 500; // LCD refresh rate. You can change this if you want
float pid_refresh_rate = 50; // PID Refresh rate
float seconds = 0; // Variable used to store the elapsed time
int running_mode = 0; // We store the running selected mode here
int selected_mode = 0; // Selected mode for the menu
int max_modes = 3; // For now, we only work with 1 mode...
bool but_3_state = true; // Store the state of the button (HIGH OR LOW)
bool but_4_state = true; // Store the state of the button (HIGH OR LOW)
float temperature = 0; // Store the temperature value here
float preheat_setpoint = 140; // Mode 1 preheat ramp value is 140-150ºC
float soak_setpoint = 150; // Mode 1 soak is 150ºC for a few seconds
float reflow_setpoint = 200; // Mode 1 reflow peak is 200ºC
float temp_setpoint = 0; // Used for PID control
float pwm_value = 255; // The SSR is OFF with HIGH, so 255 PWM would turn OFF the SSR
float MIN_PID_VALUE = 0; // min PID value
float MAX_PID_VALUE = 180; // Max PID value. You can change this.
float cooldown_temp = 40; // When is ok to touch the plate
//* PID VARIABLES
float Kp = 2; // Mine was 2
float Ki = 0.0025; // Mine was 0.0025
float Kd = 9; // Mine was 9
float PID_Output = 0;
float PID_P, PID_I, PID_D;
float PID_ERROR, PREV_ERROR;
//***** SETUP
void setup()
{
// Define the pins as outputs or inputs
pinMode(SSR, OUTPUT);
digitalWrite(SSR, HIGH); // Make sure we start with the SSR OFF (is off with HIGH)
pinMode(buzzer, OUTPUT);
digitalWrite(buzzer, LOW);
pinMode(but_1, INPUT_PULLUP);
pinMode(but_2, INPUT_PULLUP);
pinMode(but_3, INPUT_PULLUP);
pinMode(but_4, INPUT_PULLUP);
pinMode(Thermistor_PIN, INPUT);
lcd.init(); // Init the LCD
lcd.noBacklight(); // Activate backlight
Serial.begin(9600);
tone(buzzer, 1800, 200);
millis_before = millis();
millis_now = millis();
}
//***** LOOP
void loop()
{
millis_now = millis();
if (millis_now - millis_before_2 > pid_refresh_rate)
{ // Refresh rate of the PID
millis_before_2 = millis();
temperature = therm1.analog2temp();
if (running_mode == 1)
{
if (temperature < preheat_setpoint)
{
temp_setpoint = seconds * 1.666; // Reach 150ºC till 90s (150/90=1.666)
}
if (temperature > preheat_setpoint && seconds < 90)
{
temp_setpoint = soak_setpoint;
}
else if (seconds > 90 && seconds < 110)
{
temp_setpoint = reflow_setpoint;
}
// Calculate PID
PID_ERROR = temp_setpoint - temperature;
PID_P = Kp * PID_ERROR;
PID_I = PID_I + (Ki * PID_ERROR);
PID_D = Kd * (PID_ERROR - PREV_ERROR);
PID_Output = PID_P + PID_I + PID_D;
// Define maximun PID values
if (PID_Output > MAX_PID_VALUE)
{
PID_Output = MAX_PID_VALUE;
}
else if (PID_Output < MIN_PID_VALUE)
{
PID_Output = MIN_PID_VALUE;
}
// Since the SSR is ON with LOW, we invert the pwm singal
pwm_value = 255 - PID_Output;
analogWrite(SSR, pwm_value); // We change the Duty Cycle applied to the SSR
PREV_ERROR = PID_ERROR;
if (seconds > 130)
{
digitalWrite(SSR, HIGH); // With HIGH the SSR is OFF
temp_setpoint = 0;// reset temp
running_mode = 10; // Cooldown mode
}
} // End of running_mode = 1
// Mode 10 is between reflow and cooldown
if (running_mode == 10)
{
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(" COMPLETE ");
tone(buzzer, 1800, 1000);
seconds = 0; // Reset timer
running_mode = 11; // Mode 11 is cooldown. SSR is OFF
delay(3000);
}
} // End of > millis_before_2 (Refresh rate of the PID code)
millis_now = millis();
if (millis_now - millis_before > refresh_rate)
{ // Refresh rate of prntiong on the LCD
millis_before = millis();
seconds = seconds + (refresh_rate / 1000); // We count time in seconds
// Mode 0 is with SSR OFF (we can selcet mode with buttons)
if (running_mode == 0)
{
digitalWrite(SSR, HIGH); // With HIGH the SSR is OFF
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("T: ");
lcd.print(temperature, 1);
lcd.setCursor(9, 0);
lcd.print("SSR OFF");
lcd.setCursor(0, 1);
if (selected_mode == 0)
{
lcd.print("Select Mode");
}
else if (selected_mode == 1)
{
lcd.print("MODE 1");
}
else if (selected_mode == 2)
{
lcd.print("MODE 2");
}
else if (selected_mode == 3)
{
lcd.print("MODE 3");
}
} // End of running_mode = 0
// Mode 11 is cooldown. SSR is OFF
else if (running_mode == 11)
{
if (temperature < cooldown_temp)
{
running_mode = 0;
tone(buzzer, 1000, 100);
}
digitalWrite(SSR, HIGH); // With HIGH the SSR is OFF
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("T: ");
lcd.print(temperature, 1);
lcd.setCursor(9, 0);
lcd.print("SSR OFF");
lcd.setCursor(0, 1);
lcd.print(" COOLDOWN ");
} // end of mode 11 is cooldown. SSR is OFF
// Mode 1 is the PID runnind with selected mode 1
else if (running_mode == 1)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("T: ");
lcd.print(temperature, 1);
lcd.setCursor(9, 0);
lcd.print("SSR ON");
lcd.setCursor(0, 1);
lcd.print("S");
lcd.print(temp_setpoint, 0);
lcd.setCursor(5, 1);
lcd.print("PWM");
lcd.print(pwm_value, 0);
lcd.setCursor(12, 1);
lcd.print(seconds, 0);
lcd.print("s");
} // End of running_mode == 1
}
///////////////////////Button detection////////////////////////////
///////////////////////////////////////////////////////////////////
if (!digitalRead(but_3) && but_3_state)
{
but_3_state = false;
selected_mode++;
tone(buzzer, 2300, 40);
if (selected_mode > max_modes)
{
selected_mode = 0;
}
delay(150);
}
else if (digitalRead(but_3) && !but_3_state)
{
but_3_state = true;
}
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
if (!digitalRead(but_4) && but_4_state)
{
if (running_mode == 1)
{
digitalWrite(SSR, HIGH); // With HIGH the SSR is OFF
running_mode = 0;
selected_mode = 0;
tone(buzzer, 2500, 150);
delay(130);
tone(buzzer, 2200, 150);
delay(130);
tone(buzzer, 2000, 150);
delay(130);
}
but_4_state = false;
if (selected_mode == 0)
{
running_mode = 0;
}
else if (selected_mode == 1)
{
running_mode = 1;
tone(buzzer, 2000, 150);
delay(130);
tone(buzzer, 2200, 150);
delay(130);
tone(buzzer, 2400, 150);
delay(130);
seconds = 0; // Reset timer
}
}
else if (digitalRead(but_4) && !but_4_state)
{
but_4_state = true;
}
}