I2CRelay/examples/Slave/Slave.ino

106 lines
2.2 KiB
C++

#include <Wire.h>
#include <EEPROM.h>
#define DEFAULT_ADDRESS 0x08
#define MAX_NAME_LENGTH 24
// EEPROM Structure
struct Config {
uint8_t address;
char deviceName[MAX_NAME_LENGTH+1];
uint8_t relayStates;
};
Config config;
const int relayPins[8] = {0, 1, 2, 3, 4, 5, 6, 7}; // GPIOs 0-7
void handleCommand(int numBytes);
void saveConfig();
void loadConfig();
void emergencyStop();
void setup() {
Serial.begin(115200);
EEPROM.begin(sizeof(Config));
loadConfig();
// Initialize relays
for(int i=0; i<8; i++) {
pinMode(relayPins[i], OUTPUT);
digitalWrite(relayPins[i], HIGH); // Active-low logic
}
Wire.onReceive(handleCommand);
Wire.onRequest([]() {
String response = String(config.address) + ",8-relay," +
config.deviceName + "," +
String(config.relayStates, BIN);
Wire.print(response);
});
Wire.begin((uint8_t)config.address);
}
void loop() { /* Empty */ }
void handleCommand(int numBytes) {
uint8_t cmd = Wire.read();
switch(cmd) {
case 0xA0: // Set relay state
if(numBytes == 3) {
uint8_t relay = Wire.read();
uint8_t state = Wire.read();
if(relay < 8) {
digitalWrite(relayPins[relay], state ? LOW : HIGH);
bitWrite(config.relayStates, relay, state);
}
}
break;
case 0xB0: // Emergency stop
emergencyStop();
break;
case 0xC0: // Set address
if(numBytes == 2) {
config.address = Wire.read();
saveConfig();
Wire.begin((uint8_t)config.address);
}
break;
case 0xD0: // Set device name
if(numBytes > 1) {
uint8_t i = 0;
while(Wire.available() && i < MAX_NAME_LENGTH) {
config.deviceName[i++] = Wire.read();
}
config.deviceName[i] = '\0';
saveConfig();
}
break;
}
}
void emergencyStop() {
for(int i=0; i<8; i++) {
digitalWrite(relayPins[i], HIGH);
}
config.relayStates = 0;
}
void loadConfig() {
EEPROM.get(0, config);
if(config.address < 0x08 || config.address > 0x77) {
config.address = DEFAULT_ADDRESS;
strcpy(config.deviceName, "8-Relay Module");
saveConfig();
}
}
void saveConfig() {
EEPROM.put(0, config);
EEPROM.commit();
}