adding the files ig

This commit is contained in:
fatimaxsen 2025-04-26 12:55:20 +03:00
commit 939a70aba5
11 changed files with 356 additions and 0 deletions

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,20 @@
#include "I2CStepper.h"
I2CStepper stepper(0x55);
void setup() {
stepper.begin();
// Optionally scan for devices
uint8_t found[10];
uint8_t n = stepper.scanDevices(found, 10);
Serial.print("Found "); Serial.print(n); Serial.println(" I2C devices.");
}
void loop() {
stepper.setSpeed(50, 1); // Move at 50% speed, forward
delay(2000);
stepper.setSpeed(50, 0); // Move at 50% speed, backward
delay(2000);
stepper.stop();
delay(1000);
}

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

@ -0,0 +1,90 @@
#include <Wire.h>
#include <EEPROM.h>
// Stepper pin definitions (adjust as needed)
#define DIR_PIN 5
#define STEP_PIN 2
#define EN_PIN 8
#define ADDR_EEPROM_LOC 0
#define EEPROM_SIZE 64
#define CMD_CHANGE_ADDR 0xAA
volatile uint8_t i2c_addr = 0x55; // Default I2C address
// Reads the I2C address from EEPROM, returns default if not set
uint8_t getI2CAddress(uint8_t defaultAddr = 0x55) {
uint8_t addr = EEPROM.read(ADDR_EEPROM_LOC);
if (addr == 0xFF || addr == 0) addr = defaultAddr;
return addr;
}
// Writes new I2C address to EEPROM and restarts the MCU
void setI2CAddress(uint8_t newAddr) {
EEPROM.write(ADDR_EEPROM_LOC, newAddr);
EEPROM.commit();
Serial.print("Address changed to: 0x");
Serial.println(newAddr, HEX);
delay(100);
ESP.restart(); // Use NVIC_SystemReset() for STM32, or asm volatile (" jmp 0"); for AVR
}
// Stepper control function: move a fixed number of steps
void moveSteps(uint16_t steps, uint8_t direction, uint16_t speedDelay) {
digitalWrite(DIR_PIN, direction);
for (uint16_t i = 0; i < steps; i++) {
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(speedDelay);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(speedDelay);
}
}
// I2C receive event handler
void receiveEvent(int howMany) {
if (howMany < 1) return;
uint8_t cmd = Wire.read();
if (cmd == CMD_CHANGE_ADDR) {
if (Wire.available() >= 1) {
uint8_t newAddr = Wire.read();
setI2CAddress(newAddr);
while (Wire.available()) Wire.read(); // Clear buffer
}
return;
}
// If not a command, treat as speed/direction
uint8_t speed = cmd;
if (Wire.available() < 1) return;
uint8_t direction = Wire.read();
// Map speed (0-100) to step delay (us): 100 = fast, 1 = slow
uint16_t speedDelay = map(speed, 1, 100, 2000, 200); // Tune as needed
// Move a fixed number of steps for demonstration
moveSteps(200, direction, speedDelay); // 200 steps = 1 rev for 1.8° stepper
}
void setup() {
pinMode(DIR_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
pinMode(EN_PIN, OUTPUT);
digitalWrite(EN_PIN, LOW); // Enable driver
Serial.begin(115200);
EEPROM.begin(EEPROM_SIZE);
i2c_addr = getI2CAddress(0x55);
Serial.print("Using I2C address: 0x");
Serial.println(i2c_addr, HEX);
Wire.begin(i2c_addr);
Wire.onReceive(receiveEvent);
}
void loop() {
// Nothing needed here
}

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=FABLAB Stepper
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(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
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

100
src/I2CStepper.cpp Normal file
View File

@ -0,0 +1,100 @@
#include "I2CStepper.h"
#include "I2CCommands.h"
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266)
#define IS_ARDUINO
#endif
// Define your stepper pins here for the slave
#define EN_PIN 8
#define DIR_PIN 5
#define STEP_PIN 2
static uint8_t currentAddress = 0x55; // Default address
I2CStepper::I2CStepper(uint8_t address) : _address(address) {}
void I2CStepper::begin() {
Wire.begin(_address);
#ifdef IS_ARDUINO
pinMode(EN_PIN, OUTPUT);
pinMode(DIR_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
digitalWrite(EN_PIN, LOW); // Enable driver
// Register receive handler for slave
Wire.onReceive([this](int numBytes){ this->handleI2CCommand(); });
#endif
}
void I2CStepper::setSpeed(uint8_t speed, uint8_t direction) {
// Send speed/direction to slave
if (_address == 0) return;
if (speed > 100) speed = 100;
direction = (direction == 1) ? 1 : 0;
Wire.beginTransmission(_address);
Wire.write(speed); // 0-100 (percent)
Wire.write(direction); // 0 or 1
Wire.endTransmission();
}
void I2CStepper::stop() {
setSpeed(0, 0);
}
uint8_t I2CStepper::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 (foundAddresses && count < maxDevices) {
foundAddresses[count] = addr;
}
count++;
}
}
return count;
}
void I2CStepper::setAddress(uint8_t newAddress) {
_address = newAddress;
}
// ========== SLAVE: I2C Command Handler ==========
void I2CStepper::handleI2CCommand() {
if (Wire.available() < 1) return;
uint8_t cmd = Wire.read();
if (cmd == CMD_CHANGE_ADDR) {
// Change I2C address
if (Wire.available() >= 1) {
uint8_t newAddr = Wire.read();
currentAddress = newAddr;
Wire.end(); // End current I2C
delay(10);
Wire.begin(currentAddress); // Restart with new address
}
return;
}
// If not a command, treat as speed/direction
uint8_t speed = cmd;
if (Wire.available() < 1) return;
uint8_t direction = Wire.read();
// Map speed (0-100) to step delay (us): 100 = fast, 1 = slow
uint16_t speedDelay = map(speed, 1, 100, 2000, 200); // Tune these values
// Move a fixed number of steps for demonstration (or make this customizable)
moveSteps(200, direction, speedDelay); // 200 steps = 1 rev for 1.8° stepper
}
void I2CStepper::moveSteps(uint16_t steps, uint8_t direction, uint16_t speedDelay) {
digitalWrite(DIR_PIN, direction);
for (uint16_t i = 0; i < steps; i++) {
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(speedDelay);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(speedDelay);
}
}

24
src/I2CStepper.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef I2CStepper_h
#define I2CStepper_h
#include <Arduino.h>
#include <Wire.h>
// ========== I2CStepper Class ==========
class I2CStepper {
public:
I2CStepper(uint8_t address = 0x55);
void begin();
void setSpeed(uint8_t speed, uint8_t direction);
void stop();
uint8_t scanDevices(uint8_t* foundAddresses, uint8_t maxDevices);
void setAddress(uint8_t newAddress);
void handleI2CCommand(); // Only used on the slave
private:
uint8_t _address;
void moveSteps(uint16_t steps, uint8_t direction, uint16_t speedDelay);
};
#endif