/* * 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 // 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); }