first upload

This commit is contained in:
fatimaxsen 2025-04-24 09:34:04 +03:00
commit 1f9edb14b4
13 changed files with 357 additions and 0 deletions

36
I2CMasterUtils.cpp Normal file
View File

@ -0,0 +1,36 @@
#include "I2CMasterUtils.h"
#include "I2CCommands.h"
void I2CMasterUtils::scanI2C(Stream &output) {
output.println("Scanning for I2C devices...");
for (uint8_t addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) {
output.print("Found device at 0x");
output.println(addr, HEX);
}
}
}
void I2CMasterUtils::changeSlaveAddress(uint8_t oldAddr, uint8_t newAddr, Stream &output) {
Wire.beginTransmission(oldAddr);
Wire.write(0xAA); // Command code for address change
Wire.write(newAddr);
Wire.endTransmission();
output.print("Sent address change command to 0x");
output.print(oldAddr, HEX);
output.print(" -> 0x");
output.println(newAddr, HEX);
}
bool I2CMasterUtils::parseChangeAddressCommand(const String &input, uint8_t &oldAddr, uint8_t &newAddr) {
if (!input.startsWith("ch")) return false;
int o, n;
int matched = sscanf(input.c_str(), "ch %x %x", &o, &n);
if (matched == 2) {
oldAddr = (uint8_t)o;
newAddr = (uint8_t)n;
return true;
}
return false;
}

14
I2CMasterUtils.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef I2CMASTERUTILS_H
#define I2CMASTERUTILS_H
#include <Arduino.h>
#include <Wire.h>
class I2CMasterUtils {
public:
static void scanI2C(Stream &output = Serial);
static void changeSlaveAddress(uint8_t oldAddr, uint8_t newAddr, Stream &output = Serial);
static bool parseChangeAddressCommand(const String &input, uint8_t &oldAddr, uint8_t &newAddr);
};
#endif

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 FABLAB Bahrain
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

20
README.md Normal file
View File

@ -0,0 +1,20 @@
# Relay8I2C Library
**By Fatima @ FABLAB Bahrain**
![FABLAB Bahrain Logo](https://via.placeholder.com/150x50.png?text=FABLAB+Bahrain)
Control 8-relay modules via I2C with dynamic address configuration. Designed for ESP8266 and Arduino platforms.
## Features
- I2C communication protocol
- Dynamic slave address configuration
- Master controller with serial interface
- Active LOW relay support
- EEPROM storage for persistent addressing
## Installation
1. Download the library ZIP
2. Arduino IDE: Sketch > Include Library > Add .ZIP Library
3. Select the downloaded ZIP file
## Usage

View File

@ -0,0 +1,65 @@
#include <Wire.h>
#include <I2CRelay.h>
#include <I2CMasterUtils.h>
RelayI2CMaster relayMaster(0x08); // Default address, can be changed via setAddress()
void setup() {
Serial.begin(115200);
delay(1000);
relayMaster.begin();
Serial.println("Enter:");
Serial.println(" s - to scan I2C bus");
Serial.println(" ch <old> <new> - to change slave address");
Serial.println(" <relay> <on/off> - to set relay (e.g. 3 on)");
}
void loop() {
if (Serial.available()) {
String input = Serial.readStringUntil('\n');
input.trim();
if (input == "s") {
I2CMasterUtils::scanI2C();
} else if (input.startsWith("ch")) {
uint8_t oldAddr, newAddr;
if (I2CMasterUtils::parseChangeAddressCommand(input, oldAddr, newAddr)) {
I2CMasterUtils::changeSlaveAddress(oldAddr, newAddr);
relayMaster.setAddress(newAddr); // Update master's address
Serial.print("Changed address to 0x");
Serial.println(newAddr, HEX);
} else {
Serial.println("Invalid command format. Use: ch <old_addr> <new_addr>");
}
} else {
int spaceIndex = input.indexOf(' ');
if (spaceIndex > 0) {
String relayStr = input.substring(0, spaceIndex);
String stateStr = input.substring(spaceIndex + 1);
int relayNum = relayStr.toInt();
bool state = false;
stateStr.toLowerCase();
if (stateStr == "on") state = true;
else if (stateStr == "off") state = false;
else {
Serial.println("Invalid state! Use 'on' or 'off'.");
return;
}
if (relayNum >= 1 && relayNum <= 8) {
relayMaster.setRelay(relayNum, state);
Serial.print("Relay ");
Serial.print(relayNum);
Serial.print(" turned ");
Serial.println(state ? "ON" : "OFF");
} else {
Serial.println("Invalid relay number! Use 1-8.");
}
} else {
Serial.println("Invalid command! Format: <relay_number> <on/off>");
}
}
}
}

65
examples/Slave/Slave.ino Normal file
View File

@ -0,0 +1,65 @@
#include <Wire.h>
#include <EEPROM.h>
// 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
}

