Version 02 of Relay
This commit is contained in:
parent
ec078c0d00
commit
dd5a8b28f7
32
README.md
32
README.md
@ -77,19 +77,23 @@ The I2CRelay library offers broad versatility for automation through its configu
|
|||||||
|
|
||||||
### API Overview
|
### API Overview
|
||||||
|
|
||||||
| Method / Constructor | Description | Parameters / Usage Example |
|
| Function | Description | Example Usage |
|
||||||
|---------------------------------------------------|-------------------------------------------------------------------------------------------------------------|------------------------------------------------------|
|
|--------------------------------------------------------------------------|-----------------------------------------------------------------------------|-----------------------------------------------|
|
||||||
| `I2CRelay(uint8_t address = 0x08, uint8_t sda = 8, uint8_t scl = 3)` | Create an I2CRelay object with optional I2C address and pin selection. | `I2CRelay relay;`<br>`I2CRelay relay(0x10, 21, 22);` |
|
| **I2CRelay(uint8_t sda, uint8_t scl)** | Constructor: set I2C SDA/SCL pins (optional, defaults to board pins) | `I2CRelay relay(8, 3);` |
|
||||||
| `void begin()` | Initialize I2C communication with the configured pins. | `relay.begin();` |
|
| **void begin()** | Initialize the I2C bus | `relay.begin();` |
|
||||||
| `void setRelay(uint8_t relayNum, uint8_t state)` | Turn relay (1–8) ON or OFF. | `relay.setRelay(3, 1); // ON relay 3` |
|
| **void scan(Stream &out = Serial)** | Scan and print all I2C devices on the bus | `relay.scan();` |
|
||||||
| `void setAllRelays(uint8_t state)` | Turn all relays ON or OFF at once. | `relay.setAllRelays(0); // OFF all relays` |
|
| **void setSlaveAddress(uint8_t oldAddr, uint8_t newAddr, Stream &out = Serial)** | Change the slave’s I2C address | `relay.setSlaveAddress(0x08, 0x09);` |
|
||||||
| `void setDeviceName(const String &name)` | Set the name of the I2C relay device (up to 24 chars). | `relay.setDeviceName("MainPanel");` |
|
| **void setSlaveName(uint8_t addr, const char* name, Stream &out = Serial)** | Change the slave’s device name | `relay.setSlaveName(0x08, "MyRelay");` |
|
||||||
| `void setI2CAddress(uint8_t newAddr)` | Change the I2C address of the relay slave. | `relay.setI2CAddress(0x12);` |
|
| **String requestSlaveInfo(uint8_t addr)** | Get info string from the slave | `String info = relay.requestSlaveInfo(0x08);` |
|
||||||
| `String getIdentification()` | Query the slave for its identification string (address, type, name, states). | `String id = relay.getIdentification();` |
|
| **bool setRelay(uint8_t addr, uint8_t relayNum, uint8_t state)** | Set relay (1–8) ON/OFF (`state`: 1=ON, 0=OFF) | `relay.setRelay(0x08, 3, 1);` |
|
||||||
| `void handleSerialCommand(const String &cmd)` | Parse and execute a serial command string (e.g., `"r 2 1"`, `"all 0"`). | `relay.handleSerialCommand("r 2 1");` |
|
| **bool setAllRelays(uint8_t addr, uint8_t state)** | Set all relays ON/OFF (`state`: 1=ON, 0=OFF) | `relay.setAllRelays(0x08, 0);` |
|
||||||
|
| **bool setRelayTimer(uint8_t addr, uint8_t relayNum, uint32_t ms)** | Set relay (1–8) ON for given ms, then auto-OFF | `relay.setRelayTimer(0x08, 2, 2000);` |
|
||||||
|
| **bool setAllRelaysTimer(uint8_t addr, uint32_t ms)** | Set all relays ON for given ms, then auto-OFF | `relay.setAllRelaysTimer(0x08, 3000);` |
|
||||||
|
|
||||||
**Notes:**
|
### Parameter Notes
|
||||||
- `relayNum` is 1–8 (user-facing), mapped internally to 0–7.
|
|
||||||
- `state` is `1` (ON) or `0` (OFF).
|
- **addr**: I2C address of the slave (e.g. `0x08`)
|
||||||
- All methods are non-blocking except `setAllRelays`, which adds a small delay between commands.
|
- **relayNum**: Relay number **1–8**
|
||||||
|
- **state**: `1` = ON, `0` = OFF
|
||||||
|
- **ms**: Duration in milliseconds
|
||||||
|
|
||||||
|
@ -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() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
delay(1000);
|
|
||||||
Serial.println("I2CRelay Master Example with 'i' command for ID");
|
|
||||||
relay.begin();
|
relay.begin();
|
||||||
|
|
||||||
// Run test functions as before
|
uint8_t addr = 0x08;
|
||||||
relay.setRelay(1, 1);
|
|
||||||
relay.setRelay(8, 1);
|
// 1. Scan the I2C bus
|
||||||
Serial.println("Turned ON relay 1 and relay 8");
|
Serial.println("=== I2C Scan ===");
|
||||||
|
relay.scan();
|
||||||
|
|
||||||
|
// 2. Get info from the slave
|
||||||
|
Serial.println("=== Request Info ===");
|
||||||
|
String info = relay.requestSlaveInfo(addr);
|
||||||
|
Serial.print("Info: ");
|
||||||
|
Serial.println(info);
|
||||||
|
|
||||||
|
// 3. Change the slave name
|
||||||
|
Serial.println("=== Change Name ===");
|
||||||
|
relay.setSlaveName(addr, "FirstRelay");
|
||||||
|
delay(100);
|
||||||
|
Serial.println("Name changed.");
|
||||||
|
|
||||||
|
// 4. Turn relay 1 ON
|
||||||
|
Serial.println("=== Turn Relay 1 ON ===");
|
||||||
|
relay.setRelay(addr, 1, 1); // 1 = ON
|
||||||
|
delay(1500);
|
||||||
|
|
||||||
|
// 5. Turn relay 1 OFF
|
||||||
|
Serial.println("=== Turn Relay 1 OFF ===");
|
||||||
|
relay.setRelay(addr, 1, 0); // 0 = OFF
|
||||||
delay(500);
|
delay(500);
|
||||||
|
|
||||||
relay.setRelay(1, 0);
|
// 6. Turn all relays ON
|
||||||
relay.setRelay(8, 0);
|
Serial.println("=== Turn All Relays ON ===");
|
||||||
Serial.println("Turned OFF relay 1 and relay 8");
|
relay.setAllRelays(addr, 1); // 1 = ON
|
||||||
delay(500);
|
delay(500);
|
||||||
|
|
||||||
relay.setAllRelays(1);
|
// 7. Turn all relays OFF
|
||||||
Serial.println("Turned ON all relays");
|
Serial.println("=== Turn All Relays OFF ===");
|
||||||
|
relay.setAllRelays(addr, 0); // 0 = OFF
|
||||||
delay(500);
|
delay(500);
|
||||||
|
|
||||||
relay.setAllRelays(0);
|
// 8. Turn relay 2 ON for 2 seconds
|
||||||
Serial.println("Turned OFF all relays");
|
Serial.println("=== Relay 2 ON for 2 seconds ===");
|
||||||
delay(500);
|
relay.setRelayTimer(addr, 2, 2000); // relay 2, 2000 ms
|
||||||
|
delay(2500);
|
||||||
|
|
||||||
relay.setDeviceName("TestPanel");
|
// 9. Turn all relays ON for 3 seconds
|
||||||
Serial.println("Device name set to 'TestPanel'");
|
Serial.println("=== All relays ON for 3 seconds ===");
|
||||||
delay(500);
|
relay.setAllRelaysTimer(addr, 3000); // 3000 ms
|
||||||
|
delay(3500);
|
||||||
|
|
||||||
String id = relay.getIdentification();
|
// 10. Change slave address from 0x08 to 0x09
|
||||||
Serial.print("Identification string: ");
|
Serial.println("=== Change Address 0x08 -> 0x09 ===");
|
||||||
Serial.println(id);
|
relay.setSlaveAddress(0x08, 0x08);
|
||||||
delay(500);
|
addr = 0x08; // Use new address for further commands
|
||||||
|
delay(1500);
|
||||||
|
|
||||||
relay.setI2CAddress(0x09);
|
// 11. Confirm new address by requesting info
|
||||||
Serial.println("Changed I2C address to 0x09");
|
Serial.println("=== Request Info from 0x09 ===");
|
||||||
Serial.println("** Update master address to 0x09 for further communication **");
|
info = relay.requestSlaveInfo(addr);
|
||||||
|
Serial.print("Info: ");
|
||||||
|
Serial.println(info);
|
||||||
|
|
||||||
|
Serial.println("=== Test Complete ===");
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
if (Serial.available()) {
|
// Nothing here
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,105 +1,181 @@
|
|||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
|
|
||||||
#define DEFAULT_ADDRESS 0x08
|
#define EEPROM_SIZE 64
|
||||||
#define MAX_NAME_LENGTH 24
|
#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
|
char deviceName[DEVICE_NAME_LEN] = "Relay";
|
||||||
struct Config {
|
uint8_t i2cAddress = DEFAULT_I2C_ADDR;
|
||||||
uint8_t address;
|
|
||||||
char deviceName[MAX_NAME_LENGTH+1];
|
// I2C command codes
|
||||||
uint8_t relayStates;
|
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
|
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);
|
enum RelayCommand : uint8_t {
|
||||||
void saveConfig();
|
CMD_RELAY_SET = 0x10, // [relay#][0|1] (relay# = 1..8)
|
||||||
void loadConfig();
|
CMD_RELAY_ALL = 0x11, // [0|1]
|
||||||
void emergencyStop();
|
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() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
EEPROM.begin(sizeof(Config));
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
loadConfig();
|
|
||||||
|
|
||||||
// Initialize relays
|
i2cAddress = readAddressFromEEPROM();
|
||||||
for(int i=0; i<8; i++) {
|
readNameFromEEPROM(deviceName);
|
||||||
|
|
||||||
|
Wire.begin(i2cAddress);
|
||||||
|
Wire.onReceive(onReceive);
|
||||||
|
Wire.onRequest(onRequest);
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
pinMode(relayPins[i], OUTPUT);
|
pinMode(relayPins[i], OUTPUT);
|
||||||
digitalWrite(relayPins[i], HIGH); // Active-low logic
|
digitalWrite(relayPins[i], HIGH); // Inverted logic: HIGH = OFF at start
|
||||||
}
|
}
|
||||||
|
|
||||||
Wire.onReceive(handleCommand);
|
Serial.print("I2C Slave started at address 0x");
|
||||||
Wire.onRequest([]() {
|
Serial.println(i2cAddress, HEX);
|
||||||
String response = String(config.address) + ",8-relay," +
|
Serial.print("Device name: ");
|
||||||
config.deviceName + "," +
|
Serial.println(deviceName);
|
||||||
String(config.relayStates, BIN);
|
|
||||||
Wire.print(response);
|
|
||||||
});
|
|
||||||
|
|
||||||
Wire.begin((uint8_t)config.address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() { /* Empty */ }
|
void loop() {
|
||||||
|
unsigned long now = millis();
|
||||||
void handleCommand(int numBytes) {
|
for (int i = 0; i < 8; i++) {
|
||||||
uint8_t cmd = Wire.read();
|
if (relayTimers[i] && now >= relayTimers[i]) {
|
||||||
|
setRelay(i+1, 0); // Use relay number 1..8
|
||||||
switch(cmd) {
|
relayTimers[i] = 0;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
170
src/I2CRelay.cpp
170
src/I2CRelay.cpp
@ -1,102 +1,110 @@
|
|||||||
#include "I2CRelay.h"
|
#include "I2CRelay.h"
|
||||||
|
|
||||||
I2CRelay::I2CRelay(uint8_t address, uint8_t sda, uint8_t scl)
|
// Command codes
|
||||||
: _address(address), _sda(sda), _scl(scl) {}
|
#define CMD_SET_ADDR 0x01
|
||||||
|
#define CMD_SET_NAME 0x02
|
||||||
|
#define CMD_RELAY_SET 0x10
|
||||||
|
#define CMD_RELAY_ALL 0x11
|
||||||
|
#define CMD_RELAY_TIMER 0x12
|
||||||
|
#define CMD_RELAY_ALL_TIMER 0x13
|
||||||
|
|
||||||
|
I2CRelay::I2CRelay(uint8_t sda, uint8_t scl)
|
||||||
|
: _sda(sda), _scl(scl) {}
|
||||||
|
|
||||||
void I2CRelay::begin() {
|
void I2CRelay::begin() {
|
||||||
Wire.begin(_sda, _scl);
|
Wire.begin(_sda, _scl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CRelay::setRelay(uint8_t relayNum, uint8_t state) {
|
void I2CRelay::scan(Stream &out) {
|
||||||
if (relayNum < 1 || relayNum > 8) return;
|
out.println("Scanning I2C bus...");
|
||||||
Wire.beginTransmission(_address);
|
uint8_t count = 0;
|
||||||
Wire.write(0xA0);
|
for (uint8_t address = 1; address < 127; address++) {
|
||||||
Wire.write(relayNum - 1); // Map 1-8 to 0-7
|
Wire.beginTransmission(address);
|
||||||
Wire.write(state);
|
uint8_t error = Wire.endTransmission();
|
||||||
Wire.endTransmission();
|
if (error == 0) {
|
||||||
}
|
out.print("I2C device found at address 0x");
|
||||||
|
if (address < 16) out.print("0");
|
||||||
void I2CRelay::setAllRelays(uint8_t state) {
|
out.print(address, HEX);
|
||||||
for (uint8_t i = 1; i <= 8; i++) {
|
out.println(" !");
|
||||||
setRelay(i, state);
|
count++;
|
||||||
delay(10);
|
|
||||||
}
|
}
|
||||||
}
|
delay(2);
|
||||||
|
|
||||||
void I2CRelay::setDeviceName(const String &name) {
|
|
||||||
Wire.beginTransmission(_address);
|
|
||||||
Wire.write(0xD0);
|
|
||||||
for (uint8_t i = 0; i < name.length() && i < 24; i++) {
|
|
||||||
Wire.write(name[i]);
|
|
||||||
}
|
}
|
||||||
Wire.endTransmission();
|
if (count == 0) {
|
||||||
|
out.println("No I2C devices found.");
|
||||||
|
} else {
|
||||||
|
out.print("Scan complete, devices found: ");
|
||||||
|
out.println(count);
|
||||||
|
}
|
||||||
|
out.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CRelay::setI2CAddress(uint8_t newAddr) {
|
void I2CRelay::setSlaveAddress(uint8_t oldAddr, uint8_t newAddr, Stream &out) {
|
||||||
if (newAddr < 8 || newAddr > 119) return;
|
Wire.beginTransmission(oldAddr);
|
||||||
Wire.beginTransmission(_address);
|
Wire.write(CMD_SET_ADDR);
|
||||||
Wire.write(0xC0);
|
|
||||||
Wire.write(newAddr);
|
Wire.write(newAddr);
|
||||||
Wire.endTransmission();
|
Wire.endTransmission();
|
||||||
|
out.print("Sent address change command: 0x");
|
||||||
|
out.print(oldAddr, HEX);
|
||||||
|
out.print(" -> 0x");
|
||||||
|
out.println(newAddr, HEX);
|
||||||
|
delay(1200); // Give slave time to restart
|
||||||
}
|
}
|
||||||
|
|
||||||
String I2CRelay::getIdentification() {
|
void I2CRelay::setSlaveName(uint8_t addr, const char* newName, Stream &out) {
|
||||||
Wire.requestFrom(_address, (uint8_t)40);
|
Wire.beginTransmission(addr);
|
||||||
String id = "";
|
Wire.write(CMD_SET_NAME);
|
||||||
|
Wire.write((const uint8_t*)newName, strlen(newName));
|
||||||
|
Wire.endTransmission();
|
||||||
|
out.print("Sent name change command to 0x");
|
||||||
|
out.print(addr, HEX);
|
||||||
|
out.print(": ");
|
||||||
|
out.println(newName);
|
||||||
|
}
|
||||||
|
|
||||||
|
String I2CRelay::requestSlaveInfo(uint8_t addr) {
|
||||||
|
Wire.requestFrom(addr, (uint8_t)40);
|
||||||
|
String response = "";
|
||||||
while (Wire.available()) {
|
while (Wire.available()) {
|
||||||
char c = Wire.read();
|
char c = Wire.read();
|
||||||
id += c;
|
response += c;
|
||||||
}
|
}
|
||||||
return id;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CRelay::handleSerialCommand(const String &cmd) {
|
// Relay control
|
||||||
if (cmd.startsWith("r ")) {
|
bool I2CRelay::setRelay(uint8_t addr, uint8_t relay, bool on) {
|
||||||
int space1 = cmd.indexOf(' ');
|
Wire.beginTransmission(addr);
|
||||||
int space2 = cmd.indexOf(' ', space1 + 1);
|
Wire.write(CMD_RELAY_SET);
|
||||||
if (space1 > 0 && space2 > space1) {
|
Wire.write(relay);
|
||||||
int relay = cmd.substring(space1 + 1, space2).toInt();
|
Wire.write(on ? 1 : 0);
|
||||||
int state = cmd.substring(space2 + 1).toInt();
|
return Wire.endTransmission() == 0;
|
||||||
if (relay >= 1 && relay <= 8 && (state == 0 || state == 1)) {
|
}
|
||||||
setRelay(relay, state);
|
|
||||||
Serial.print("Relay ");
|
bool I2CRelay::setAllRelays(uint8_t addr, bool on) {
|
||||||
Serial.print(relay);
|
Wire.beginTransmission(addr);
|
||||||
Serial.print(" set to ");
|
Wire.write(CMD_RELAY_ALL);
|
||||||
Serial.println(state ? "ON" : "OFF");
|
Wire.write(on ? 1 : 0);
|
||||||
} else {
|
return Wire.endTransmission() == 0;
|
||||||
Serial.println("Invalid relay number or state. Use 1-8 and 0/1.");
|
}
|
||||||
}
|
|
||||||
} else {
|
bool I2CRelay::setRelayTimer(uint8_t addr, uint8_t relay, uint32_t ms) {
|
||||||
Serial.println("Usage: r <relayNum 1-8> <0|1>");
|
Wire.beginTransmission(addr);
|
||||||
}
|
Wire.write(CMD_RELAY_TIMER);
|
||||||
} else if (cmd.startsWith("all ")) {
|
Wire.write(relay);
|
||||||
int state = cmd.substring(4).toInt();
|
Wire.write((uint8_t)(ms & 0xFF));
|
||||||
if (state == 0 || state == 1) {
|
Wire.write((uint8_t)((ms >> 8) & 0xFF));
|
||||||
setAllRelays(state);
|
Wire.write((uint8_t)((ms >> 16) & 0xFF));
|
||||||
Serial.print("All relays set to ");
|
Wire.write((uint8_t)((ms >> 24) & 0xFF));
|
||||||
Serial.println(state ? "ON" : "OFF");
|
return Wire.endTransmission() == 0;
|
||||||
} else {
|
}
|
||||||
Serial.println("Invalid state for all.");
|
|
||||||
}
|
bool I2CRelay::setAllRelaysTimer(uint8_t addr, uint32_t ms) {
|
||||||
} else if (cmd.startsWith("name ")) {
|
Wire.beginTransmission(addr);
|
||||||
String name = cmd.substring(5);
|
Wire.write(CMD_RELAY_ALL_TIMER);
|
||||||
setDeviceName(name);
|
Wire.write((uint8_t)(ms & 0xFF));
|
||||||
Serial.print("Device name set to: ");
|
Wire.write((uint8_t)((ms >> 8) & 0xFF));
|
||||||
Serial.println(name);
|
Wire.write((uint8_t)((ms >> 16) & 0xFF));
|
||||||
} else if (cmd.startsWith("addr ")) {
|
Wire.write((uint8_t)((ms >> 24) & 0xFF));
|
||||||
int newAddr = cmd.substring(5).toInt();
|
return Wire.endTransmission() == 0;
|
||||||
if (newAddr >= 8 && newAddr <= 119) {
|
|
||||||
setI2CAddress(newAddr);
|
|
||||||
Serial.print("I2C address set to: ");
|
|
||||||
Serial.println(newAddr, HEX);
|
|
||||||
} else {
|
|
||||||
Serial.println("Invalid address.");
|
|
||||||
}
|
|
||||||
} else if (cmd == "id") {
|
|
||||||
String id = getIdentification();
|
|
||||||
Serial.print("ID: ");
|
|
||||||
Serial.println(id);
|
|
||||||
} else {
|
|
||||||
Serial.println("Unknown command.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -6,22 +6,22 @@
|
|||||||
|
|
||||||
class I2CRelay {
|
class I2CRelay {
|
||||||
public:
|
public:
|
||||||
I2CRelay(uint8_t address = 0x08, uint8_t sda = 8, uint8_t scl = 3);
|
I2CRelay(uint8_t sda = SDA, uint8_t scl = SCL);
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
void setRelay(uint8_t relayNum, uint8_t state);
|
void scan(Stream &out = Serial);
|
||||||
void setAllRelays(uint8_t state);
|
void setSlaveAddress(uint8_t oldAddr, uint8_t newAddr, Stream &out = Serial);
|
||||||
void setDeviceName(const String &name);
|
void setSlaveName(uint8_t addr, const char* newName, Stream &out = Serial);
|
||||||
void setI2CAddress(uint8_t newAddr);
|
String requestSlaveInfo(uint8_t addr);
|
||||||
String getIdentification();
|
|
||||||
|
|
||||||
// Helper for command parsing (optional)
|
// Relay control
|
||||||
void handleSerialCommand(const String &cmd);
|
bool setRelay(uint8_t addr, uint8_t relay, bool on);
|
||||||
|
bool setAllRelays(uint8_t addr, bool on);
|
||||||
|
bool setRelayTimer(uint8_t addr, uint8_t relay, uint32_t ms);
|
||||||
|
bool setAllRelaysTimer(uint8_t addr, uint32_t ms);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t _address;
|
uint8_t _sda, _scl;
|
||||||
uint8_t _sda;
|
|
||||||
uint8_t _scl;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user