/*
Kevin Setya Nugraha - 30 October 2023
Project Demo at https://wokwi.com/projects/379964121870835713
Link for Libraries used in this sketch
1. LiquidCrystal_I2C - https://www.arduinolibraries.info/libraries/liquid-crystal-i2-c
2. Button2 - https://github.com/LennartHennigs/Button2/tree/master
3. ESPRotary - https://github.com/LennartHennigs/ESPRotary/tree/master
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#include "Button2.h"
Button2 b;
#define BUTTON_PIN 2
#include "ESPRotary.h"
ESPRotary r;
#define ROTARY_PIN1 7
#define ROTARY_PIN2 6
#define CLICKS_PER_STEP 4
#define MIN_POS 0
#define MAX_POS 59
#define START_POS 0
#define INCREMENT 1
int setValue;
byte setTimer = 1;
int setHour, setMinute, setSecond;
bool getReady, onResume;
String readyText, pausedText;
#define LED 4
unsigned long now = millis();
unsigned long lastTrigger = 0;
unsigned long previousMillis = 0;
const long interval = 1000; // for countdown timer
const long interval2 = 200; // for each funciton
void setup() {
Serial.begin(9600);
lcd.init();
// lcd.backlight();
lcd.clear();
r.begin(ROTARY_PIN1, ROTARY_PIN2, CLICKS_PER_STEP, MIN_POS, MAX_POS, START_POS, INCREMENT);
r.setChangedHandler(rotate);
r.setLowerOverflowHandler(lower);
r.setUpperOverflowHandler(upper);
r.retriggerEvent(false);
b.begin(BUTTON_PIN);
b.setTapHandler(click);
pinMode(LED, OUTPUT);
}
void click(Button2& b) {
setTimer++;
lcd.clear();
r.resetPosition();
}
void rotate(ESPRotary& r) {
setValue = r.getPosition();
}
void upper(ESPRotary& r) {
// Serial.println("upper bound hit");
}
void lower(ESPRotary& r) {
// Serial.println("lower bound hit");
}
void loop() {
now = millis();
r.loop();
b.loop();
if (setTimer == 1) { // Hour Configuration
if (now - previousMillis >= interval2) {
hourConfig();
previousMillis = now;
}
} else if (setTimer == 2) { // Minute Configuration
if (now - previousMillis >= interval2) {
minuteConfig();
previousMillis = now;
}
} else if (setTimer == 3) { // Second Configuration
if (now - previousMillis >= interval2) {
secondConfig();
previousMillis = now;
}
} else if (setTimer == 4) { // Decision to start
if (now - previousMillis >= interval2) {
isReady();
previousMillis = now;
}
} else if (setTimer == 5) { // Time is running
startTimer();
} else if (setTimer == 6) { // Time is Paused
if (now - previousMillis >= interval2) {
onPaused();
previousMillis = now;
}
} else if (setTimer == 7) { // Resume or Restart?
if (onResume) {
setTimer = 5;
} else {
getReady = false;
setTimer = 1;
}
}
}
void hourConfig() {
lcd.setCursor(0,0);
lcd.print("Set Hour");
setHour = setValue;
lcd.setCursor(14,0);
lcd.print(DuaDigit(setHour) + " ");
}
void minuteConfig() {
lcd.setCursor(0,0);
lcd.print("Set Minute");
setMinute = setValue;
lcd.setCursor(14,0);
lcd.print(DuaDigit(setMinute) + " ");
}
void secondConfig() {
lcd.setCursor(0,0);
lcd.print("Set Second");
setSecond = setValue;
lcd.setCursor(14,0);
lcd.print(DuaDigit(setSecond) + " ");
}
void isReady() {
lcd.setCursor(0,0);
lcd.print("Start Timer?");
if (setValue % 2 == 0) {
readyText = ">YES NO";
getReady = true;
} else {
readyText = " YES >NO";
getReady = false;
}
lcd.setCursor(0,1);
lcd.print(readyText);
}
void startTimer() {
if (getReady) {
digitalWrite(LED, HIGH);
if (now - previousMillis >= interval) {
setSecond--;
previousMillis = now;
}
if (setSecond < 0) {
setSecond = 59;
setMinute = setMinute - 1;
}
if (setMinute < 0) {
setMinute = 59;
setHour = setHour - 1;
}
lcd.setCursor(0,0);
lcd.print(" REMAINING TIME ");
lcd.setCursor(4,1);
lcd.print(DuaDigit(setHour) + ":" + DuaDigit(setMinute) + ":" + DuaDigit(setSecond));
if (setHour == 0 && setMinute == 0 && setSecond == 0) {
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" TIME IS UP ");
digitalWrite(LED, LOW);
delay(5000);
lcd.clear();
getReady = false;
setTimer = 1;
}
} else {
setTimer = 1;
}
}
void onPaused() {
digitalWrite(LED, LOW);
lcd.setCursor(0,0);
lcd.print("Paused, " + DuaDigit(setHour) + ":" + DuaDigit(setMinute) + ":" + DuaDigit(setSecond));
if (setValue % 2 == 0) {
pausedText = ">YES NO";
onResume = true;
} else {
pausedText = " YES >NO";
onResume = false;
}
lcd.setCursor(0,1);
lcd.print("Resume? " + pausedText);
}
String DuaDigit(int angka) {
if (angka > 9) {
return String(angka);
} else {
String tmp = " ";
tmp.concat(angka);
return tmp;
}
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
lcd1:GND
lcd1:VCC
lcd1:SDA
lcd1:SCL
led1:A
led1:C
encoder1:CLK
encoder1:DT
encoder1:SW
encoder1:VCC
encoder1:GND