feat: implement initial ESP32 school bell system with web UI, DFPlayer control, RTC, LittleFS, and OTA.
This commit is contained in:
113
src/main.cpp
113
src/main.cpp
@@ -1,15 +1,16 @@
|
||||
// src/main.cpp
|
||||
// Bel Sekolah ESP32 - final version
|
||||
// Pins:
|
||||
// RESET_PIN = 5 (hold >15s -> reset admin credentials)
|
||||
// STATUS_LED_PIN = 6
|
||||
// RELAY_PIN = 7 (active LOW)
|
||||
// DFPLAYER_RX_PIN = 15
|
||||
// DFPLAYER_TX_PIN = 16
|
||||
// BUSY_PIN = 17 (LOW = busy)
|
||||
//esp32 sda 21
|
||||
//esp32 scl 22
|
||||
//MCU adalah Wemos ESP32 mini
|
||||
// TEST_BUTTON = 18 (click -> toggle relay, long press -> play test MP3)
|
||||
// RESET_BUTTON = 0 (long press >15s -> reset admin credentials)
|
||||
// STATUS_LED_PIN = 26
|
||||
// RELAY_PIN = 19 (active LOW)
|
||||
// DFPLAYER_RX_PIN = 16
|
||||
// DFPLAYER_TX_PIN = 17
|
||||
// BUSY_PIN = 5 (LOW = busy)
|
||||
// esp32 sda 21
|
||||
// esp32 scl 22
|
||||
// MCU adalah Wemos ESP32 mini
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
@@ -35,7 +36,8 @@
|
||||
#define DFPLAYER_TX_PIN 17 //2 df
|
||||
#define RELAY_PIN 19
|
||||
#define BUSY_PIN 5 //must high at boot (strapping pin)
|
||||
#define RESET_PIN 18
|
||||
#define TEST_BUTTON 18
|
||||
#define RESET_BUTTON 0
|
||||
#define BUZZER_PIN 23
|
||||
|
||||
#define RESET_HOLD_MS 15000UL
|
||||
@@ -74,12 +76,19 @@ bool buzzerState = false;
|
||||
bool adminResetBlinking = false;
|
||||
unsigned long adminResetEndTime = 0;
|
||||
|
||||
// Button flags
|
||||
volatile bool btnClickPending = false;
|
||||
volatile bool btnLongPressPending = false;
|
||||
// Button flags for TEST_BUTTON
|
||||
volatile bool testBtnClickPending = false;
|
||||
volatile bool testBtnLongPressPending = false;
|
||||
|
||||
// OneButton instance for RESET_PIN
|
||||
OneButton button(RESET_PIN, true);
|
||||
// Button flags for RESET_BUTTON
|
||||
volatile bool resetBtnLongPressPending = false;
|
||||
|
||||
// Manual relay toggle state (separate from automatic relay control)
|
||||
bool manualRelayOn = false;
|
||||
|
||||
// OneButton instances
|
||||
OneButton testButton(TEST_BUTTON, true);
|
||||
OneButton resetButton(RESET_BUTTON, true);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// WiFi Channel Selection
|
||||
@@ -659,7 +668,8 @@ void setup(){
|
||||
pinMode(RELAY_PIN, OUTPUT);
|
||||
digitalWrite(RELAY_PIN, HIGH); // relay active LOW, so HIGH = off
|
||||
pinMode(BUSY_PIN, INPUT_PULLUP); // busy pin input (LOW when busy)
|
||||
pinMode(RESET_PIN, INPUT_PULLUP);
|
||||
pinMode(TEST_BUTTON, INPUT_PULLUP);
|
||||
pinMode(RESET_BUTTON, INPUT_PULLUP);
|
||||
pinMode(BUZZER_PIN, OUTPUT);
|
||||
digitalWrite(BUZZER_PIN, LOW);
|
||||
|
||||
@@ -732,16 +742,19 @@ void setup(){
|
||||
ArduinoOTA.begin();
|
||||
|
||||
|
||||
// Setup OneButton callbacks
|
||||
button.setPressMs(15000); // Set long press to 15 seconds
|
||||
button.attachClick([]() {
|
||||
// Just set flag, don't do heavy work here
|
||||
btnClickPending = true;
|
||||
// Setup TEST_BUTTON callbacks (click=toggle relay, long press=play test MP3)
|
||||
testButton.setPressMs(2000); // 2 seconds for test MP3 play
|
||||
testButton.attachClick([]() {
|
||||
testBtnClickPending = true;
|
||||
});
|
||||
testButton.attachLongPressStart([]() {
|
||||
testBtnLongPressPending = true;
|
||||
});
|
||||
|
||||
button.attachLongPressStart([]() {
|
||||
// Just set flag
|
||||
btnLongPressPending = true;
|
||||
// Setup RESET_BUTTON callbacks (long press=reset admin credentials)
|
||||
resetButton.setPressMs(15000); // 15 seconds for admin reset
|
||||
resetButton.attachLongPressStart([]() {
|
||||
resetBtnLongPressPending = true;
|
||||
});
|
||||
|
||||
|
||||
@@ -754,21 +767,45 @@ void setup(){
|
||||
void loop(){
|
||||
ArduinoOTA.handle();
|
||||
|
||||
ws.cleanupClients();
|
||||
// Handle OneButton instances
|
||||
testButton.tick();
|
||||
resetButton.tick();
|
||||
|
||||
// Handle OneButton
|
||||
button.tick();
|
||||
|
||||
// Process button events outside of callback
|
||||
if (btnClickPending) {
|
||||
btnClickPending = false;
|
||||
Serial.println("[BUTTON] Click detected: playing track 1000");
|
||||
playTrack(1000, "Manual Click");
|
||||
// Process TEST_BUTTON click: toggle relay manually
|
||||
if (testBtnClickPending) {
|
||||
testBtnClickPending = false;
|
||||
manualRelayOn = !manualRelayOn;
|
||||
if (manualRelayOn) {
|
||||
digitalWrite(RELAY_PIN, LOW); // relay active LOW
|
||||
relayOn = true;
|
||||
Serial.println("[BUTTON] Manual relay ON");
|
||||
DynamicJsonDocument d(256);
|
||||
d["type"] = "log";
|
||||
d["msg"] = "🔊 Relay dinyalakan manual";
|
||||
sendJsonWs(d);
|
||||
} else {
|
||||
digitalWrite(RELAY_PIN, HIGH); // relay off
|
||||
relayOn = false;
|
||||
Serial.println("[BUTTON] Manual relay OFF");
|
||||
DynamicJsonDocument d(256);
|
||||
d["type"] = "log";
|
||||
d["msg"] = "🔇 Relay dimatikan manual";
|
||||
sendJsonWs(d);
|
||||
}
|
||||
broadcastStatus();
|
||||
}
|
||||
|
||||
if (btnLongPressPending) {
|
||||
btnLongPressPending = false;
|
||||
Serial.println("[BUTTON] Long press detected: resetting admin credentials");
|
||||
// Process TEST_BUTTON long press: play test MP3
|
||||
if (testBtnLongPressPending) {
|
||||
testBtnLongPressPending = false;
|
||||
Serial.println("[BUTTON] Long press detected: playing track 1000");
|
||||
playTrack(1000, "Manual Test");
|
||||
}
|
||||
|
||||
// Process RESET_BUTTON long press: reset admin credentials
|
||||
if (resetBtnLongPressPending) {
|
||||
resetBtnLongPressPending = false;
|
||||
Serial.println("[BUTTON] Reset button long press: resetting admin credentials");
|
||||
resetAdminToDefault();
|
||||
}
|
||||
|
||||
@@ -842,8 +879,8 @@ void loop(){
|
||||
}
|
||||
}
|
||||
|
||||
// release relay if conditions met
|
||||
if (!busy && relayOn && millis() > relayHoldUntil) {
|
||||
// release relay if conditions met (but not if manual mode is active)
|
||||
if (!busy && relayOn && millis() > relayHoldUntil && !manualRelayOn) {
|
||||
digitalWrite(RELAY_PIN, HIGH); // OFF
|
||||
relayOn = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user