Version 02 of Relay

This commit is contained in:
fatimaxsen committed 2025-05-18 10:06:27 +03:00
1 parent ec078c0d00
commit dd5a8b28f7
5 files changed
+343 -237

No files matched your search

+61 -43
View File
@@ -1,57 +1,75 @@
#include <I2CRelay.h>
#include <Wire.h>
#include "I2CRelay.h"
I2CRelay relay;
I2CRelay relay(8, 3); // Use your SDA/SCL pins
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("I2CRelay Master Example with 'i' command for ID");
relay.begin();
Serial.begin(115200);
relay.begin();
// Run test functions as before
relay.setRelay(1, 1);
relay.setRelay(8, 1);
Serial.println("Turned ON relay 1 and relay 8");
delay(500);
uint8_t addr = 0x08;
relay.setRelay(1, 0);
relay.setRelay(8, 0);
Serial.println("Turned OFF relay 1 and relay 8");
delay(500);
// 1. Scan the I2C bus
Serial.println("=== I2C Scan ===");
relay.scan();
relay.setAllRelays(1);
Serial.println("Turned ON all relays");
delay(500);
// 2. Get info from the slave
Serial.println("=== Request Info ===");
String info = relay.requestSlaveInfo(addr);
Serial.print("Info: ");
Serial.println(info);
relay.setAllRelays(0);
Serial.println("Turned OFF all relays");
delay(500);
// 3. Change the slave name
Serial.println("=== Change Name ===");
relay.setSlaveName(addr, "FirstRelay");
delay(100);
Serial.println("Name changed.");
relay.setDeviceName("TestPanel");
Serial.println("Device name set to 'TestPanel'");
delay(500);
// 4. Turn relay 1 ON
Serial.println("=== Turn Relay 1 ON ===");
relay.setRelay(addr, 1, 1); // 1 = ON
delay(1500);
String id = relay.getIdentification();
Serial.print("Identification string: ");
Serial.println(id);
delay(500);
// 5. Turn relay 1 OFF
Serial.println("=== Turn Relay 1 OFF ===");
relay.setRelay(addr, 1, 0); // 0 = OFF
delay(500);
relay.setI2CAddress(0x09);
Serial.println("Changed I2C address to 0x09");
Serial.println("** Update master address to 0x09 for further communication **");
// 6. Turn all relays ON
Serial.println("=== Turn All Relays ON ===");
relay.setAllRelays(addr, 1); // 1 = ON
delay(500);
// 7. Turn all relays OFF
Serial.println("=== Turn All Relays OFF ===");
relay.setAllRelays(addr, 0); // 0 = OFF
delay(500);
// 8. Turn relay 2 ON for 2 seconds
Serial.println("=== Relay 2 ON for 2 seconds ===");
relay.setRelayTimer(addr, 2, 2000); // relay 2, 2000 ms
delay(2500);
// 9. Turn all relays ON for 3 seconds
Serial.println("=== All relays ON for 3 seconds ===");
relay.setAllRelaysTimer(addr, 3000); // 3000 ms
delay(3500);
// 10. Change slave address from 0x08 to 0x09
Serial.println("=== Change Address 0x08 -> 0x09 ===");
relay.setSlaveAddress(0x08, 0x08);
addr = 0x08; // Use new address for further commands
delay(1500);
// 11. Confirm new address by requesting info
Serial.println("=== Request Info from 0x09 ===");
info = relay.requestSlaveInfo(addr);
Serial.print("Info: ");
Serial.println(info);
Serial.println("=== Test Complete ===");
}
void loop() {
if (Serial.available()) {
String cmd = Serial.readStringUntil('\n');
cmd.trim();
// Replace "id" with "i" here:
if (cmd == "i") {
String id = relay.getIdentification();
Serial.print("ID: ");
Serial.println(id);
} else {
relay.handleSerialCommand(cmd);
}
}
// Nothing here
}
+164 -88
View File
@@ -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();
}