#include #include // EEPROM settings #define ADDR_EEPROM_LOC 0 #define EEPROM_SIZE 64 // Relay pins: GPIO0 to GPIO7 const int relayPins[8] = {0, 1, 2, 3, 4, 5, 6, 7}; // GPIOs 0-7 uint8_t i2cAddress; // Unified I2C receive event void receiveEvent(int howMany) { if (howMany >= 2) { uint8_t first = Wire.read(); uint8_t second = Wire.read(); // Check for address change command if (first == 0xAA) { // Change I2C address and store in EEPROM uint8_t newAddr = second; EEPROM.write(ADDR_EEPROM_LOC, newAddr); EEPROM.commit(); Serial.print("I2C address changed to: 0x"); Serial.println(newAddr, HEX); delay(100); ESP.restart(); return; } // Otherwise, treat as relay control int relay = first; // Relay number: 1-8 int state = second; // State: 1=ON, 0=OFF if (relay >= 1 && relay <= 8) { digitalWrite(relayPins[relay - 1], state ? LOW : HIGH); // Active LOW relays } } } void setup() { Serial.begin(115200); EEPROM.begin(EEPROM_SIZE); // Read I2C address from EEPROM or use default i2cAddress = EEPROM.read(ADDR_EEPROM_LOC); if (i2cAddress == 0xFF || i2cAddress == 0) i2cAddress = 0x08; // Default address Serial.print("Using I2C address: 0x"); Serial.println(i2cAddress, HEX); // Initialize relay pins for (int i = 0; i < 8; i++) { pinMode(relayPins[i], OUTPUT); digitalWrite(relayPins[i], HIGH); // Relays OFF initially (active LOW) } // Start I2C slave Wire.begin(i2cAddress); Wire.onReceive(receiveEvent); } void loop() { // Nothing needed here for basic operation }