#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
#include <ESP32Time.h>
#include <string.h>
#include <EEPROM.h>
U8G2_SH1106_128X32_VISIONOX_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
#define EEPROM_SIZE 16
#define encoderclkPin 15
#define encoderdtPin 16
#define encoderswPin 17
#define timerOutPin 2
#define timeDisplayState 0
#define timeSettingState 1
#define timerOnSettingState 2
#define timerOffSettingState 3
#define timeDisplay 0
#define timerOn 1
#define timerOff 2
#define hourEditState 0
#define minuteEditState 1
#define secondEditState 2
int timeEditState = hourEditState;
int activeState = timeDisplayState;
int encoderCounter = 0;
int encoderState;
bool encoderSwitchPressed = false;
int encoderSwitchState = HIGH;
int encoderSwitchDownCounter = 0;
int encoderSwitchUpCounter = 0;
bool blinky = false;
int setTimeHour;
int setTimeMinute;
bool timerState = false;
int timerOnHour = 15;
int timerOnMinute = 20;
int timerOffHour = 0;
int timerOffMinute = 0;
bool initialEdit = true;
int lastClk = HIGH;
//ESP32Time rtc;
ESP32Time rtc(0);
void IRAM_ATTR readEncoder() {
encoderSwitchUpCounter = 0;
int dtValue = digitalRead(encoderdtPin);
if (dtValue == HIGH) {
encoderCounter++;
}
if (dtValue == LOW) {
encoderCounter--;
}
}
void IRAM_ATTR encoderswPinDown () {
encoderSwitchPressed = true;
encoderSwitchDownCounter = 0;
encoderSwitchUpCounter = 0;
}
void EEPROM_Save() {
EEPROM.write(0, timerOnHour);
EEPROM.write(1, timerOnMinute);
EEPROM.write(2, timerOffHour);
EEPROM.write(3, timerOffMinute);
}
void EEPROM_Load() {
EEPROM.write(0, timerOnHour);
EEPROM.write(1, timerOnMinute);
EEPROM.write(2, timerOffHour);
EEPROM.write(3, timerOffMinute);
}
void initSettingState() {
if (activeState == timeSettingState) {
setTimeHour = rtc.getHour(true);
setTimeMinute = rtc.getMinute();
} else if (activeState == timerOnSettingState) {
setTimeHour = timerOnHour;
setTimeMinute = timerOnMinute;
} else if (activeState == timerOffSettingState) {
setTimeHour = timerOffHour;
setTimeMinute = timerOffMinute;
}
timeEditState = hourEditState;
encoderSwitchPressed = false;
encoderSwitchDownCounter = 0;
encoderSwitchUpCounter = 0;
}
void checkAndSetTimerOutput() {
int currentTotalMinutes;
int timerOnTotalMinutes;
int timerOffTotalMinutes;
currentTotalMinutes = (60*rtc.getHour(true)) + rtc.getMinute();
timerOnTotalMinutes = (60*timerOnHour) + timerOnMinute;
timerOffTotalMinutes = (60*timerOffHour) + timerOffMinute;
bool checkTimer = false;
// if timer has been set and isn't same:
if (timerOnTotalMinutes != timerOffTotalMinutes) {
// if timer-on is "after" timer-off:
if (timerOnTotalMinutes > timerOffTotalMinutes) {
// if current time is after timer-on or before timer-off
if ((currentTotalMinutes >= timerOnTotalMinutes) || (currentTotalMinutes < timerOffTotalMinutes)) {
checkTimer = true;
}
} else {
// if timer-on is "before" timer-off:
// if current time is after timer-on and before timer-off
if ((currentTotalMinutes >= timerOnTotalMinutes) && (currentTotalMinutes < timerOffTotalMinutes)) {
checkTimer = true;
}
}
}
if (checkTimer == true) {
timerState = true;
digitalWrite(timerOutPin, HIGH);
}else {
timerState = false;
digitalWrite(timerOutPin, LOW);
}
}
void setup() {
pinMode(timerOutPin, OUTPUT);
digitalWrite(timerOutPin, LOW);
pinMode(encoderswPin, INPUT_PULLUP);
pinMode(encoderclkPin, INPUT);
pinMode(encoderdtPin, INPUT);
attachInterrupt(digitalPinToInterrupt(encoderclkPin), readEncoder, FALLING);
attachInterrupt(digitalPinToInterrupt(encoderswPin), encoderswPinDown, FALLING);
Serial.begin(115200);
u8g2.begin();
rtc.setTime(30, 24, 15, 17, 11, 2022); // 17th Nov 2022 15:24:30
EEPROM.begin(EEPROM_SIZE);
EEPROM_Load();
}
void drawTime(int activeState, bool blinky) {
u8g2.firstPage();
do {
u8g2.setFont(u8g2_font_t0_13b_mr);
u8g2.setCursor(0,10);
if (activeState == timeDisplayState) {
u8g2.print("Pa:");
u8g2.drawBox(10,0,2,2);
if (timerState == false) {
u8g2.drawCircle(8,18,5,U8G2_DRAW_UPPER_LEFT|U8G2_DRAW_UPPER_RIGHT);
u8g2.drawEllipse(8,19,5,6,U8G2_DRAW_LOWER_LEFT|U8G2_DRAW_LOWER_RIGHT);
}
if (timerState == true) {
u8g2.drawDisc(8,18,5,U8G2_DRAW_UPPER_LEFT|U8G2_DRAW_UPPER_RIGHT);
u8g2.drawFilledEllipse(8,19,5,6,U8G2_DRAW_LOWER_LEFT|U8G2_DRAW_LOWER_RIGHT);
}
u8g2.drawLine(6,25,6,30);
u8g2.drawLine(10,25,10,30);
u8g2.drawLine(7,29,9,29);
u8g2.drawLine(7,27,9,27);
u8g2.drawLine(7,31,9,31);
u8g2.drawLine(6,25,6,30);
u8g2.drawLine(10,25,10,30);
u8g2.drawLine(7,29,9,29);
u8g2.drawLine(7,27,9,27);
u8g2.drawLine(7,31,9,31);
u8g2.setCursor(36,10);
if (timerOnHour <= 9) u8g2.print("0");
u8g2.print(timerOnHour);
u8g2.print(":");
if (timerOnMinute <= 9) u8g2.print("0");
u8g2.print(timerOnMinute);
u8g2.setCursor(74,10);
u8g2.print("-");
u8g2.setCursor(83,10);
if (timerOffHour <= 9) u8g2.print("0");
u8g2.print(timerOffHour);
u8g2.print(":");
if (timerOffMinute <= 9) u8g2.print("0");
u8g2.print(timerOffMinute);
}
if (activeState == timeSettingState) {
u8g2.setCursor(0,12);
u8g2.print("Ange");
u8g2.setCursor(0,28);
u8g2.print("tid:");
}
if (activeState == timerOnSettingState) {
u8g2.setCursor(0,12);
u8g2.print("Timer");
u8g2.setCursor(0,28);
u8g2.print("pa:");
u8g2.drawBox(10,18,2,2);
}
if (activeState == timerOffSettingState) {
u8g2.setCursor(0,12);
u8g2.print("Timer");
u8g2.setCursor(0,28);
u8g2.print("av:");
}
u8g2.setFont(u8g2_font_VCR_OSD_mr);
u8g2.drawBox(62,17,2,2);
u8g2.drawBox(62,25,2,2);
u8g2.drawBox(92,17,2,2);
u8g2.drawBox(92,25,2,2);
u8g2.setCursor(36,30);
// Time display:
if (activeState == timeDisplayState) {
if (rtc.getHour(true) <= 9) u8g2.print("0");
u8g2.print(rtc.getHour(true));
u8g2.setCursor(66,30);
if (rtc.getMinute() <= 9) u8g2.print("0");
u8g2.print(rtc.getMinute());
u8g2.setCursor(96,30);
if (rtc.getSecond() <= 9) u8g2.print("0");
u8g2.print(rtc.getSecond());
} else {
if ((blinky == true) && (timeEditState == hourEditState)) {
u8g2.print(" ");
} else {
if (setTimeHour <= 9) u8g2.print("0");
u8g2.print(setTimeHour);
}
u8g2.setCursor(66,30);
if ((blinky == true) && (timeEditState == minuteEditState)) {
u8g2.print(" ");
} else {
if (setTimeMinute <= 9) u8g2.print("0");
u8g2.print(setTimeMinute);
}
u8g2.setCursor(96,30);
if (activeState == timeSettingState) {
if (rtc.getSecond() <= 9) u8g2.print("0");
u8g2.print(rtc.getSecond());
} else {
u8g2.print("00");
}
}
} while ( u8g2.nextPage() );
}
void loop() {
// Read encoder:
encoderSwitchState = digitalRead(encoderswPin);
if (encoderSwitchState == LOW) encoderSwitchDownCounter++;
if (encoderSwitchState == HIGH) encoderSwitchUpCounter++;
// Change program state when switch pressed down:
if (encoderSwitchDownCounter >= 2) {
if (activeState == timeSettingState)
rtc.setTime(rtc.getSecond(), setTimeMinute, setTimeHour, rtc.getDay(), rtc.getMonth(), rtc.getYear()); // 17th Nov 2022 15:24:30
if (activeState == timerOnSettingState) {
timerOnHour = setTimeHour;
timerOnMinute = setTimeMinute;
}
if (activeState == timerOffSettingState) {
timerOffHour = setTimeHour;
timerOffMinute = setTimeMinute;
}
activeState +=1 ;
if (activeState > timerOffSettingState) activeState = timeSettingState;
initSettingState();
}
// return to timeDisplayState after timeout:
if (encoderSwitchUpCounter > 10) {
encoderSwitchUpCounter = 0;
if (activeState == timeSettingState)
rtc.setTime(rtc.getSecond(), setTimeMinute, setTimeHour, rtc.getDay(), rtc.getMonth(), rtc.getYear()); // 17th Nov 2022 15:24:30
if (activeState == timerOnSettingState) {
timerOnHour = setTimeHour;
timerOnMinute = setTimeMinute;
}
if (activeState == timerOffSettingState) {
timerOffHour = setTimeHour;
timerOffMinute = setTimeMinute;
}
EEPROM_Save();
activeState = timeDisplayState;
}
if (activeState == timeDisplayState) {
drawTime(activeState,false);
delay(825);
} else {
if (encoderSwitchPressed == true) {
encoderSwitchPressed = false;
if (timeEditState == hourEditState) timeEditState = minuteEditState;
else timeEditState = hourEditState;
}
if (timeEditState == hourEditState) {
if (encoderCounter != 0) {
setTimeHour = setTimeHour + encoderCounter;
encoderCounter = 0;
if (setTimeHour <= 0) setTimeHour = 23;
if (setTimeHour >= 24) setTimeHour = 0;
}
}
if (timeEditState == minuteEditState) {
if (encoderCounter != 0) {
setTimeMinute = setTimeMinute + encoderCounter;
encoderCounter = 0;
if (setTimeMinute < 0) setTimeMinute = 59;
if (setTimeMinute > 59) setTimeMinute = 0;
}
}
drawTime(activeState,blinky);
blinky = !blinky;
delay(500);
}
checkAndSetTimerOutput();
// struct tm timeinfo = rtc.getTimeStruct();
//Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); // (tm struct) Sunday, January 17 2021 07:24:38
}