diff --git a/esp32_bluetooth_relay/esp32_bluetooth_relay.ino b/esp32_bluetooth_relay/esp32_bluetooth_relay.ino new file mode 100644 index 0000000..7623846 --- /dev/null +++ b/esp32_bluetooth_relay/esp32_bluetooth_relay.ino @@ -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 + +// 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); +}