16
keywords.txt Normal file
View File

@ -0,0 +1,16 @@
#######################################
# Syntax coloring for Relay8I2C Library
#######################################
# Classes
RelayI2CMaster KEYWORD1
I2CMasterUtils KEYWORD1
# Methods
begin KEYWORD2
setRelay KEYWORD2
scanI2C KEYWORD2
changeSlaveAddress KEYWORD2
# Constants
CMD_CHANGE_ADDR LITERAL1

9
library.properties Normal file
View File

@ -0,0 +1,9 @@
name=I2CMasterUtils
version=1.0.0
author=Fatima Idrees <fatimaxidrees@gmail.com>
maintainer=Fatima Idrees <fatimaxidrees@gmail.com>
sentence=Control DC motors via I2C with scanning and configuration utilities.
paragraph=Provides easy control of 8-relay modules via I2C communication with dynamic address configuration. Includes master/slave implementation for ESP8266/Arduino platforms.
category=Device Control
url=https://github.com/fablabbh/I2CMasterUtils
architectures=*

6
src/I2CCommands.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef I2C_COMMANDS_H
#define I2C_COMMANDS_H
#define CMD_CHANGE_ADDR 0xAA // Use the same value as in your slave
#endif

36
src/I2CMasterUtils.cpp Normal file
View File

@ -0,0 +1,36 @@
#include "I2CMasterUtils.h"
#include "I2CCommands.h"
void I2CMasterUtils::scanI2C(Stream &output) {
output.println("Scanning for I2C devices...");
for (uint8_t addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) {
output.print("Found device at 0x");
output.println(addr, HEX);
}
}
}
void I2CMasterUtils::changeSlaveAddress(uint8_t oldAddr, uint8_t newAddr, Stream &output) {
Wire.beginTransmission(oldAddr);
Wire.write(CMD_CHANGE_ADDR); // Use the command code from I2CCommands.h
Wire.write(newAddr);
Wire.endTransmission();
output.print("Sent address change command to 0x");
output.print(oldAddr, HEX);
output.print(" -> 0x");
output.println(newAddr, HEX);
}
bool I2CMasterUtils::parseChangeAddressCommand(const String &input, uint8_t &oldAddr, uint8_t &newAddr) {
if (!input.startsWith("ch")) return false;
int o, n;
int matched = sscanf(input.c_str(), "ch %x %x", &o, &n);
if (matched == 2) {
oldAddr = (uint8_t)o;
newAddr = (uint8_t)n;
return true;
}
return false;
}

14
src/I2CMasterUtils.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef I2CMASTERUTILS_H
#define I2CMASTERUTILS_H
#include <Arduino.h>
#include <Wire.h>
class I2CMasterUtils {
public:
static void scanI2C(Stream &output = Serial);
static void changeSlaveAddress(uint8_t oldAddr, uint8_t newAddr, Stream &output = Serial);
static bool parseChangeAddressCommand(const String &input, uint8_t &oldAddr, uint8_t &newAddr);
};
#endif

35
src/I2CRelay.cpp Normal file
View File

@ -0,0 +1,35 @@
#include <Wire.h>
#include <Arduino.h>
#include "I2CRelay.h"
#include "I2CMasterUtils.h"
#include "I2CCommands.h"
RelayI2CMaster::RelayI2CMaster(uint8_t slaveAddress) : _slaveAddress(slaveAddress) {}
void RelayI2CMaster::setAddress(uint8_t newAddress) {
_slaveAddress = newAddress;
}
void RelayI2CMaster::begin() {
Wire.begin();
}
void RelayI2CMaster::setRelay(uint8_t relayIndex, bool state) {
Wire.beginTransmission(_slaveAddress);
Wire.write(relayIndex);
Wire.write(state ? 1 : 0);
Wire.endTransmission();
}
uint8_t RelayI2CMaster::scanDevices(uint8_t* foundAddresses, uint8_t maxDevices) {
uint8_t count = 0;
for(uint8_t addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if(Wire.endTransmission() == 0) {
if(count < maxDevices) {
foundAddresses[count++] = addr;
}
}
}
return count;
}

20
src/I2CRelay.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef RELAY_I2C_MASTER_H
#define RELAY_I2C_MASTER_H
#include <Arduino.h>
#include <Wire.h>
class RelayI2CMaster {
public:
RelayI2CMaster(uint8_t slaveAddress);
void begin();
void setRelay(uint8_t relayIndex, bool state);
uint8_t scanDevices(uint8_t* foundAddresses, uint8_t maxDevices);
void setAddress(uint8_t newAddress);
void handleI2CCommand();
private:
uint8_t _slaveAddress;
};
#endif