#include #include #include // Pin Definitions #define MENU_BUTTON A2 #define SET_BUTTON A3 #define GAUCHE_BUTTON A4 #define DROITE_BUTTON A5 #define BUZZER_PIN 8 #define ALARM_LED_PIN 13 #define TEMPERATURE_SENSOR_PIN A0 #define ALARM_SETTINGS_ADDRESS 0 #define ALARM_SET_FLAG_ADDRESS 2 #define LCD_D2 2 #define LCD_D3 3 #define LCD_D4 4 #define LCD_D5 5 #define LCD_D11 11 #define LCD_D12 12 // LCD Configuration LiquidCrystal lcd(LCD_D12, LCD_D11, LCD_D5, LCD_D4, LCD_D3, LCD_D2); // Global Variables bool alarmEnabled = true; bool editMode = false; bool editingHour = false; bool editingMinute = false; bool editingSecond = false; bool isAlarmSet = false; bool menuButtonPressed = false; bool setButtonPressed = false; bool gaucheButtonPressed = false; bool droiteButtonPressed = false; unsigned int hour = 0; unsigned int minute = 0; unsigned int second = 0; byte setHour = 12; byte setMinute = 0; byte setSecond = 0; byte alarmHour = 0; byte alarmMinute = 0; float temperature = 0.0; int ledTimer = 0; enum MenuState { MENU_OFF, MENU_TIME, MENU_ALARM_TIME, MENU_ALARM_STATUS }; MenuState menuState = MENU_OFF; // Alarm State enum AlarmState { ALARM_OFF, ALARM_ON, ALARM_SNOOZE, }; AlarmState alarmState = ALARM_OFF; unsigned long alarmStartTime = 0; const unsigned long snoozeDuration = 120000; // 2 minutes snooze duration (in milliseconds) void updateTemperature() { // Read temperature from the sensor and return the value int valeur = analogRead(TEMPERATURE_SENSOR_PIN); //Formule pour transformer en degré -> 10000 pour resistance 10k, 3977 pour beta double voltage = valeur * 5.0 / 1023.0; double resistance = 10000.0 * voltage / (5.0 - voltage); double tempKelvin = 1.0 / (1.0 / 298.15 + log(resistance / 10000.0) / 3977); double tempCelcius = tempKelvin - 273.15; temperature = tempCelcius; } void updateTime() { // Update the time variables based on the elapsed time second = millis() / 1000; minute = second / 60; hour = second / 3600; minute %= 60; second %= 60; hour %= 24; } void displayTime() { // Display current time on the LCD lcd.setCursor(0, 0); // Set cursor to top-left corner char str[16]; snprintf(str, sizeof(str), "%02d:%02d:%02d", hour + setHour, minute + setMinute, second + setSecond); lcd.print(str); } void displayTemperature() { // Display temperature on the LCD lcd.setCursor(9, 0); // Set cursor to top-right corner lcd.print(String(temperature, 2)); } void displayAlarmStatus() { // Display alarm status (ON/OFF) and time on the bottom row of the LCD lcd.setCursor(0, 1); // Set cursor to the start of the second row char str[16]; snprintf(str, sizeof(str), "%02d:%02d", alarmHour, alarmMinute); // Display alarm status and time if (alarmEnabled) { lcd.print(str); lcd.print(" (ON)"); } else { lcd.print(str); lcd.print(" (OFF)"); } } void displayMenuTop(){ lcd.setCursor(0, 0); lcd.print("Menu: "); lcd.setCursor(6, 0); switch (menuState) { case MENU_TIME: lcd.print("Heure"); break; case MENU_ALARM_TIME: lcd.print("Alarme"); break; case MENU_ALARM_STATUS: lcd.print("Alarme"); break; } } void displayMenuInfo(){ lcd.setCursor(0, 1); char str[16]; switch (menuState) { case MENU_TIME: snprintf(str, sizeof(str), "%02d:%02d:%02d", hour + setHour, minute + setMinute, second); lcd.print(str); break; case MENU_ALARM_TIME: snprintf(str, sizeof(str), "%02d:%02d", alarmHour, alarmMinute); lcd.print(str); break; case MENU_ALARM_STATUS: if(alarmEnabled) lcd.print("ON"); else lcd.print("OFF"); break; } } void handleMenuButton() { if(digitalRead(MENU_BUTTON)) menuButtonPressed = false; if(!menuButtonPressed){ if(!digitalRead(MENU_BUTTON)){ if(alarmState == ALARM_ON){ snoozeAlarm(); return; } switch (menuState) { case MENU_OFF: lcd.clear(); menuState = MENU_TIME; break; case MENU_TIME: lcd.clear(); menuState = MENU_ALARM_TIME; break; case MENU_ALARM_TIME: lcd.clear(); menuState = MENU_ALARM_STATUS; break; case MENU_ALARM_STATUS: lcd.clear(); menuState = MENU_OFF; break; } menuButtonPressed = true; } } } void handleSetButton() { if(digitalRead(SET_BUTTON)) setButtonPressed = false; if(!setButtonPressed){ if(!digitalRead(SET_BUTTON)){ switch (menuState) { case MENU_OFF: break; case MENU_TIME: if(!editMode){ editMode = true; } else{ if(!editingHour){ editingHour = true; } else{ editingHour = false; if(!editingMinute){ editingMinute = true; } else{ editingMinute = false; if(!editingSecond){ editingSecond = true; } else{ editingSecond = false; editMode = false; } } } } break; case MENU_ALARM_TIME: if(!editMode){ editMode = true; } else{ if(!editingHour){ editingHour = true; } else{ editingHour = false; if(!editingMinute){ editingMinute = true; } else{ editingMinute = false; editMode = false; setAlarm(); } } } break; case MENU_ALARM_STATUS: if(!editMode){ editMode = true; } else{ editMode = false; } break; } setButtonPressed = true; } } } void handleGaucheButton() { if(digitalRead(GAUCHE_BUTTON)) gaucheButtonPressed = false; if(!gaucheButtonPressed){ if(!digitalRead(GAUCHE_BUTTON)){ if(alarmState == ALARM_ON){ if(!digitalRead(DROITE_BUTTON)){ stopAlarm(); } } switch (menuState) { case MENU_OFF: break; case MENU_TIME: if(editMode){ if(editingHour){ setHour++; } if(editingMinute){ setMinute++; } if(editingSecond){ setSecond++; } } break; case MENU_ALARM_TIME: if(editMode){ if(editingHour){ alarmHour++; } if(editingMinute){ alarmMinute++; } } break; case MENU_ALARM_STATUS: if(editMode){ lcd.clear(); if(alarmEnabled) alarmEnabled = false; else alarmEnabled = true; } break; } gaucheButtonPressed = true; } } } void handleDroiteButton() { if(digitalRead(DROITE_BUTTON)) droiteButtonPressed = false; if(!droiteButtonPressed){ if(!digitalRead(DROITE_BUTTON)){ switch (menuState) { case MENU_OFF: break; case MENU_TIME: if(editMode){ if(editingHour){ setHour--; } if(editingMinute){ setMinute--; } if(editingSecond){ setSecond--; } } break; case MENU_ALARM_TIME: if(editMode){ if(editingHour){ alarmHour--; } if(editingMinute){ alarmMinute--; } } break; case MENU_ALARM_STATUS: break; } droiteButtonPressed = true; } } } void checkAlarm() { if (alarmEnabled && (hour + setHour == alarmHour) && (minute + setMinute == alarmMinute) && alarmState == ALARM_OFF) { // Set alarm state to sound alarmState = ALARM_ON; alarmStartTime = millis(); } } void stopAlarm() { alarmState = ALARM_OFF; noTone(BUZZER_PIN); digitalWrite(ALARM_LED_PIN, LOW); } void snoozeAlarm() { alarmState = ALARM_SNOOZE; alarmStartTime = millis(); } void restoreAlarmSettings() { // Read alarm settings from EEPROM and set variables accordingly // If no settings are found, use default values byte storedHour = EEPROM.read(ALARM_SETTINGS_ADDRESS); byte storedMinute = EEPROM.read(ALARM_SETTINGS_ADDRESS + 1); isAlarmSet = EEPROM.read(ALARM_SET_FLAG_ADDRESS); // Check if EEPROM contains valid alarm settings if (isAlarmSet && storedHour != 255 && storedMinute != 255) { alarmHour = storedHour; alarmMinute = storedMinute; } else { // Default alarm time (12:01) if EEPROM is empty or contains invalid data alarmHour = 12; alarmMinute = 1; isAlarmSet = false; } } void saveAlarmSettings() { // Save alarm settings and the alarm set flag to EEPROM EEPROM.write(ALARM_SETTINGS_ADDRESS, alarmHour); EEPROM.write(ALARM_SETTINGS_ADDRESS + 1, alarmMinute); EEPROM.write(ALARM_SET_FLAG_ADDRESS, isAlarmSet); } void setAlarm() { isAlarmSet = true; // Save alarm settings and the alarm set flag to EEPROM when the alarm is set saveAlarmSettings(); } void clearAlarm() { // Clear the alarm and update the alarm set flag in EEPROM alarmHour = 6; alarmMinute = 0; isAlarmSet = false; saveAlarmSettings(); } void setup() { //For debugging Serial.begin(115200); // Initialize LCD lcd.begin(16, 2); // Restore alarm settings from EEPROM restoreAlarmSettings(); // Initialize buttons as inputs pinMode(MENU_BUTTON, INPUT_PULLUP); pinMode(SET_BUTTON, INPUT_PULLUP); pinMode(GAUCHE_BUTTON, INPUT_PULLUP); pinMode(DROITE_BUTTON, INPUT_PULLUP); } void loop() { if(menuState == MENU_OFF){ // Update temperature updateTemperature(); // Update time updateTime(); // Display information on LCD displayTime(); displayTemperature(); displayAlarmStatus(); // Check and activate the alarm checkAlarm(); // Handle the alarm state switch (alarmState) { case ALARM_OFF: stopAlarm(); break; case ALARM_ON: tone(BUZZER_PIN, 300); break; case ALARM_SNOOZE: // Check if snooze duration has passed if (millis() - alarmStartTime >= snoozeDuration) { alarmState = ALARM_ON; alarmStartTime = millis(); } break; } } else{ displayMenuTop(); displayMenuInfo(); } // Handle button presses handleMenuButton(); handleSetButton(); handleGaucheButton(); handleDroiteButton(); }