241 lines
6.3 KiB
C++
241 lines
6.3 KiB
C++
/*
|
|
* 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);
|
|
}
|