Version 02 of Relay
This commit is contained in:
1 parent
ec078c0d00
commit
dd5a8b28f7
5 files changed
+343
-237
No files matched your search
+164
-88
@@ -1,105 +1,181 @@
|
||||
#include <Wire.h>
|
||||
#include <EEPROM.h>
|
||||
|
||||
#define DEFAULT_ADDRESS 0x08
|
||||
#define MAX_NAME_LENGTH 24
|
||||
#define EEPROM_SIZE 64
|
||||
#define EEPROM_ADDR_LOC 0 // EEPROM location for I2C address
|
||||
#define EEPROM_NAME_LOC 1 // EEPROM location for device name
|
||||
#define DEVICE_NAME_LEN 24
|
||||
#define DEFAULT_I2C_ADDR 0x08 // Default I2C address
|
||||
|
||||
// EEPROM Structure
|
||||
struct Config {
|
||||
uint8_t address;
|
||||
char deviceName[MAX_NAME_LENGTH+1];
|
||||
uint8_t relayStates;
|
||||
char deviceName[DEVICE_NAME_LEN] = "Relay";
|
||||
uint8_t i2cAddress = DEFAULT_I2C_ADDR;
|
||||
|
||||
// I2C command codes
|
||||
enum Command : uint8_t {
|
||||
CMD_SET_ADDR = 0x01,
|
||||
CMD_SET_NAME = 0x02,
|
||||
};
|
||||
|
||||
Config config;
|
||||
// --- RELAY FEATURE ADDITIONS ---
|
||||
const int relayPins[8] = {0, 1, 2, 3, 4, 5, 6, 7}; // GPIOs 0-7
|
||||
uint8_t relayStates[8] = {0}; // 0=OFF, 1=ON
|
||||
unsigned long relayTimers[8] = {0}; // millis() when to turn off, 0 = no timer
|
||||
|
||||
void handleCommand(int numBytes);
|
||||
void saveConfig();
|
||||
void loadConfig();
|
||||
void emergencyStop();
|
||||
enum RelayCommand : uint8_t {
|
||||
CMD_RELAY_SET = 0x10, // [relay#][0|1] (relay# = 1..8)
|
||||
CMD_RELAY_ALL = 0x11, // [0|1]
|
||||
CMD_RELAY_TIMER = 0x12, // [relay#][ms_L][ms_H][ms_U][ms_T]
|
||||
CMD_RELAY_ALL_TIMER = 0x13 // [ms_L][ms_H][ms_U][ms_T]
|
||||
};
|
||||
|
||||
// *** INVERTED RELAY LOGIC ***
|
||||
// User relay numbers: 1–8. Array indices: 0–7.
|
||||
void setRelay(uint8_t relayNum, uint8_t state) {
|
||||
if (relayNum >= 1 && relayNum <= 8) {
|
||||
uint8_t idx = relayNum - 1;
|
||||
relayStates[idx] = (state == 1 ? 1 : 0);
|
||||
// Inverted logic: LOW = ON, HIGH = OFF
|
||||
digitalWrite(relayPins[idx], relayStates[idx] ? LOW : HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
void setAllRelays(uint8_t state) {
|
||||
for (uint8_t i = 1; i <= 8; i++) setRelay(i, state);
|
||||
}
|
||||
// --- END RELAY FEATURE ADDITIONS ---
|
||||
|
||||
void storeAddressToEEPROM(uint8_t addr) {
|
||||
EEPROM.write(EEPROM_ADDR_LOC, addr);
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
uint8_t readAddressFromEEPROM() {
|
||||
uint8_t addr = EEPROM.read(EEPROM_ADDR_LOC);
|
||||
if (addr == 0xFF || addr == 0x00) {
|
||||
addr = DEFAULT_I2C_ADDR;
|
||||
storeAddressToEEPROM(addr);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
void storeNameToEEPROM(const char* name) {
|
||||
for (int i = 0; i < DEVICE_NAME_LEN; i++) {
|
||||
EEPROM.write(EEPROM_NAME_LOC + i, name[i]);
|
||||
if (name[i] == '\0') break;
|
||||
}
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
void readNameFromEEPROM(char* name) {
|
||||
for (int i = 0; i < DEVICE_NAME_LEN; i++) {
|
||||
name[i] = EEPROM.read(EEPROM_NAME_LOC + i);
|
||||
if (name[i] == '\0') break;
|
||||
}
|
||||
name[DEVICE_NAME_LEN - 1] = '\0';
|
||||
}
|
||||
|
||||
// Handle data received from master
|
||||
void onReceive(int len) {
|
||||
if (len < 1) return;
|
||||
uint8_t cmd = Wire.read();
|
||||
switch (cmd) {
|
||||
case CMD_SET_ADDR:
|
||||
if (Wire.available()) {
|
||||
uint8_t newAddr = Wire.read();
|
||||
if (newAddr > 0x00 && newAddr < 0x78) {
|
||||
storeAddressToEEPROM(newAddr);
|
||||
ESP.restart();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CMD_SET_NAME: {
|
||||
int i = 0;
|
||||
while (Wire.available() && i < DEVICE_NAME_LEN - 1) {
|
||||
deviceName[i++] = Wire.read();
|
||||
}
|
||||
deviceName[i] = '\0';
|
||||
storeNameToEEPROM(deviceName);
|
||||
break;
|
||||
}
|
||||
// --- RELAY FEATURE ADDITIONS ---
|
||||
case CMD_RELAY_SET:
|
||||
if (Wire.available() >= 2) {
|
||||
uint8_t relayNum = Wire.read(); // Now 1..8
|
||||
uint8_t state = Wire.read(); // 0|1
|
||||
setRelay(relayNum, state);
|
||||
if (relayNum >= 1 && relayNum <= 8) relayTimers[relayNum-1] = 0;
|
||||
}
|
||||
break;
|
||||
case CMD_RELAY_ALL:
|
||||
if (Wire.available() >= 1) {
|
||||
uint8_t state = Wire.read(); // 0|1
|
||||
setAllRelays(state);
|
||||
for (int i = 0; i < 8; i++) relayTimers[i] = 0;
|
||||
}
|
||||
break;
|
||||
case CMD_RELAY_TIMER:
|
||||
if (Wire.available() >= 5) {
|
||||
uint8_t relayNum = Wire.read(); // 1..8
|
||||
uint32_t ms = Wire.read();
|
||||
ms |= ((uint32_t)Wire.read()) << 8;
|
||||
ms |= ((uint32_t)Wire.read()) << 16;
|
||||
ms |= ((uint32_t)Wire.read()) << 24;
|
||||
setRelay(relayNum, 1);
|
||||
if (relayNum >= 1 && relayNum <= 8)
|
||||
relayTimers[relayNum-1] = millis() + ms;
|
||||
}
|
||||
break;
|
||||
case CMD_RELAY_ALL_TIMER:
|
||||
if (Wire.available() >= 4) {
|
||||
uint32_t ms = Wire.read();
|
||||
ms |= ((uint32_t)Wire.read()) << 8;
|
||||
ms |= ((uint32_t)Wire.read()) << 16;
|
||||
ms |= ((uint32_t)Wire.read()) << 24;
|
||||
setAllRelays(1);
|
||||
unsigned long offTime = millis() + ms;
|
||||
for (int i = 0; i < 8; i++) relayTimers[i] = offTime;
|
||||
}
|
||||
break;
|
||||
// --- END RELAY FEATURE ADDITIONS ---
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle data requested by master
|
||||
void onRequest() {
|
||||
String response = String(i2cAddress, HEX) + ",GENERIC," + deviceName;
|
||||
Wire.write((const uint8_t*)response.c_str(), response.length());
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
EEPROM.begin(sizeof(Config));
|
||||
loadConfig();
|
||||
|
||||
// Initialize relays
|
||||
for(int i=0; i<8; i++) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
|
||||
i2cAddress = readAddressFromEEPROM();
|
||||
readNameFromEEPROM(deviceName);
|
||||
|
||||
Wire.begin(i2cAddress);
|
||||
Wire.onReceive(onReceive);
|
||||
Wire.onRequest(onRequest);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
pinMode(relayPins[i], OUTPUT);
|
||||
digitalWrite(relayPins[i], HIGH); // Active-low logic
|
||||
digitalWrite(relayPins[i], HIGH); // Inverted logic: HIGH = OFF at start
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
Serial.print("I2C Slave started at address 0x");
|
||||
Serial.println(i2cAddress, HEX);
|
||||
Serial.print("Device name: ");
|
||||
Serial.println(deviceName);
|
||||
}
|
||||
|
||||
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 loop() {
|
||||
unsigned long now = millis();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (relayTimers[i] && now >= relayTimers[i]) {
|
||||
setRelay(i+1, 0); // Use relay number 1..8
|
||||
relayTimers[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
Reference in new issue
Block a user