#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#include "RTClib.h"
#include "DHT.h"
RTC_DS1307 rtc; //Mạch thời gian thực
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 0x3C);
#define BUTTON_MOVE_PIN 2
#define BUTTON_SELECT_PIN 4
#define DHTPIN 16 //DHT22
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
enum MenuState {
HOME,
MAIN_MENU,
LED_SETTINGS,
SET_LED_1,
SET_LED_2,
SET_LED_3,
SET_LED_4,
SET_LED_5,
TEMPERATURE_SENSOR_SETTINGS,
SET_TEMP_STATE,
SET_TEMP_ALERT,
SET_TEMP_UNIT,
DATE_TIME_SETTINGS,
SET_TIME,
SET_DATE
};
MenuState menuState = HOME;
int cursorPosition = 1;
bool isButtonMovePressed = false;
bool isButtonSelectPressed = false;
bool isButtonMoveLongPressed = false;
unsigned long buttonMovePressStartTime = 0;
unsigned long lastButtonActionTime = 0;
void setup() {
pinMode(BUTTON_MOVE_PIN, INPUT_PULLUP);
pinMode(BUTTON_SELECT_PIN, INPUT_PULLUP);
Serial.begin(115200);
rtc.begin(); //RTC MODULE
dht.begin(); //DHT22 MODULE
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
}
void loop() {
handleButtons();
display.clearDisplay();
if (millis() - lastButtonActionTime >= 10000) {
menuState = HOME;
}
switch (menuState) {
case HOME:
displayDefaultHome();
break;
case MAIN_MENU:
displayMainMenu();
break;
case LED_SETTINGS:
displayLedSettings();
break;
case TEMPERATURE_SENSOR_SETTINGS:
displayTemperatureSensorSettings();
break;
case DATE_TIME_SETTINGS:
displayTimeSettings();
break;
}
display.display();
}
void handleButtons() {
bool buttonMoveState = digitalRead(BUTTON_MOVE_PIN);
bool buttonSelectState = digitalRead(BUTTON_SELECT_PIN);
if (buttonMoveState != isButtonMovePressed) {
isButtonMovePressed = buttonMoveState;
if (isButtonMovePressed) {
buttonMovePressStartTime = millis();
} else {
if (millis() - buttonMovePressStartTime >= 1000) {
isButtonMoveLongPressed = true;
} else {
handleButtonMoveClick();
}
buttonMovePressStartTime = 0;
}
lastButtonActionTime = millis();
}
if (buttonSelectState != isButtonSelectPressed) {
isButtonSelectPressed = buttonSelectState;
if (isButtonSelectPressed) {
handleButtonSelectClick();
}
lastButtonActionTime = millis();
}
}
void handleButtonMoveClick() {
if (isButtonMoveLongPressed) {
// Xử lý khi nút di chuyển được nhấn và giữ trong một khoảng thời gian dài
//menuState = MAIN_MENU; // Không nên vì nhấn hơi lâu xíu thì sẽ về Menu nha
isButtonMoveLongPressed = false;
} else {
cursorPosition++;
Serial.print("Position: ");
Serial.println(cursorPosition);
//Nếu cursorPosition lớn hơn Position 50 thì cho cusor quay về vì trí Pos = 10
if (cursorPosition > 5) {
cursorPosition = 1;
}
}
}
void handleButtonSelectClick() {
switch (menuState) {
case MAIN_MENU:
if (cursorPosition == 1) {
menuState = LED_SETTINGS;
} else if (cursorPosition == 2) {
menuState = TEMPERATURE_SENSOR_SETTINGS;
} else if (cursorPosition == 3) {
menuState = DATE_TIME_SETTINGS;
} else if (cursorPosition == 4) {
menuState = HOME;
}
break;
case LED_SETTINGS:
if (cursorPosition == 1) {
// Thực hiện các hành động khi chọn cài đặt LED
} else if (cursorPosition == 2) {
// Thực hiện các hành động khi chọn cài đặt đèn hậu
} else if (cursorPosition == 3) {
// Thực hiện các hành động khi chọn cài đặt đèn biển số
} else if (cursorPosition == 4) {
// Thực hiện các hành động khi chọn cài đặt đèn ngầm
} else if (cursorPosition == 5) {
menuState = MAIN_MENU;
}
break;
case TEMPERATURE_SENSOR_SETTINGS:
if (cursorPosition == 1) {
// Thực hiện các hành động khi bật/tắt cảm biến nhiệt độ
} else if (cursorPosition == 2) {
// Thực hiện cáchành động khi đặt cảnh báo
} else if (cursorPosition == 2) {
// Thực hiện cáchành động khi hiển thị đơn vị nhiệt độ
} else if (cursorPosition == 4) {
menuState = MAIN_MENU;
}
break;
case DATE_TIME_SETTINGS:
if (cursorPosition == 1) {
//Set Time
} else if (cursorPosition == 2) {
//Set Date
} else if (cursorPosition == 3) {
menuState = MAIN_MENU;
}
break;
}
}
void displayDefaultHome() {
display.clearDisplay();
//HEADER
String Header = "KYTHUATVIEN.NET";
int pos_header = Find_Position_Write(Header);
display.setCursor(pos_header, 10);
display.println(Header);
//DATETIME
DateTime now = rtc.now();
String date = String(now.day()) + "-" + String(now.month()) + "-" + String(now.year());
String time = String(now.hour()) + ":" + String(now.minute()) + ":" + String(now.second());
int pos_date = Find_Position_Write(date);
display.setCursor(pos_date, 20);
display.println(date);
int pos_time = Find_Position_Write(time);
display.setCursor(pos_time, 30);
display.println(time);
//SENSOR
String Sensor = getTemperature() + " - " + getHumidity();
int pos_sensor = Find_Position_Write(Sensor);
display.setCursor(pos_sensor, 40);
display.print(Sensor);
display.display();
//Sự kiện khi nhấn và giữ nút trên 1000ms thì sẽ vào màn hình Main Menu
if (isButtonMoveLongPressed == true) {
//display.clearDisplay();
menuState = MAIN_MENU;
}
//Mục đích để Update Time
delay(750);
}
void displayMainMenu() {
//Nếu cursorPosition > 4 thì đặt cusor về 1
if (cursorPosition > 4) {
cursorPosition = 1;
}
display.setCursor(0, 0);
display.println("MAIN MENU");
display.println();
display.setCursor(0, 10);
display.print(cursorPosition == 1 ? "> " : " ");
display.println("LED Settings");
display.setCursor(0, 20);
display.print(cursorPosition == 2 ? "> " : " ");
display.println("Sensor Settings");
display.setCursor(0, 30);
display.print(cursorPosition == 3 ? "> " : " ");
display.println("Time Settings");
display.setCursor(0, 40);
display.print(cursorPosition == 4 ? "> " : " ");
display.println("Exit");
}
void displayLedSettings() {
display.setCursor(0, 0);
display.println("LED SETTINGS");
display.println();
display.setCursor(0, 10);
display.print(cursorPosition == 1 ? "> " : " ");
display.println("LED 1");
display.setCursor(0, 20);
display.print(cursorPosition == 2 ? "> " : " ");
display.println("LED 2");
display.setCursor(0, 30);
display.print(cursorPosition == 3 ? "> " : " ");
display.println("LED 3");
display.setCursor(0, 40);
display.print(cursorPosition == 4 ? "> " : " ");
display.println("LED 4");
display.setCursor(0, 50);
display.print(cursorPosition == 5 ? "> " : " ");
display.println("Back");
}
void displayTemperatureSensorSettings() {
if (cursorPosition > 4) {
cursorPosition = 1;
}
display.setCursor(0, 0);
display.println("SENSOR SETTINGS");
display.println();
display.setCursor(0, 10);
display.print(cursorPosition == 1 ? "> " : " ");
display.println("Enable/Disable");
display.setCursor(0, 20);
display.print(cursorPosition == 2 ? "> " : " ");
display.println("Set Alert");
display.setCursor(0, 30);
display.print(cursorPosition == 3 ? "> " : " ");
display.println("Display Unit");
display.setCursor(0, 40);
display.print(cursorPosition == 4 ? "> " : " ");
display.println("Back");
}
void displayTimeSettings() {
if (cursorPosition > 3) {
cursorPosition = 1;
}
display.setCursor(0, 0);
display.println("DATETIME SETTINGS");
display.println();
display.setCursor(0, 10);
display.print(cursorPosition == 1 ? "> " : " ");
display.println("Set Time");
display.setCursor(0, 20);
display.print(cursorPosition == 2 ? "> " : " ");
display.println("Set Date");
display.setCursor(0, 30);
display.print(cursorPosition == 3 ? "> " : " ");
display.println("Back");
}
int Find_Position_Write(String myString) {
//int COUNT_CHAR = strlen(myChar);
int COUNT_CHAR = myString.length();
double PIXEL_A_CHAR = 5.9;
int CHAR_ON_A_LINE_SCREEN = 21;
double POSITION_START = 2.0; //1 ký tự là 5.9px * 128 = 124px --> left: 2 center: 124 right: 2
double TEXT_WIDTH_PIXEL = (COUNT_CHAR * PIXEL_A_CHAR);
int POSITION_WRITE = round(((124 / 2) - (TEXT_WIDTH_PIXEL / 2)) + POSITION_START);
return POSITION_WRITE;
}
String getTemperature() {
float temperature = dht.readTemperature();
if (isnan(temperature)) {
return "Failed to read temperature";
}
return String(temperature, 1) + "C";
}
String getHumidity() {
float humidity = dht.readHumidity();
if (isnan(humidity)) {
return "Failed to read humidity";
}
return String(humidity, 1) + "%";
}