483 lines
11 KiB
C++
483 lines
11 KiB
C++
#include <Arduino.h>
|
|
#include <LiquidCrystal.h>
|
|
#include <EEPROM.h>
|
|
|
|
// 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();
|
|
}
|
|
|