#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include "time.h"
#include <ESP32Time.h>
#include <EEPROM.h>
// define the number of bytes you want to access
#define EEPROM_SIZE 4
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
enum Richtung {
RECHTS,
LINKS,
OBEN,
UNTEN,
NICHTS
};
// WIFI
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* ntpServer = "europe.pool.ntp.org";
const long gmtOffset_sec = 3600;
const int daylightOffset_sec = 3600;
// LCD
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Buttons
const int buttonUp = 35; // Pin for button 1
const int buttonLeft = 34; // Pin for button 2
const int buttonRight= 36; //27 Pin for button 3
const int buttonDown= 32;//32; // Pin for button 3
const int buttonMiddel= 39; // Pin for button 3
//Led
const int LED_Monday = 15;
const int LED_Tuesday = 2;
const int LED_Wednesday = 0;
const int LED_Thursday = 16;
const int LED_Friday = 17;
const int LED_Saturday = 5;
const int LED_Sunday = 18;
volatile bool buttonMiddelPressed1 = false;
bool alarmOn = false;
struct alarmTime {
int hours;
int minutes;
};
int currentAlarm = 0; // Indicates which alarm is currently being set
bool isHourtoSet = true;
// Alarm Time Array
alarmTime timeArray[3];
volatile unsigned long lastbuttonMiddelTime1 = 0;
const unsigned long debounceDelay = 500;
void IRAM_ATTR handlebuttonMiddelInterrupt1() {
unsigned long currentMillis = millis();
if (currentMillis - lastbuttonMiddelTime1 > debounceDelay) {
buttonMiddelPressed1 = true;
lastbuttonMiddelTime1 = currentMillis;
}
//buttonMiddelPressed1 = false;
}
void setup() {
// initialize EEPROM with predefined size
EEPROM.begin(EEPROM_SIZE);
timeArray[0].hours = EEPROM.read(0)%24;
timeArray[0].minutes = EEPROM.read(1)%60;
timeArray[1].hours = EEPROM.read(2)%24;
timeArray[1].minutes = EEPROM.read(3)%60;
// Initialize buttons
pinMode(buttonUp, INPUT);
pinMode(buttonLeft, INPUT);
pinMode(buttonRight, INPUT);
pinMode(buttonDown, INPUT);
pinMode(buttonMiddel, INPUT);
// Initialize led
pinMode(LED_Monday, OUTPUT);
pinMode(LED_Tuesday, OUTPUT);
pinMode(LED_Wednesday, OUTPUT);
pinMode(LED_Thursday, OUTPUT);
pinMode(LED_Friday, OUTPUT);
pinMode(LED_Saturday, OUTPUT);
pinMode(LED_Sunday, OUTPUT);
digitalWrite(LED_Monday, HIGH);
digitalWrite(LED_Tuesday, HIGH);
digitalWrite(LED_Wednesday, HIGH);
digitalWrite(LED_Thursday, HIGH);
digitalWrite(LED_Friday, HIGH);
digitalWrite(LED_Saturday, HIGH);
digitalWrite(LED_Sunday, HIGH);
// TODO
//pinMode(4, INPUT);
Serial.begin(115200);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextColor(WHITE);
// Attach interrupts to buttons
attachInterrupt(digitalPinToInterrupt(buttonMiddel), handlebuttonMiddelInterrupt1, FALLING);
// Connect to Wi-Fi
Serial.print("Connecting to ");
Serial.println(ssid);
display.setCursor(10, 0);
display.setTextSize(1);
display.println("Try to connect");
display.println(" to Wifi ");
display.display();
display.clearDisplay();
int counter = 0;
bool clockFromInternet = true;
WiFi.begin(ssid, password);
while ((WiFi.status() != WL_CONNECTED)&&(clockFromInternet == true)) {
delay(500);
Serial.print(".");
//display.print(".");
if(counter == 5)
{
clockFromInternet = false;
}
counter++;
}
if( clockFromInternet)
{
Serial.println("");
Serial.println("WiFi connected");
display.println("WiFi connected");
display.display();
display.clearDisplay();
delay(500);
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
// Init and get the time
SetLocalTime();
}
else
{
Serial.println("Manual");
setClockManual();
}
// Disconnect WiFi as it's no longer needed
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
}
int setVarFromDisplay(String text,int limit, int numberOfChar,int defaultValue)
{
// Init display
display.clearDisplay();
display.setCursor(10,0);
display.setTextSize(2);
int Value = defaultValue;
display.print("Set "+text);
display.setCursor(10,30);
display.print(Value);
display.display();
while(!buttonMiddelPressed1)
{
// Read Button
Richtung direktion = ReadButton();
if(direktion == OBEN)
{
if(Value < limit)
{
Value++;Serial.println("Value++");
}
}
else if(direktion == UNTEN)
{
if(Value > 0)
{
Value--;
}
}
if(direktion != NICHTS)
{
Serial.println("New display");
// New display
display.clearDisplay();
display.setCursor(10,0);
display.print("Set "+text);
display.setCursor(10,30);
display.print(Value);
display.display();
display.clearDisplay();
}
}
Serial.println("Ende setVarFromDisplay");
buttonMiddelPressed1 = false;
return Value;
// Act
}
void setClockManual()
{
int day = 1;
int month = 1;
int year = 2023;
int hour = 0;
int minute = 0;
// Set Day
day = setVarFromDisplay("Day",31,2,0);
month = setVarFromDisplay("Month",12,2,0);
year = setVarFromDisplay("Year",3000,4,2024);
hour = setVarFromDisplay("Hour",24,2,0);
minute = setVarFromDisplay("Min.",60,2,0);
ESP32Time rtc(3600); // offset in seconds GMT+1
rtc.setTime(0, minute,hour, day, month, year); // 17th Jan 2021 15:24:30
}
Richtung ReadButton()
{
//Serial.println("ReadButton");
if(digitalRead(buttonLeft) == LOW)
{
Serial.println("buttonLeft ON");
delay(200);
return LINKS;
}
else if(digitalRead(buttonRight) == LOW)
{
Serial.println("buttonRight ON");
delay(200);
return RECHTS;
}
else if(digitalRead(buttonUp) == LOW)
{
Serial.println("buttonUp ON");
delay(200);
return OBEN;
}
else if(digitalRead(buttonDown) == LOW)
{
Serial.println("buttonDown ON");
delay(200);
return UNTEN;
}
return NICHTS;
}
void setAlarmTime(int level, bool isHourtoSet)
{
Serial.println("setAlarmTime");
clearClock();
display.setCursor(10, 0);
display.setTextSize(2);
display.print("SET");
display.display();
while(true)
{
Richtung direktion = ReadButton();
if(direktion == OBEN)
{
if(isHourtoSet)
{
timeArray[level].hours = (timeArray[level].hours +1) % 24;
}
else
{
timeArray[level].minutes = (timeArray[level].minutes +1) % 60;
}
setRectFill(level,BLACK);
SetAlarmsettings();
display.display();
}
else if(direktion == UNTEN)
{
if(isHourtoSet)
{
if(timeArray[level].hours != 0)
{
timeArray[level].hours = (timeArray[level].hours -1) % 24;
}
}
else
{
if(timeArray[level].minutes != 0)
{
timeArray[level].minutes = (timeArray[level].minutes -1) % 60;
}
}
setRectFill(level,BLACK);
SetAlarmsettings();
display.display();
}
if(buttonMiddelPressed1)
{//
Serial.println("FbuttonMiddelPressed1_3");
if(level == 0)
{
if(isHourtoSet)
{
EEPROM.write(0, timeArray[level].hours);
}
else
{
EEPROM.write(1, timeArray[level].minutes);
}
}
else if(level == 1)
{
if(isHourtoSet)
{
EEPROM.write(2, timeArray[level].hours);
}
else
{
EEPROM.write(3, timeArray[level].minutes);
}
}
EEPROM.commit();
buttonMiddelPressed1 = false;
break;
}
}
}
void loop() {
if (buttonMiddelPressed1)
{
Serial.println("Adjusting Alarm");
clearClock();
display.setCursor(10, 0);
display.setTextSize(2);
display.print("Select");
display.display();
buttonMiddelPressed1 = false;
currentAlarm = 1; // Indicates which alarm is currently being set
isHourtoSet = true;
// Set Alarm Mode
int level = 0;
setRect(level,WHITE);
display.display();
while(true)
{
Richtung direktion = ReadButton();
if(direktion != NICHTS)
{
// Delete old box
setRect(level,BLACK);
if(direktion == RECHTS)
{
isHourtoSet = false;
}
else if(direktion == LINKS)
{
isHourtoSet = true;
}
else if(direktion == OBEN)
{
if(level != 0)
{
level--;
}
}
else if(direktion == UNTEN)
{
if(level != 1)
{
level++;
}
}
setRect(level,WHITE);
display.display();
}
if(buttonMiddelPressed1)
{
Serial.println("buttonMiddelPressed1_2");
buttonMiddelPressed1 = false;
// Set Time
setAlarmTime(level,isHourtoSet);
// Delete box
setRect(level,BLACK);
break;
}
}
currentAlarm = 0;
}
// Check Time for alarm
// Normal mode
//Serial.println("Normal Mode");
delay(1000);
SetLocalTime();
SetAlarmsettings();
display.display();
checkTimeForAlarm();
}
void checkTimeForAlarm()
{
Serial.println("checkTimeForAlarm");
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Failed to obtain time");
return;
}
if(!alarmOn)
{
// Check Alarm
if((timeArray[0].hours == timeinfo.tm_hour)&&(timeArray[0].minutes == timeinfo.tm_min))
{
// Timer 1
Serial.println("Alarm 1");
alarmOn = true;
}
if((timeArray[1].hours == timeinfo.tm_hour)&&(timeArray[1].minutes == timeinfo.tm_min))
{
// Timer 2
Serial.println("Alarm 2");
alarmOn = true;
}
if(alarmOn == true)
{
setLed(timeinfo.tm_wday);
}
}
else
{
}
}
void setLed(int DayOfWeek)
{
Serial.println("setLed");
Serial.println(DayOfWeek);
if(DayOfWeek == 0)
{
digitalWrite(LED_Sunday, LOW);
}
else if(DayOfWeek == 1)
{
digitalWrite(LED_Monday, LOW);
}
else if(DayOfWeek == 2)
{
digitalWrite(LED_Tuesday, LOW);
}
else if(DayOfWeek == 3)
{
digitalWrite(LED_Wednesday, LOW);
}
else if(DayOfWeek == 4)
{
digitalWrite(LED_Thursday, LOW);
}
else if(DayOfWeek == 5)
{
digitalWrite(LED_Friday, LOW);
}
else if(DayOfWeek == 6)
{
digitalWrite(LED_Saturday, LOW);
}
}
String generateTimeString(int Hour, int Min)
{
String tmp_sTime = " ";
// Füge Stunden hinzu
if (Hour < 10) {
tmp_sTime += '0'; // Führende Null für einstellige Stunden
}
tmp_sTime += String(Hour);
tmp_sTime += ':';
// Füge Minuten hinzu
if (Min < 10) {
tmp_sTime += '0'; // Führende Null für einstellige Minuten
}
tmp_sTime += String(Min);
return tmp_sTime;
}
void SetAlarmsettings()
{
// Print Alarm settings
display.setCursor(0, 30);
display.setTextSize(2);
display.print("1:");
display.print(generateTimeString(timeArray[0].hours,timeArray[0].minutes));
display.setCursor(0, 50);
display.print("2:");
display.print(generateTimeString(timeArray[1].hours,timeArray[1].minutes));
}
void setRectFill(int level,uint16_t color)
{
Serial.println("setRectFill");
Serial.println(level);
switch(level) {
case 0:
if(isHourtoSet)
{
Serial.println("setRectFill Left");
display.fillRect(35, 29, 23,16, color); // Oben Links
}
else
{
Serial.println("setRectFill richt");
display.fillRect(71, 29, 23,16, color); // Oben Rechts
}
break;
case 1:
if(isHourtoSet)
{
Serial.println("setRectFill Mitte Links");
display.fillRect(35, 49, 23,16, color); // Mitte Links
}
else
{
Serial.println("setRectFill Mitee Rechts");
display.fillRect(71, 49, 23,16, color); // Mitee Rechts
}
break;
}
}
void setRect(int level,uint16_t color)
{
Serial.println(level);
switch(level) {
case 0:
if(isHourtoSet)
{
//abstand links, abst oben, kasten
display.drawRect(34, 28, 26,18, color); // Oben Links
}
else
{
display.drawRect(70, 28, 26,18, color); // Oben Rechts
}
break;
case 1:
if(isHourtoSet)
{
display.drawRect(34, 48, 26,18, color); // Mitte Links
}
else
{
display.drawRect(70, 48, 26,18, color); // Mitee Rechts
}
break;
}
}
void clearClock()
{
display.fillRect(10, 0, 95,14, BLACK);
//display.display();
}
void SetLocalTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Failed to obtain time");
return;
}
char timeStringBuff[20]; // Buffersize 20
strftime(timeStringBuff, sizeof(timeStringBuff), "%H:%M:%S", &timeinfo);
clearClock();
display.setCursor(10, 0);
display.setTextSize(2);
display.print(timeStringBuff);
display.display();
}