adding the files ig
This commit is contained in:
commit
939a70aba5
21
LICENSE
Normal file
21
LICENSE
Normal 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
20
README.md
Normal file
@ -0,0 +1,20 @@
|
||||
# Relay8I2C Library
|
||||
**By Fatima @ 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
|
20
examples/Master/Master.ino
Normal file
20
examples/Master/Master.ino
Normal 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
90
examples/Slave/Slave.ino
Normal 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
16
keywords.txt
Normal 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
9
library.properties
Normal 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
6
src/I2CCommands.h
Normal 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
36
src/I2CMasterUtils.cpp
Normal 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
14
src/I2CMasterUtils.h
Normal 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
100
src/I2CStepper.cpp
Normal 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
24
src/I2CStepper.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user