// Libraries
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>
#include <Fonts/FreeSans9pt7b.h>
// OLED setup
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define I2C_SDA 6
#define I2C_SCL 7
// Rotary Encoder
#define ENCODER_CLK 10
#define ENCODER_DT 11
#define ENCODER_BTN 23
// Long press threshold (in ms)
#define LONG_PRESS_DURATION 3000
// Default temperature setting
#define DEFAULT_TEMP 40.0
// Temperature Colors
enum Color { Y = 0, M, C, K, W, G, COLOR_COUNT };
const char* colorNames[] = {"Y", "M", "C", "K", "W", "G"};
// EEPROM Addresses
int eepromAddr[COLOR_COUNT] = {0, 4, 8, 12, 16, 20};
// States
bool inSetup = false;
bool showSetTemp = false; // false = แสดงอุณหภูมิปัจจุบัน, true = แสดงอุณหภูมิที่ตั้งค่า
unsigned long btnPressTime = 0;
bool btnPressed = false;
bool btnLongPressHandled = false;
bool btnLongPressTriggered = false;
bool waitReleaseToContinue = false;
bool blink = true;
unsigned long lastBlink = 0;
#define BLINK_INTERVAL 500 // ms
// activity time
unsigned long lastActivityTime = 0;
const unsigned long timeoutDuration = 30000; // 30 วินาที
// Current selection
volatile Color currentColor = Y;
float setTemps[COLOR_COUNT] = {DEFAULT_TEMP, DEFAULT_TEMP, DEFAULT_TEMP, DEFAULT_TEMP, DEFAULT_TEMP, DEFAULT_TEMP};
float tempBackup[COLOR_COUNT];
// Interrupt state
volatile bool rotated = false;
volatile int direction = 0; // 1 = CW, -1 = CCW
// Function declarations
float ReadTemp(Color color, float setPoint) {
return setPoint + (color * 2); // Simulated temperature
}
void IRAM_ATTR handleEncoder() {
static unsigned long lastInterruptTime = 0;
unsigned long interruptTime = millis();
if (interruptTime - lastInterruptTime > 70) {
int dtState = digitalRead(ENCODER_DT);
direction = (dtState == LOW) ? 1 : -1;
rotated = true;
lastInterruptTime = interruptTime;
}
}
void saveSettings() {
for (int i = 0; i < COLOR_COUNT; i++) {
EEPROM.put(eepromAddr[i], setTemps[i]);
}
EEPROM.commit();
for (int i = 0; i < COLOR_COUNT; i++) {
tempBackup[i] = setTemps[i];
}
}
void loadSettings() {
for (int i = 0; i < COLOR_COUNT; i++) {
EEPROM.get(eepromAddr[i], setTemps[i]);
if (isnan(setTemps[i]) || setTemps[i] < 0.0 || setTemps[i] > 100.0) setTemps[i] = DEFAULT_TEMP;
tempBackup[i] = setTemps[i];
}
}
void drawNormalScreen() {
display.clearDisplay();
display.setTextColor(WHITE);
display.setFont();
// display.setFont(NULL); // ใช้ฟอนต์ดั้งเดิม
display.setTextSize(2);
display.setCursor(0, 0);
display.print(colorNames[currentColor]);
// float temp = ReadTemp(currentColor, setTemps[currentColor]);
//float temp = showSetTemp ? setTemps[currentColor] : ReadTemp(currentColor, setTemps[currentColor]);
float temp;
if (showSetTemp) {
temp = setTemps[currentColor];
display.setCursor(110, 0);
display.print("s");
}
else {
temp = ReadTemp(currentColor, setTemps[currentColor]);
display.setCursor(110, 0);
display.print("");
}
display.setFont();
display.setTextSize(3);
display.setCursor(30, 20);
display.print(temp, 1);
display.setTextSize(2);
display.setCursor(95, 50);
display.print((char)247); // แสดงสัญลักษณ์องศา (°)
display.print("C");
// display.setFont(); // ใช้ฟอนต์มาตรฐาน
// display.setTextSize(1);
// display.setCursor(0, 0);
// display.print("Temp: ");
// display.print(temp, 1); // แสดงค่าอุณหภูมิ 1 ตำแหน่งทศนิยม
// display.print((char)247); // แสดงสัญลักษณ์องศา (°)
// display.print("C"); // แสดงตัวอักษร C
display.display();
}
void drawSetupScreen() {
display.clearDisplay();
display.setTextColor(WHITE);
display.setFont();
display.setTextSize(2);
display.setCursor(0, 0);
display.print("SET " + String(colorNames[currentColor]));
if (blink) {
display.setFont();
display.setTextSize(3);
display.setCursor(30, 20);
display.print(setTemps[currentColor], 1);
}
display.setTextSize(2);
display.setCursor(100, 50);
display.print((char)247); // แสดงสัญลักษณ์องศา (°)
display.print("C");
display.display();
}
void setup() {
Serial.begin(115200);
Wire.begin(I2C_SDA, I2C_SCL);
EEPROM.begin(64);
loadSettings();
pinMode(ENCODER_CLK, INPUT_PULLUP);
pinMode(ENCODER_DT, INPUT_PULLUP);
pinMode(ENCODER_BTN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ENCODER_CLK), handleEncoder, RISING);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.setTextColor(WHITE);
display.clearDisplay();
display.display();
lastActivityTime = millis();
}
void loop() {
if (rotated) {
noInterrupts();
if (inSetup) {
if (direction == 1) {
setTemps[currentColor] += 0.1;
} else if (direction == -1) {
setTemps[currentColor] -= 0.1;
}
} else {
if (direction == 1) {
currentColor = (Color)((currentColor + 1) % COLOR_COUNT);
} else if (direction == -1) {
currentColor = (Color)((currentColor + COLOR_COUNT - 1) % COLOR_COUNT);
}
}
rotated = false;
interrupts();
}
int btnState = digitalRead(ENCODER_BTN);
if (btnState == LOW) {
if (!btnPressed) {
btnPressed = true;
btnLongPressHandled = false;
btnPressTime = millis();
} else if (!btnLongPressHandled && millis() - btnPressTime > LONG_PRESS_DURATION) {
btnLongPressHandled = true;
if (!inSetup) {
inSetup = true;
for (int i = 0; i < COLOR_COUNT; i++) tempBackup[i] = setTemps[i];
} else {
saveSettings();
inSetup = false;
}
}
} else {
if (btnPressed) {
if (!btnLongPressHandled) {
if (inSetup) {
for (int i = 0; i < COLOR_COUNT; i++) setTemps[i] = tempBackup[i];
inSetup = false;
} else {
showSetTemp = !showSetTemp; // สลับการแสดงผล
}
}
btnPressed = false;
btnLongPressHandled = false;
}
}
if (millis() - lastBlink > BLINK_INTERVAL) {
blink = !blink;
lastBlink = millis();
}
// ตรวจสอบว่ามีการปรับค่า (เช่น การหมุน Encoder หรือกดปุ่ม)
if (rotated || btnPressed) {
lastActivityTime = millis(); // อัปเดตเวลาปัจจุบัน
}
// ตรวจสอบว่าเวลาที่ผ่านไปเกิน 30 วินาทีหรือไม่
if (millis() - lastActivityTime > timeoutDuration) {
if (inSetup) {
inSetup = false; // กลับไปที่โหมดปกติ
saveSettings(); // บันทึกการตั้งค่า (ถ้าจำเป็น)
}
}
if (inSetup) {
drawSetupScreen();
} else {
drawNormalScreen();
}
}