#include <Arduino.h>
#include <ezButton.h>
#include <esp_now.h>
#include <WiFi.h>
#include <LCD_I2C.h>
#include "pitches.h"
// Initiate
LCD_I2C lcd(0x27, 16, 2);
ezButton play_pause(19);
ezButton up(13);
ezButton down(14);
ezButton sel(18);
#define BUZZER 12
uint8_t broadcastAddress2[] = {0x78, 0x21, 0x84, 0x79, 0x5D, 0x2C}; //ESP32S MAC-ADDRESS
uint8_t broadcastAddress1[] = {0x94, 0xb5, 0x55, 0x26, 0xc1, 0xcc}; // ESP32 LOLIN
uint8_t broadcastAddress3[] = {0xc8, 0xc9, 0xa3, 0xc7, 0xbe, 0xd4}; // ESP32 DEVKIT1 NO ANTENNA
// SYMBOLS
uint8_t leftArrow[] = {
B00000,
B00000,
B00100,
B01100,
B11111,
B01100,
B00100,
B00000
};
uint8_t rightArrow[] = {
B00000,
B00000,
B00100,
B00110,
B11111,
B00110,
B00100,
B00000
};
uint8_t underScore[] = {
0b00100,
0b01110,
0b00000,
0b00000,
0b00000,
0b00000,
0b00000,
0b00000
};
uint8_t plus[] = {
0b00000,
0b00000,
0b00100,
0b01110,
0b11111,
0b00100,
0b00100,
0b00000
};
uint8_t minus[] = {
0b00000,
0b00100,
0b00100,
0b11111,
0b01110,
0b00100,
0b00000,
0b00000
};
uint8_t playPause1[] = {
0b01000,
0b01100,
0b01110,
0b01111,
0b01110,
0b01100,
0b01000,
0b00000
};
uint8_t playPause2[] = {
0b11011,
0b11011,
0b11011,
0b11011,
0b11011,
0b11011,
0b11011,
0b00000
};
uint8_t reset[] = {
0b00000,
0b00000,
0b01101,
0b10011,
0b10111,
0b10000,
0b01110,
0b00000
};
// Variables
uint8_t dots = 0b01000000;
int cd_seconds;
int cd_ten_seconds;
int cd_minutes;
int cd_ten_minutes;
int timer_seconds;
int timer_ten_seconds;
int timer_minutes;
int timer_ten_minutes;
byte selectedDigit = 0;
bool buzzer321 = false;
bool buzzerOnOff = true;
int melody[] = {
NOTE_A5, NOTE_B5, NOTE_C6, NOTE_G5, NOTE_F5, NOTE_E5, NOTE_G5, NOTE_D5, NOTE_C5, NOTE_C5
};
double noteDurations[] = {
4, 4, 4, 4, 4, 4, 4, 1.2, 4, 0.8
};
// Millis
unsigned long previousMillis;
const long interval = 1000;
// Millis2 for "OT" text blinking
unsigned long previousMillis2;
// Millis3 for "[paused..]" text blinking
unsigned long previousMillis3;
unsigned long previousMillis4;
// Buzzer Tone
unsigned long previousMillis5;
typedef struct clockVars {
int total_cd_time;
int total_timer_time;
int state;
bool timerRunning;
bool countdownRunning;
bool overTime;
} clockVars;
clockVars clockTime;
clockVars incomingClockTime;
esp_now_peer_info_t peerInfo;
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
// Timer Start Function
void timerStart(){
lcd.setCursor(3,1);
lcd.print(" ");
lcd.setCursor(15, 1);
lcd.print(" ");
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval){
previousMillis = currentMillis;
timer_seconds++;
}
if (timer_seconds > 9){
timer_ten_seconds++;
timer_seconds = 0;
if (timer_ten_seconds > 5){
timer_minutes++;
timer_ten_seconds = 0;
if (timer_minutes > 9){
timer_ten_minutes++;
timer_minutes = 0;
}
}
}
}
void countdownStart(){
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval){
previousMillis = currentMillis;
cd_seconds--;
if (cd_ten_minutes == 0 && cd_minutes == 0 && cd_ten_seconds == 0 && cd_seconds == 0){
clockTime.countdownRunning = false;
clockTime.timerRunning = true;
clockTime.state = 7;
}
if (cd_ten_minutes >= 0 && cd_minutes >= 0 && cd_ten_seconds > 0 && cd_seconds < 0){
cd_ten_seconds--;
cd_seconds = 9;
}
if (cd_ten_minutes >= 0 && cd_minutes > 0 && cd_ten_seconds <= 0 && cd_seconds < 0){
cd_minutes--;
cd_ten_seconds = 5;
cd_seconds = 9;
}
if (cd_ten_minutes >= 0 && cd_minutes <= 0 && cd_ten_seconds <= 0 && cd_seconds < 0){
cd_ten_minutes--;
cd_minutes = 9;
cd_ten_seconds = 5;
cd_seconds = 9;
}
}
}
void setup() {
Serial.begin(115200);
pinMode(BUZZER, OUTPUT);
lcd.begin();
lcd.backlight();
play_pause.setDebounceTime(50);
sel.setDebounceTime(50);
up.setDebounceTime(50);
down.setDebounceTime(50);
/*
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
return;
}
esp_now_register_send_cb(OnDataSent);
peerInfo.channel = 0;
peerInfo.encrypt = false;
memcpy(peerInfo.peer_addr, broadcastAddress3, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Failed to add peer");
return;
}
*/
lcd.createChar(0,leftArrow);
lcd.createChar(1,rightArrow);
lcd.createChar(2,plus);
lcd.createChar(3,minus);
lcd.createChar(4,underScore);
lcd.createChar(5,reset);
lcd.createChar(6,playPause1);
lcd.createChar(7,playPause2);
// JWSONG
// for (int thisNote = 0; thisNote < 10; thisNote++) {
// // to calculate the note duration, take one second divided by the note type.
// //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
// double noteDuration = 1000 / noteDurations[thisNote];
// tone(BUZZER, melody[thisNote], noteDuration);
// // to distinguish the notes, set a minimum time between them.
// // the note's duration + 30% seems to work well:
// int pauseBetweenNotes = noteDuration * 1.30;
// delay(pauseBetweenNotes);
// // stop the tone playing:
// noTone(BUZZER);
// }
}
void loop() {
play_pause.loop();
up.loop();
down.loop();
sel.loop();
/* SWITCH BETWEEN STATES AND SCREENS */
switch (clockTime.state)
{
/* DEFAULT STATE || MENU SCREEN */
case 0:
lcd.setCursor(4,0);
lcd.print("Start Timer");
lcd.write(1); // Display Right Arrow Symbol
lcd.setCursor(2,1);
lcd.print("Set CountDown");
lcd.write(1); // Display Right Arrow Symbol
// Set timer and countdown timer states to default:
clockTime.countdownRunning = false;
clockTime.timerRunning = false;
/* Button registry */
// "Set Countdown" button is released
if (sel.isReleased())
{
lcd.clear(); // Clear screen
clockTime.state = 1; // Move to "Set Countdown" screen
}
// "Start Timer" button is released
if (play_pause.isReleased())
{
lcd.clear(); // Clear screen
clockTime.state = 2; // Move to "Timer" screen
clockTime.timerRunning = true; // Set "Timer" flag to true
}
break;
/* SET COUNTDOWN STATE || SET COUNTDOWN SCREEN */
case 1:
lcd.setCursor(0,0);
lcd.write(2); // Display Up Arrow symbol
lcd.setCursor(0,1);
lcd.write(3); // Display Down Arrow symbol
lcd.setCursor(14,1);
lcd.write(0); // Display Left Arrow symbol
lcd.write(1); // Display Right Arrow symbol beside Left Arrow = "<- ->"
lcd.setCursor(14,0);
lcd.write(6); // Display Play Symbol
lcd.write(7); // Display Pause Symbol beside Play Symbol = ">||"
lcd.setCursor(5,0);
lcd.print(cd_ten_minutes);
lcd.print(cd_minutes); // OUTPUTS THE TIMER
lcd.print(":"); // 00:00
lcd.print(cd_ten_seconds);
lcd.print(cd_seconds);
/* Selected Digit Button Registry*/
if (sel.isReleased())
{
selectedDigit++; // Change selected digit
}
if (play_pause.isReleased())
{
/* if START button is pressed without setting the countdown timer, start timer immediately */
if (clockTime.total_cd_time <= 0)
{
lcd.clear();
clockTime.timerRunning = true; // Set "Timer" flag to true
clockTime.state = 2; // Move to "Timer" screen
}
/* if START button is pressed and countdown timer is set, start countdown timer */
if (clockTime.total_cd_time > 0)
{
lcd.clear();
clockTime.countdownRunning = true; // Set "Countdown Timer" flag to true
clockTime.state = 3; // Move to "Countdown Timer" screen
}
}
/* Select a DIGIT to set */
switch (selectedDigit)
{
// First Digit Selected = 00:00
// ^
case 0:
lcd.setCursor(5,1);
lcd.write(4); // Display Select Arrow symbol
lcd.print(" "); // Reset any arrow print from last selectedDigit
/* Add 1 to selectedDigit */
if (up.isReleased())
{
cd_ten_minutes++;
}
/* Subtract 1 to selectedDigit */
if (down.isReleased())
{
cd_ten_minutes--;
}
/* Reset selectedDigit to 0 or 9 depending on the case */
if (cd_ten_minutes > 9) cd_ten_minutes = 0;
if (cd_ten_minutes < 0) cd_ten_minutes = 9;
break;
// Second Digit Selected = 00:00
// ^
case 1:
lcd.setCursor(5,1);
lcd.print(" "); // Reset any arrow print from last selectedDigit
lcd.write(4); // Display Select Arrow symbol
/* Add 1 to selectedDigit */
if (up.isReleased())
{
cd_minutes++;
}
/* Subtract 1 to selectedDigit */
if (down.isReleased())
{
cd_minutes--;
}
/* Reset selectedDigit to 0 or 9 depending on the case */
if (cd_minutes > 9) cd_minutes = 0;
if (cd_minutes < 0) cd_minutes = 9;
break;
// Third Digit Selected = 00:00
// ^
case 2:
lcd.setCursor(5,1);
lcd.print(" "); // Reset any arrow print from last selectedDigit
lcd.write(4); // Display Select Arrow symbol
/* Add 1 to selectedDigit */
if (up.isReleased())
{
cd_ten_seconds++;
}
/* Subtract 1 to selectedDigit */
if (down.isReleased())
{
cd_ten_seconds--;
}
/* Reset selectedDigit to 0 or 9 depending on the case */
if (cd_ten_seconds > 5) cd_ten_seconds = 0;
if (cd_ten_seconds < 0) cd_ten_seconds = 5;
break;
// Fourth Digit Selected = 00:00
// ^
case 3:
lcd.setCursor(5,1);
lcd.print(" "); // Reset any arrow print from last selectedDigit
lcd.write(4); // Display Select Arrow symbol
/* Add 1 to selectedDigit */
if (up.isReleased())
{
cd_seconds++;
}
/* Subtract 1 to selectedDigit */
if (down.isReleased())
{
cd_seconds--;
}
/* Reset selectedDigit to 0 or 9 depending on the case */
if (cd_seconds > 9) cd_seconds = 0;
if (cd_seconds < 0) cd_seconds = 9;
break;
default:
selectedDigit = 0; // Go back to First selectedDigit
break;
}
break;
/* START TIMER || GO TO TIMER SCREEN */
case 2:
lcd.setCursor(14,0);
lcd.write(6); // START 1st HALF
lcd.write(7); // START 2nd HALF
lcd.setCursor(5,0);
lcd.print(timer_ten_minutes);
lcd.print(timer_minutes);
lcd.print(":");
lcd.print(timer_ten_seconds);
lcd.print(timer_seconds);
/* PLAY or PAUSE TIMER*/
if (play_pause.isReleased())
{
clockTime.timerRunning = !clockTime.timerRunning;
}
if (clockTime.timerRunning){
if (clockTime.overTime)
{
lcd.setCursor(0,0);
lcd.print("O");
lcd.setCursor(0,1);
lcd.print("T");
}
if (!clockTime.overTime)
{
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
}
timerStart();
}
/* RESET or GO BACK TO MENU depending on conditions met */
if (!clockTime.timerRunning)
{
/* Check if TIMER is PAUSED and value is greater than 0 */
if (clockTime.total_timer_time > 0)
{
lcd.setCursor(3,1);
lcd.print("paused...");
lcd.setCursor(15,1);
lcd.write(5);
/* RESET TIMER BACK TO 00:00 */
if (sel.isReleased())
{
timer_ten_minutes = 0;
timer_minutes = 0;
timer_ten_seconds = 0;
timer_seconds = 0;
}
}
/* Check if TIMER is PAUSED and value is less than or equal to 0 */
if (clockTime.total_timer_time <= 0)
{
lcd.setCursor(3,1);
lcd.print("paused...");
lcd.setCursor(15,1);
lcd.write(0);
/* GO BACK TO MENU SCREEN */
if (sel.isReleased())
{
clockTime.state = 0;
}
}
/* IF TIMER IS RUNNING */
}
break;
/* START COUNTDOWN TIMER */
case 3:
lcd.setCursor(14,0);
lcd.write(6); // START 1st HALF
lcd.write(7); // START 2nd HALF
lcd.setCursor(5,0);
lcd.print(cd_ten_minutes);
lcd.print(cd_minutes);
lcd.print(":");
lcd.print(cd_ten_seconds);
lcd.print(cd_seconds);
if (play_pause.isReleased())
{
clockTime.countdownRunning = !clockTime.countdownRunning;
}
if (clockTime.countdownRunning)
{
lcd.setCursor(3,1);
lcd.print(" ");
countdownStart();
}
if (clockTime.total_cd_time == 0)
{
clockTime.state = 2;
clockTime.countdownRunning = false;
clockTime.timerRunning = true;
clockTime.overTime = true;
}
if (!clockTime.countdownRunning)
{
lcd.setCursor(3,1);
lcd.print("paused...");
if (sel.isReleased())
{
clockTime.state = 0;
}
}
break;
default:
break;
}
clockTime.total_cd_time = cd_seconds + (cd_ten_seconds*10) + (cd_minutes*100) + (cd_ten_minutes*1000);
clockTime.total_timer_time = timer_seconds + (timer_ten_seconds*10) + (timer_minutes*100) + (timer_ten_minutes*1000);
Serial.println(clockTime.total_cd_time);
// if (millis() - previousMillis4 >= 80){
// previousMillis4 = millis();
// esp_now_send(broadcastAddress3, (uint8_t *) &clockTime, sizeof(clockTime));
// }
}