Hello there. I am am working on a motorbike dashboard that is going to have a clock that is run in the RTC memory so it still calculates even as it is in deep sleep. But I also want to have two buttons, one to increment the hours and one to increment the minutes.
The buttons worked first when i was using millis to test out the buttons (i know millis doesn't hold time in deep sleep). But when i moved on to use RTC memory, buttons stopped working properly. my program doesn't detect the press and release of the individual buttons, then when i do long press on either it takes a second before the increments start to happen and then continue for a second after I let go.
would really appreciate some advice or tips on this, still relatively new to this.
thank you
==My Current Code==
#include <Wire.h>
#include <LiquidCrystal.h>
#include <driver/twai.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <time.h>
#include <esp_sleep.h>
#include <esp32/rtc.h>
#define LCD_RS 13
#define LCD_EN 12
#define LCD_D4 11
#define LCD_D5 10
#define LCD_D6 9
#define LCD_D7 6
#define BUTTON1_PIN 18
#define BUTTON2_PIN 2
#define ACC_PIN 4
LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
unsigned long lastDebounceTime1 = 0;
unsigned long lastDebounceTime2 = 0;
const unsigned long debounceDelay = 100;
const unsigned long longPressDelay = 500;
RTC_DATA_ATTR int hour = 0;
RTC_DATA_ATTR int minute = 0;
RTC_DATA_ATTR int cHour = 0;
RTC_DATA_ATTR int cMinute = 0;
RTC_DATA_ATTR unsigned long lastClockUpdate = 0;
RTC_DATA_ATTR int lastDisplayHour = -1;
RTC_DATA_ATTR int lastDisplayMinute = -1;
bool button1State = HIGH;
bool button2State = HIGH;
bool lastButton1State = HIGH;
bool lastButton2State = HIGH;
bool button1Pressed = false;
bool button2Pressed = false;
const unsigned long repeatInterval = 200;
unsigned long button1PressTime = 0;
unsigned long button2PressTime = 0;
unsigned long lastRepeat1 = 0;
unsigned long lastRepeat2 = 0;
bool button1AutoRepeat = false;
bool button2AutoRepeat = false;
#define DS18B20_PIN 39
OneWire oneWire(DS18B20_PIN);
DallasTemperature sensors(&oneWire);
void enterDeepSleepOnAcc() {
lastClockUpdate = esp_timer_get_time();
//this function controls deep sleep
esp_sleep_enable_ext0_wakeup((gpio_num_t)ACC_PIN, 1);
Serial.println("Entering Deep Sleep, Waiting on ACC HIGH");
lcd.clear();
lcd.print("Sleep...");
lcd.clear();
delay(500);
esp_deep_sleep_start();
}
void updateClockFromRtc() {
int64_t now = esp_timer_get_time();
int64_t elapsed = now - lastClockUpdate;
if (elapsed > 0) {
int minutesPassed = elapsed / 60000000LL;
if (minutesPassed > 0) {
cMinute += minutesPassed;
if (cMinute > 59) {
cHour += cMinute / 60;
cMinute = cMinute % 60;
}
if (cHour > 23) {
cHour = cHour % 24;
}
lastClockUpdate = now - (elapsed % 60000000LL);
}
}
}
void displayLcdScreen() {
//get the temprature to display
sensors.requestTemperatures();
float tempC = sensors.getTempCByIndex(0);
//format for the display
//for the clock
if (cHour != lastDisplayHour || cMinute != lastDisplayMinute) {
lcd.setCursor(0, 0);
char clock[6];
snprintf(clock, sizeof(clock), "%02d:%02d", cHour, cMinute);
lcd.print(clock);
lcd.print(" ");
}
//for the temp sensor
lcd.setCursor(0, 1);
lcd.print("T:");
lcd.print(tempC, 1);
lcd.print(" ");
}
void setup() {
Serial.begin(115200);
lcd.begin(16, 2);
lcd.setCursor(0, 0);
pinMode(BUTTON1_PIN, INPUT_PULLUP);
pinMode(BUTTON2_PIN, INPUT_PULLUP);
pinMode(ACC_PIN, INPUT);
if (lastClockUpdate == 0) {
cHour = hour;
cMinute = minute;
lastClockUpdate = esp_timer_get_time();
}
else {
updateClockFromRtc();
}
if (digitalRead(ACC_PIN) == LOW) {
enterDeepSleepOnAcc();
}
}
void loop() {
unsigned long currentMillis = millis();
if (digitalRead(ACC_PIN) == LOW) {
enterDeepSleepOnAcc();
}
bool reading1 = digitalRead(BUTTON1_PIN);
bool reading2 = digitalRead(BUTTON2_PIN);
updateClockFromRtc();
displayLcdScreen();
// --- Button 1 (Hour) ---
if (reading1 != lastButton1State) {
lastDebounceTime1 = currentMillis;
}
if ((currentMillis - lastDebounceTime1) > debounceDelay) {
if (reading1 == LOW) {
if (!button1Pressed) {
button1Pressed = true;
button1PressTime = currentMillis;
button1AutoRepeat = false;
}
else {
if (!button1AutoRepeat && (currentMillis - button1PressTime >= longPressDelay)) {
cHour = (cHour + 1) % 24;
lastClockUpdate = esp_timer_get_time();
button1AutoRepeat = true;
lastRepeat1 = currentMillis;
Serial.println("Button 1 Long Press Start");
}
else if (button1AutoRepeat && (currentMillis - lastRepeat1 >= repeatInterval)) {
cHour = (cHour + 1) % 24;
lastClockUpdate = esp_timer_get_time();
lastRepeat1 = currentMillis;
Serial.println("Button 1 Auto Repeat");
}
}
}
else if (button1Pressed) {
// Button was released
button1Pressed = false;
if (!button1AutoRepeat) {
cHour = (cHour + 1) % 24;
lastClockUpdate = esp_timer_get_time();
Serial.println("Button 1 Short Press");
}
button1AutoRepeat = false;
}
}
// --- Button 2 (Minute) ---
if (reading2 != lastButton2State) {
lastDebounceTime2 = currentMillis;
}
if ((currentMillis - lastDebounceTime2) > debounceDelay) {
if (reading2 == LOW) {
if (!button2Pressed) {
button2Pressed = true;
button2PressTime = currentMillis;
button2AutoRepeat = false;
}
else {
if (!button2AutoRepeat && (currentMillis - button2PressTime >= longPressDelay)) {
cMinute = (cMinute + 1) % 60;
lastClockUpdate = esp_timer_get_time();
button2AutoRepeat = true;
lastRepeat2 = currentMillis;
Serial.println("Button 2 Long Press Start");
}
else if (button2AutoRepeat && (currentMillis - lastRepeat2 >= repeatInterval)) {
cMinute = (cMinute + 1) % 60;
lastClockUpdate = esp_timer_get_time();
lastRepeat2 = currentMillis;
Serial.println("Button 2 Auto Repeat");
}
}
}
else if (button2Pressed) {
button2Pressed = false;
if (!button2AutoRepeat) {
cMinute = (cMinute + 1) % 60;
lastClockUpdate = esp_timer_get_time();
Serial.println("Button 2 Short Press");
}
button2AutoRepeat = false;
}
}
// Only update state after processing
lastButton1State = reading1;
lastButton2State = reading2;
}