#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
// กำหนดพินสำหรับ Relay
const int relayPin = 2;
// กำหนดพินสำหรับ Push Buttons
const int buttonGreenPin = 4; // ปุ่มสีเขียว (Start)
const int buttonRedPin = 3; // ปุ่มสีแดง (Stop)
// กำหนดพินสำหรับ LED
const int greenLedPin = 1; // LED สีเขียว (Pin 1)
const int redLedPin = 5; // LED สีแดง (Pin 5)
// กำหนดพินสำหรับ Membrane Keypad
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'.', '0', '#', 'D'} // เปลี่ยน '*' เป็น '.'
};
byte rowPins[ROWS] = {13, 12, 11, 10};
byte colPins[COLS] = {9, 8, 7, 6};
// กำหนด LCD
LiquidCrystal_I2C lcd(0x27, 16, 2);
Keypad customKeypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// ตัวแปรสำหรับเก็บค่าเวลา (เปลี่ยนเป็น float เพื่อรองรับทศนิยม)
float totalHours = 0.0;
float operatingTime = 0.0; // ในหน่วยนาที
float breakTime = 0.0; // ในหน่วยนาที
// ตัวแปรสำหรับการทำงาน
bool isRunning = false;
bool isPaused = false;
int completedRounds = 0;
int totalRounds = 0;
unsigned long startTime = 0;
float remainingTime = 0.0; // เปลี่ยนเป็น float
bool isInOperating = true;
// สถานะปุ่ม
int redButtonPressCount = 0;
String inputBuffer = "";
// ตัวแปรสำหรับสลับการแสดงผล
unsigned long lastDisplaySwitchTime = 0; // เก็บเวลาล่าสุดที่สลับการแสดงผล
bool showRemainingTime = true; // ควบคุมการแสดงผล: true = แสดงเวลาที่เหลือ, false = แสดงรอบที่ทำเสร็จ
void getInput(const char* prompt, float& value) {
lcd.clear();
lcd.print(prompt);
lcd.setCursor(0, 1);
while (true) {
char key = customKeypad.getKey();
if (key != NO_KEY) {
if (key == '#') { // ลบ
if (inputBuffer.length() > 0) { // ตรวจสอบว่า inputBuffer ไม่ว่าง
inputBuffer.remove(inputBuffer.length() - 1);
lcd.setCursor(0, 1);
lcd.print(" "); // ล้างบรรทัด
lcd.setCursor(0, 1);
lcd.print(inputBuffer);
}
} else if (key == 'A') { // ยืนยัน
if (inputBuffer.length() > 0) { // ตรวจสอบว่า inputBuffer ไม่ว่าง
value = inputBuffer.toFloat(); // ใช้ toFloat() แทน toInt()
inputBuffer = "";
break;
}
} else if (isdigit(key) || key == '.') { // ยอมรับตัวเลขและจุดทศนิยม
inputBuffer += key;
lcd.setCursor(0, 1);
lcd.print(inputBuffer);
}
}
}
}
bool confirmStart() {
lcd.clear();
lcd.print("Are you ready?");
lcd.setCursor(0, 1);
lcd.print("Yes(Green) No");
while (true) {
if (digitalRead(buttonGreenPin) == LOW) {
return true; // ยืนยัน
} else if (customKeypad.getKey() == 'B') {
return false; // ย้อนกลับ
}
}
}
void controlLeds() {
unsigned long currentMillis = millis();
static unsigned long previousMillisGreen = 0;
static unsigned long previousMillisRed = 0;
const long interval = 500; // ระยะเวลากระพริบ (500 ms)
// ควบคุม LED สีเขียว (Pin 1)
if (isRunning && !isPaused) {
if (currentMillis - previousMillisGreen >= interval) {
previousMillisGreen = currentMillis;
digitalWrite(greenLedPin, !digitalRead(greenLedPin)); // สลับสถานะ LED
}
} else {
digitalWrite(greenLedPin, LOW); // ปิด LED สีเขียวหากไม่ได้ทำงาน
}
// ควบคุม LED สีแดง (Pin 5)
if (isPaused) {
if (currentMillis - previousMillisRed >= interval) {
previousMillisRed = currentMillis;
digitalWrite(redLedPin, !digitalRead(redLedPin)); // สลับสถานะ LED
}
} else {
digitalWrite(redLedPin, LOW); // ปิด LED สีแดงหากไม่ได้หยุดชั่วคราว
}
}
void startOperation() {
totalRounds = (totalHours * 60) / (operatingTime + breakTime); // คำนวณจำนวนรอบ
completedRounds = 0;
isRunning = true;
while (isRunning) {
if (isInOperating) {
// ทำงาน
remainingTime = operatingTime * 60; // แปลงเป็นวินาที
digitalWrite(relayPin, HIGH);
lcd.clear();
lcd.print("Operating...");
} else {
// พัก
remainingTime = breakTime * 60; // แปลงเป็นวินาที
digitalWrite(relayPin, LOW);
lcd.clear();
lcd.print("On Break...");
}
startTime = millis();
while (remainingTime > 0) {
if (digitalRead(buttonRedPin) == LOW) {
redButtonPressCount++;
delay(500); // ป้องกันการกดซ้ำ
if (redButtonPressCount == 1) {
isPaused = true;
digitalWrite(relayPin, LOW); // ปิด Relay เมื่อหยุดชั่วคราว
lcd.clear();
lcd.print("Paused...");
} else if (redButtonPressCount == 2) {
resetSystem();
return;
}
} else if (isPaused && digitalRead(buttonGreenPin) == LOW) {
isPaused = false;
redButtonPressCount = 0;
digitalWrite(relayPin, isInOperating ? HIGH : LOW); // เปิด Relay กลับมาทำงาน
lcd.clear();
lcd.print(isInOperating ? "Operating..." : "On Break...");
}
if (!isPaused) {
unsigned long currentTime = millis();
remainingTime = max(0.0, (float)(operatingTime * 60 - ((currentTime - startTime) / 1000.0))); // คำนวณเวลาที่เหลือ
// สลับการแสดงผลทุกๆ 15 วินาที
if ((currentTime - lastDisplaySwitchTime) >= 15000) { // 15000 ms = 15 วินาที
showRemainingTime = !showRemainingTime; // สลับค่า
lastDisplaySwitchTime = currentTime; // อัปเดตเวลาล่าสุด
}
// แสดงผลบน LCD
lcd.setCursor(0, 1);
if (showRemainingTime) {
lcd.print("Remain: ");
lcd.print((int)remainingTime); // แสดงเวลาที่เหลือในหน่วยวินาที
lcd.print("s ");
} else {
lcd.print("Comp: ");
lcd.print(completedRounds); // แสดงรอบที่ทำเสร็จไปแล้ว
lcd.print("/");
lcd.print(totalRounds); // แสดงรอบทั้งหมด
lcd.print(" rounds"); // เพิ่มคำว่า "rounds" เพื่อชัดเจน
}
}
// ควบคุม LED
controlLeds();
delay(100);
}
// สลับระหว่าง Operating และ Break
isInOperating = !isInOperating;
if (isInOperating) {
completedRounds++;
}
if (completedRounds >= totalRounds) {
isRunning = false;
digitalWrite(relayPin, LOW); // ปิด Relay เมื่อเสร็จสิ้น
lcd.clear();
lcd.print("Operation Done!");
}
}
}
void resetSystem() {
isRunning = false;
isPaused = false;
completedRounds = 0;
redButtonPressCount = 0;
digitalWrite(relayPin, LOW); // ปิด Relay ทันทีเมื่อรีเซ็ต
lcd.clear();
lcd.print("System Reset");
delay(2000);
// เริ่มต้นใหม่โดยให้กรอกเวลาอีกครั้ง
setup(); // เรียก setup() เพื่อเริ่มต้นกระบวนการใหม่
}
void setup() {
pinMode(relayPin, OUTPUT);
pinMode(buttonGreenPin, INPUT_PULLUP);
pinMode(buttonRedPin, INPUT_PULLUP);
// กำหนดโหมดสำหรับ LED
pinMode(greenLedPin, OUTPUT);
pinMode(redLedPin, OUTPUT);
lcd.init();
lcd.backlight();
lcd.clear();
// รับค่าเวลา (ใช้ float แทน int)
getInput("Total hour(hr):", totalHours);
getInput("Operating(min):", operatingTime);
getInput("Break(min):", breakTime);
// ยืนยันการทำงาน
if (confirmStart()) {
startOperation();
} else {
resetSystem();
}
}
void loop() {
// ไม่มีการทำงานใน loop เพราะทุกอย่างถูกควบคุมใน setup()
}