Add main ESP32 firmware with Bluetooth control

This commit is contained in:
2025-12-15 16:08:05 +11:00
parent db3487c8e8
commit 4e373574d2

View File

@@ -0,0 +1,240 @@
/*
* ESP32 8-Channel Bluetooth Relay Controller
*
* Features:
* - Control 8 relays via Bluetooth Serial
* - Individual relay on/off control
* - All relays on/off commands
* - Status query for all relays
* - Toggle individual relays
* - Persistent state (remembers relay states on reboot)
*
* Commands:
* - ON1-8: Turn on relay 1-8
* - OFF1-8: Turn off relay 1-8
* - TOGGLE1-8: Toggle relay 1-8
* - ALL_ON: Turn all relays on
* - ALL_OFF: Turn all relays off
* - STATUS: Get status of all relays
* - HELP: Show available commands
*/
#include "BluetoothSerial.h"
#include <Preferences.h>
// Check if Bluetooth is enabled
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to enable it
#endif
// Bluetooth Serial object
BluetoothSerial SerialBT;
// Preferences for persistent storage
Preferences preferences;
// Define relay pins (adjust these based on your ESP32 board)
const int relayPins[8] = {13, 12, 14, 27, 26, 25, 33, 32};
// Relay states (true = ON, false = OFF)
bool relayStates[8] = {false, false, false, false, false, false, false, false};
// Relay names for easier identification
const char* relayNames[8] = {
"Relay 1", "Relay 2", "Relay 3", "Relay 4",
"Relay 5", "Relay 6", "Relay 7", "Relay 8"
};
// Device name for Bluetooth
const char* deviceName = "ESP32-Relay-8CH";
// Command buffer
String commandBuffer = "";
void setup() {
// Initialize serial for debugging
Serial.begin(115200);
Serial.println("\nESP32 8-Channel Bluetooth Relay Controller");
Serial.println("==========================================");
// Initialize preferences
preferences.begin("relay-states", false);
// Initialize relay pins
for (int i = 0; i < 8; i++) {
pinMode(relayPins[i], OUTPUT);
// Load saved state from preferences
relayStates[i] = preferences.getBool(String("relay" + String(i)).c_str(), false);
// Set initial state (relays are typically active LOW)
digitalWrite(relayPins[i], relayStates[i] ? LOW : HIGH);
Serial.printf("Pin %d (%s): %s\n", relayPins[i], relayNames[i],
relayStates[i] ? "ON" : "OFF");
}
// Initialize Bluetooth Serial
if(!SerialBT.begin(deviceName)) {
Serial.println("Bluetooth initialization failed!");
while(1);
}
Serial.printf("\nBluetooth device \"%s\" is ready to pair!\n", deviceName);
Serial.println("Waiting for Bluetooth connection...\n");
// Print available commands
printHelp();
}
void loop() {
// Check for Bluetooth data
while (SerialBT.available()) {
char inChar = (char)SerialBT.read();
// Add character to buffer
if (inChar == '\n' || inChar == '\r') {
// Process command when newline is received
if (commandBuffer.length() > 0) {
processCommand(commandBuffer);
commandBuffer = "";
}
} else {
commandBuffer += inChar;
}
}
// Small delay to prevent watchdog issues
delay(10);
}
void processCommand(String command) {
command.trim();
command.toUpperCase();
Serial.printf("Received command: %s\n", command.c_str());
// ON commands (ON1 through ON8)
if (command.startsWith("ON") && command.length() == 3) {
int relayNum = command.charAt(2) - '0';
if (relayNum >= 1 && relayNum <= 8) {
setRelay(relayNum - 1, true);
return;
}
}
// OFF commands (OFF1 through OFF8)
if (command.startsWith("OFF") && command.length() == 4) {
int relayNum = command.charAt(3) - '0';
if (relayNum >= 1 && relayNum <= 8) {
setRelay(relayNum - 1, false);
return;
}
}
// TOGGLE commands (TOGGLE1 through TOGGLE8)
if (command.startsWith("TOGGLE") && command.length() == 7) {
int relayNum = command.charAt(6) - '0';
if (relayNum >= 1 && relayNum <= 8) {
toggleRelay(relayNum - 1);
return;
}
}
// ALL_ON command
if (command == "ALL_ON" || command == "ALLON") {
setAllRelays(true);
return;
}
// ALL_OFF command
if (command == "ALL_OFF" || command == "ALLOFF") {
setAllRelays(false);
return;
}
// STATUS command
if (command == "STATUS" || command == "STATE") {
sendStatus();
return;
}
// HELP command
if (command == "HELP" || command == "?") {
printHelp();
return;
}
// Unknown command
SerialBT.println("ERROR: Unknown command");
Serial.println("ERROR: Unknown command");
SerialBT.println("Type HELP for available commands");
}
void setRelay(int relayIndex, bool state) {
if (relayIndex < 0 || relayIndex >= 8) return;
relayStates[relayIndex] = state;
// Relays are typically active LOW (relay on when pin is LOW)
digitalWrite(relayPins[relayIndex], state ? LOW : HIGH);
// Save state to preferences
preferences.putBool(String("relay" + String(relayIndex)).c_str(), state);
// Send confirmation
String response = String(relayNames[relayIndex]) + " is now " +
(state ? "ON" : "OFF");
SerialBT.println(response);
Serial.println(response);
}
void toggleRelay(int relayIndex) {
if (relayIndex < 0 || relayIndex >= 8) return;
setRelay(relayIndex, !relayStates[relayIndex]);
}
void setAllRelays(bool state) {
for (int i = 0; i < 8; i++) {
relayStates[i] = state;
digitalWrite(relayPins[i], state ? LOW : HIGH);
preferences.putBool(String("relay" + String(i)).c_str(), state);
}
String response = "All relays turned " + String(state ? "ON" : "OFF");
SerialBT.println(response);
Serial.println(response);
}
void sendStatus() {
SerialBT.println("=== Relay Status ===");
Serial.println("=== Relay Status ===");
for (int i = 0; i < 8; i++) {
String status = String(relayNames[i]) + ": " +
(relayStates[i] ? "ON" : "OFF");
SerialBT.println(status);
Serial.println(status);
}
SerialBT.println("===================");
Serial.println("===================");
}
void printHelp() {
const char* helpText = R"(
=== Available Commands ===
ON1-8 : Turn on relay 1-8 (e.g., ON1, ON5)
OFF1-8 : Turn off relay 1-8 (e.g., OFF1, OFF8)
TOGGLE1-8 : Toggle relay 1-8 (e.g., TOGGLE1)
ALL_ON : Turn all relays on
ALL_OFF : Turn all relays off
STATUS : Get current status of all relays
HELP : Show this help message
==========================
)";
SerialBT.print(helpText);
Serial.print(helpText);
}