#include <PID_v1.h>
#include <AccelStepper.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Pin Definitions
#define THERMISTOR_PIN A0
#define HEATER_PIN 9
#define MOTOR_STEP_PIN 3
#define MOTOR_DIR_PIN 2
#define MOTOR_EN_PIN 7
#define BUTTON_ACTION 4 // ปุ่มการทำงาน
#define BUTTON_STOP 5 // ปุ่มหยุดการทำงาน
// Thermistor Constants
#define SERIES_RESISTOR 4700
#define NOMINAL_RESISTANCE 100000
#define NOMINAL_TEMPERATURE 25
#define B_COEFFICIENT 3950
#define ADC_RESOLUTION 1023
// PID Variables
double TempSetpoint = 0;
double TempInput, TempOutput;
double Kp = 49, Ki = 2.9, Kd = 150;
PID tempPID(&TempInput, &TempOutput, &TempSetpoint, Kp, Ki, Kd, DIRECT);
// Stepper Motor Setup
AccelStepper stepper(AccelStepper::DRIVER, MOTOR_STEP_PIN, MOTOR_DIR_PIN);
bool motorActive = false;
unsigned long motorRunTime = 0; // เวลาในการทำงานของ Stepper Motor (หน่วย: วินาที)
unsigned long motorStartTime = 0;
// Menu and Button Variables
int actionStep = 0; // ลำดับการทำงานของปุ่ม 1
unsigned long lastButtonPress = 0;
const unsigned long buttonDebounceDelay = 200;
// Temperature Threshold Flags
bool isTemp210Reached = false; // อุณหภูมิแตะ 210°C แล้วหรือยัง
bool isTemp220Reached = false; // อุณหภูมิแตะ 220°C แล้วหรือยัง
// LCD Setup
LiquidCrystal_I2C lcd(0x27, 16, 2);
String previousLine1 = ""; // บันทึกข้อความแถว 1 ก่อนหน้า
String previousLine2 = ""; // บันทึกข้อความแถว 2 ก่อนหน้า
String previousLine3 = ""; // บันทึกข้อความแถว 2 ก่อนหน้า
void setup() {
// PID Setup
pinMode(HEATER_PIN, OUTPUT);
pinMode(MOTOR_EN_PIN, OUTPUT);
tempPID.SetMode(AUTOMATIC);
tempPID.SetOutputLimits(0, 255);
// Stepper Motor Setup
stepper.setMaxSpeed(6000);
stepper.setAcceleration(1000);
stepper.setSpeed(1000);
// Button Setup
pinMode(BUTTON_ACTION, INPUT_PULLUP);
pinMode(BUTTON_STOP, INPUT_PULLUP);
// LCD Setup
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("DIY-PET_Dachawat");
lcd.setCursor(0, 1);
lcd.print("phon_098-3246220");
delay(3000);
actionStep = 0; // รีเซ็ตลำดับการทำงาน
TempSetpoint = 0; // ตั้งอุณหภูมิเป็น 0°C
motorActive = false; // ปิด Stepper Motor
motorRunTime = 0; // รีเซ็ตเวลา
isTemp210Reached = false; // รีเซ็ตสถานะอุณหภูมิ
isTemp220Reached = false;
digitalWrite(MOTOR_EN_PIN,HIGH);
}
void loop() {
Serial.begin(9600);\
Serial.println();
// อ่านค่าอุณหภูมิและควบคุมฮีตเตอร์
TempInput = readTemperature();
tempPID.Compute();
analogWrite(HEATER_PIN, TempOutput);
// ตรวจจับว่าอุณหภูมิแตะเกณฑ์แล้วหรือยัง
if (TempInput >= 210) {
isTemp210Reached = true;
}
if (TempInput >= 220) {
isTemp220Reached = true;
}
// จัดการปุ่มและลำดับการทำงาน
handleActionButton();
handleStopButton();
// ตรวจสอบการทำงานของ Stepper Motor
handleStepperMotor();
// อัปเดตจอ LCD
updateDisplay();
}
// ฟังก์ชันอ่านอุณหภูมิจาก Thermistor
float readTemperature() {
int analogValue = analogRead(THERMISTOR_PIN);
if (analogValue == 0) {
return NAN;
}
float resistance = (float)(ADC_RESOLUTION - analogValue) * SERIES_RESISTOR / analogValue;
float temperature = resistance / NOMINAL_RESISTANCE;
temperature = log(temperature);
temperature /= B_COEFFICIENT;
temperature += 1.0 / (NOMINAL_TEMPERATURE + 273.15);
temperature = 1.0 / temperature;
temperature -= 273.15;
return temperature;
}
// ฟังก์ชันจัดการปุ่มการทำงาน
void handleActionButton() {
if (digitalRead(BUTTON_ACTION) == LOW && millis() - lastButtonPress >= buttonDebounceDelay) {
lastButtonPress = millis();
switch (actionStep) {
case 0: // กดครั้งแรก ตั้งอุณหภูมิ 210°C
TempSetpoint = 210;
actionStep = 1;
break;
case 1: // กดครั้งที่ 2 ตั้งอุณหภูมิ 220°C (ต้องแตะ 210°C แล้ว)
if (isTemp210Reached) {
TempSetpoint = 220;
actionStep = 2;
}
break;
default: // กดครั้งที่ 3 ตั้งเวลาสำหรับ Stepper Motor (ต้องแตะ 220°C แล้ว)
if (isTemp220Reached) {
if (motorRunTime == 0) motorRunTime = 600; // เริ่มต้น 30 นาที
else if (motorRunTime < 600) motorRunTime += 60; // เพิ่มทีละ 5 นาที
isTemp220Reached = false;
digitalWrite(MOTOR_EN_PIN,LOW);
motorActive = true;
motorStartTime = millis();
actionStep = 3;
}
if(motorRunTime>=3660){
motorRunTime = 0;
}
break;
/*default: // รีเซ็ตลำดับ
if(motorRunTime<=3600){
motorRunTime += 300;
motorStartTime = millis();
if(motorRunTime>=3600){
motorRunTime = 0;
}
}
break;*/
}
}
}
// ฟังก์ชันจัดการปุ่มหยุด
void handleStopButton() {
if (digitalRead(BUTTON_STOP) == LOW && millis() - lastButtonPress >= buttonDebounceDelay) {
lastButtonPress = millis();
digitalWrite(MOTOR_EN_PIN,HIGH);
actionStep = 0; // รีเซ็ตลำดับการทำงาน
TempSetpoint = 0; // ตั้งอุณหภูมิเป็น 0°C
motorActive = false; // ปิด Stepper Motor
motorRunTime = 0; // รีเซ็ตเวลา
isTemp210Reached = false; // รีเซ็ตสถานะอุณหภูมิ
isTemp220Reached = false;
}
}
// ฟังก์ชันจัดการ Stepper Motor
void handleStepperMotor() {
if (motorActive && motorRunTime > 0) {
if (millis() - motorStartTime >= 1000) {
motorRunTime--;
motorStartTime = millis();
}
stepper.runSpeed(); // หมุนมอเตอร์
}
if (motorRunTime == 0) {
motorActive = false;
}
}
// ฟังก์ชันอัปเดตจอ LCD
void updateDisplay() {
String line1 = "";
String line2 = "";
if (actionStep == 1) { // แสดงสถานะตั้งอุณหภูมิ 210°C
line1 = "Set Temp: 210*C ";
line2 = "Cur Temp: " + String((int)TempInput) + "*C ";
} else if (actionStep == 2) { // แสดงสถานะตั้งอุณหภูมิ 220°C
line1 = "Set Temp: 220*C ";
line2 = "Cur Temp: " + String((int)TempInput) + "*C ";
} else if (actionStep == 3) { // แสดงเวลาที่ตั้งไว้สำหรับ Stepper Motor
line1 = "motr:" + String(motorActive ? " ON " : "OFF");
lcd.setCursor(9, 0);
lcd.print("T:");
lcd.setCursor(11, 0);
lcd.print((int)TempInput);
// คำนวณเวลาที่เหลือในรูปแบบ นาที.วินาที
int minutes = motorRunTime / 60; // นาทีที่เหลือ
int seconds = motorRunTime % 60; // วินาทีที่เหลือ
line2 = "Time: " + String(minutes) + "." + (seconds < 10 ? "0" : "") + String(seconds) + " min";
} else { // หน้าแรก
line1 = "System Ready....";
line2 = " Temp:" + String((int)TempInput) + "*C ";
}
// อัปเดตเฉพาะข้อความที่เปลี่ยนแปลง
if (line1 != previousLine1) {
lcd.setCursor(0, 0);
lcd.print(line1);
previousLine1 = line1;
}
if (line2 != previousLine2) {
lcd.setCursor(0, 1);
lcd.print(line2);
previousLine2 = line2;
}
}