Code Monkey home page Code Monkey logo

esp32_i2c_slave's People

Contributors

fstefanni avatar gutierrezps avatar tylerbird avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

esp32_i2c_slave's Issues

"Max attempts" error after a few minutes - Master reader / slave sender

Hi, I have a code with communication between two ESP-WROOM 32U 240MHz / 4MB Flash. During sending first 4-5 times everything is ok, but next I'm getting error "Max attempts" or "Slave not found". Master restart doesn't fix a problem, so I think It must be problem with slave (his restart fix problem).

It's my code: (a little chaotic, because I'm trying different things to repair this error)

Master:

`

 void I2CFun(void * param) {

vTaskDelay(2000);
String message = "";
Serial.println("Wywoluje x.begin();");
x.setClock(10000);
bool status = (x.begin(16, 4));
vTaskDelay(2000);
scanI2C();

for (;;){


	if (!status) {
		Serial.println("Wywoluje x.begin();");
		status = (x.begin(16, 4));
	}
	
	WireSlaveRequest slaveReq(x, 0x04, MAX_SLAVE_RESPONSE_LENGTH);
	slaveReq.setRetryDelay(100);
	slaveReq.setAttempts(255);
	
	bool success = slaveReq.request();
	String temp = "";
	if (success) {
		while (1 < slaveReq.available()) {   // pętla przez wszystkie bajty oprócz ostatniego
			char c = slaveReq.read(); // otrzymaj bajt jako znak
			temp += c;
			              // wypisuje znak
		}
		Serial.println(temp);
		saveData(temp);
		deserializeJson(sensorsData, temp);
	}
	else {
		Serial.println(slaveReq.lastStatusToString());
		Serial.println("Wywoluje x.begin();");
		I2C_ClearBus();
		vTaskDelay(2000);
		status = (x.begin(16, 4));
		vTaskDelay(2000);
	}
	//deserializeJson(sensorsData, message);

	vTaskDelay(1000*60*3);
}

I2CTask = NULL;
vTaskDelete(NULL);
   }

`

and Slave:

`

void I2CMasterFun(void * param) {

unsigned long timeToBeginAgain = millis() + (1000 * 60 * 5);

vTaskDelay(1000);
bool status = (WireSlave.begin(13, 27, 0x04));
vTaskDelay(10);
if (!status) {
	Serial.println("I2C Slave init failed");
	while (1) delay(100);
}
else {
	Serial.println("I2C Slave init OK");
}

WireSlave.onRequest(requestEvent);

for (;;) {
	
	if (millis() >= timeToBeginAgain) {
		I2C_ClearBus();
		status = (WireSlave.begin(13, 27, 0x04));
		WireSlave.onRequest(requestEvent);

		WireSlave.clearWriteError();
		WireSlave.flush();
		Serial.print("PEEK: ");
		Serial.println(WireSlave.peek());
		
		timeToBeginAgain = millis() + (1000 * 60 * 2);
	}
	

	WireSlave.update();
	vTaskDelay(5);
	
}

vTaskDelete(NULL);
     }

`

Memory access violation on high data rates

Thank you for your library.
I used it in a project and stumbled upon an issue on high data rates.
I found two problems in the WireSlaveRequest.cpp where memory is accessed in an array without range checking the index.

I solved the problem by changing the line while (unpacker.available()) in the bool WireSlaveRequest::request(uint8_t address) function to while ((unpacker.available()) && (rxIndex_ < UNPACKER_BUFFER_LENGTH))
and line if (lastStatus_ == PACKET_READ && rxIndex_ < rxLength_) in the int WireSlaveRequest::read() function to if (lastStatus_ == PACKET_READ && rxIndex_ < rxLength_ && (rxIndex_ < UNPACKER_BUFFER_LENGTH))

I will create a pull request with this fix.

slave esp32 not receiving anything in i2c Arduino wire library example

Hi folks,
I am trying to use this library to communicate between two esp32, one as master and one as slave, particularly master needs to write to slave here. I have verified the following items, but still no receive event is detected by the code, and the function that is assigned by "WireSlave.onReceive(receiveEvent);" does not get called at all.
I appreciate any help on this

  1. I checked where the thread travels within the WireSlave.cpp code once the "update" function is called, and the result always goes through the condition of "nothing received" or "inputLen == 0".

  2. I have verified with Saleae logic hardware and probing the i2c signal and it shows that master successfully writes the bytes, and also slave acknowledges the receipt of write setup and each byte of packet.

  3. I used the unpacker in master when sending

  4. This print never shows up, meaning that nothing is detected to be received by the code
    void receiveEvent(int howMany)
    {
    #ifdef debug_prints
    Serial.print(" receiveEvent ");
    #endif
    }
    i2c_screen1

Thread-safe implementation on callback.

I am looking at how the WireSlave.onRequest() method is implemented. The function accepts a callback and I was hoping to pass some context variable to the (say an opaque pointer) callback. As the callback has no argument, the only way to pass a variable to it is through a global variable. It can be done, but this would be bad design practice, particularly in a multi-threaded environment.

There are three ways to fix this:

  1. Pass a void* context pointer to WireSlave.onRequest() . This would however break compatibility with existing code that uses your library.
  2. Create an alternative function that accepts a void* pointer. This would unnecessarily clutter the library.
  3. Replace the low-level calls to i2c_XXX functions and wrap them into reusable functions that WireSlave.update() calls. This may be the best solution leaving the option to implement I/O strategies to the user of your library, but at the same time not losing the simplicity of the current design or the portability of the library. This can be done as inline class functions. Here's a suggested implementation.

`
int readSlaveBuffer( uint8_t *data, size_t max_size, TickType_t ticks_to_wait=1 )
{
return i2c_slave_read_buffer(portNum, data, max_size, ticks_to_wait );
}

int writeSlaveBuffer( const uint8_t *data, size_t size, TickType_t ticks_to_wait=0, bool reset_fifo=true )
{
if( reset_fifo )
i2c_reset_tx_fifo(portNum);
return i2c_slave_write_buffer(portNum, data, size, ticks_to_wait);
}
`

Frequancy State

Hello;

Thanks for the library, it works really well. In one of my projects, I need to communicate with stm32 to ı2c. I think I'm having problems with frequencies. I could not find a frequency arrangement in the library. Which frequency does it use for communication or can they change the frequency?

Send large amount of data?

Thanks for your great library!

I am just curious how to send a large amount of data? Say 3~4k bytes?

Of course, I can split the 3~4k bytes payload into several 128-byte blocks, but not sure how to send the 2nd block..

Using WireSlave.write() function, but it returns 0 if the buffer is full with 128 bytes.

Thanks!

WireSlave.onRequest(requestEvent); never run

TL;DR go to the end of issue

Hello,

Back on my project with raspberry pi as master and esp32 as slave.

In the last months everythings works well and was so great. I doing a break from this part of the project.

Today i back on it and i'm facing a strange behavior with the method WireSlave.onRequest(requestEvent);

When i send i2c request from master with the good data format the WireSlave.onReceive(receiveEvent); get the data but the

WireSlave.onRequest(requestEvent); never run and send nothing to the master....

This is my test sketch on esp32 side directly copied from this repo:

// WireSlave Sender
// by Gutierrez PS <https://github.com/gutierrezps>
// ESP32 I2C slave library: <https://github.com/gutierrezps/ESP32_I2C_Slave>
// based on the example by Nicholas Zambetti <http://www.zambetti.com>

// Demonstrates use of the WireSlave library for ESP32.
// Sends data as an I2C/TWI slave device; data is packed using WirePacker.
// In order to the slave send the data, an empty packet must
// be received first. This is internally done by the WireSlaveRequest class.
// The data is sent using WirePacker, also done internally by WireSlave.
// Refer to the "master_reader" example for use with this

#include <Arduino.h>
#include <Wire.h>
#include <WireSlave.h>

#define SDA_PIN 21
#define SCL_PIN 22
#define I2C_SLAVE_ADDR 0x60

byte reg;
int howManyBytesReceived;

void requestEvent();
void receiveEvent(int howMany);

// function that runs whenever the master sends an empty packet.
// this function is registered as an event, see setup().
// do not perform time-consuming tasks inside this function,
// do them elsewhere and simply read the data you wish to
// send inside here.
void requestEvent()
{
  Serial.println(F("request event --> send to master"));
  WireSlave.write(127);
}

// function that executes whenever a complete and valid packet
// is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
  Serial.println(F("receive event --> receive from master"));
  howManyBytesReceived = howMany;
  Serial.print(howManyBytesReceived);
  Serial.println(F(" bytes"));
  reg = WireSlave.read();
  Serial.println(reg);
}

void setup()
{
  Serial.begin(115200);

  bool res = WireSlave.begin(SDA_PIN, SCL_PIN, I2C_SLAVE_ADDR);
  if (!res)
  {
    Serial.println("I2C slave init failed");
    while (1)
      delay(100);
  }

  WireSlave.onRequest(requestEvent);
  WireSlave.onReceive(receiveEvent);
  Serial.printf("Slave joined I2C bus with addr #%d\n", I2C_SLAVE_ADDR);
}

void loop()
{
  // the slave response time is directly related to how often
  // this update() method is called, so avoid using long delays
  // inside loop(), and be careful with time-consuming tasks
  WireSlave.update();

  // let I2C and other ESP32 peripherals interrupts work
  delay(1);
}
}

this is my raspberry pi side python code (including python classes from https://github.com/MkLHX/Raspberry_Pi_Master_for_ESP32_I2C_SLAVE for more readable i remove Packer, Unpacker and Crc8 classes from snippet:

from time import sleep
from Adafruit_PureIO.smbus import SMBus
from adafruit_extended_bus import ExtendedI2C as I2C

if "__main__" == __name__:

    try:
        i2c = I2C(1)
        scan = i2c.scan()
        print("I2c devices found: ", scan)
        with SMBus(1) as smbus:
            address = scan[0]
            register = [244, 128, 2, 3]
            num_of_bytes = 5
            unpacked = None
            with Packer() as packer:
                packer.debug = True
                packer.write(register[0])
                packer.end()
                packed = packer.read()
                print("packed: ", packed)
            smbus.write_bytes(address, bytearray(packed))
            sleep(0.8)  # let the bus process first write
            raw = smbus.read_bytes(address, num_of_bytes)
            with Unpacker() as unpacker:
                unpacker.debug = True
                unpacker.write(list(raw))
                unpacked = unpacker.read()
            print(unpacked)
    except Exception as e:
        print("ERROR: {}".format(e))

the anwser on esp32 is:

pio device monitor
--- Available filters and text transformations: colorize, debug, default, 
direct, esp32_exception_decoder, hexlify, log2file, nocontrol, printable, 
send_on_enter, time
--- More details at http://bit.ly/pio-monitor-filters
--- Miniterm on COM3  115200,8,N,1 ---
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---     
ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00   
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5828
entry 0x400806a8
�Slave joined I2C bus with addr #96
receive event --> receive from master
1 bytes
244

the answer on raspberry pi:

I2c devices found:  [96]
Data to pack:  244
packed:  [2, 5, 244, 21, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Data to unpack:  [255, 255, 255, 255, 255]
ERROR: ERROR: Unpacker invalid start byte

We can see the device is found 0x60 = 96
the data to pack as waiting esp32 slave is 244 and formated bytearray is good with first, length, data, crc8, last parameters.

But the ESP32 doesn't return anything to the rpi so the unpacked instance crash.

So my question is why WireSlave.onRequest(requestEvent); seems to do nothing when i2c event is triggered?
And how to debug it ASAP? because my project need to be deliver next week and now nothing works.

Don't change anything juste take the code i wrote few months ago and re run it.

I see i used the latest release 0.0.3 seems to fix update blocking but maybe not (in my case)

how can i rollback to the v0.2.0 to test it?

EDIT: i download the archive of v0.2.0, put it in lib/ folder on pio project and my project rollback to works!
i think there is a bug between python raspberry and v0.3.0...

How to set I2C frequency?

Hi, in the Wire library its possible to set the i2c frequency. I couldnt find it in yours, could you help me out?

Not working with ESP32-ArduinoMega I2C Connection

I have been trying to get this library working in ESP32-Arduino Mega communication but no luck. The Arduino is sending few simple chars over I2C while the ESP32 should receive and display the chars but it is not working. I am using 0x04 as an address in both devices and ESP32 is acting as a master.
What could be the issue here?

Guide to transition to the native I2C?

Hi,

I am a long-time user of this library, so first I want to thank you for all your work to have I2C slave work on ESP32 all this time.
I understand that the ESP32-Arduino core has finally fixed the issue with native I2C slave support. I am not very sure how would I transition to it.
The fix isn't included in any release yet, should I wait for the next release? Once I have the latest Arduino core, do I just use the Wire library the same as on an Uno?

Thanks,

Work on python master class

Hello, i'm working on python class to permit Raspberry as i2c Master with ESP32 slave. look #2

I have to convert the parcker and unpacker class into python code and i'm facing about this operation =>

uint8_t crc = crc8.update(buffer_ + 2, payloadLength);

What is the goal of >buffer_ + 2< ? bytearray + 2 🤓

Why using packer and unpacker data workflow? is it the esp-idf layer who need this data format?

ESP32 Wroom 32 as a slave

Hi,

I am trying to set up a network where an ESP32 development board will be the master & there will be 2 ESP32 slaves (dev modules) connected via SDA & SCL.

I uploaded the master_reveiver to the ESP32 dev board & slave_sender to the ESP32 dev module. Somehow, the master is not able to identify slave & keeps printing "slave not found".

Now I tried the same code, I uploaded the master_receiver to one ESP32 dev module & slave_sender to one ESP32 dev module, it worked. Is there any reason as to why the master ESP32 dev kit would not detect the slave?

Set the SLA pin as 23 & SDA as 22. Pull-up resistors connected on both slave boards (I am assuming the main esp32 dev kit doesn't require additional ones?)

Thanks! Any help would be appreciated!

Not working on ESP32 board MH-ET LIVE MINIKIT

Hi there!

I'm trying to use this library on ESP32 has i2c slave with a raspberry pi 3A+ has master.
I'm working on platformio (core: 5.0.1 / Home 3.3.0) framework arduino
here my platformio.ini:

[env:mhetesp32minikit]
platform = espressif32
board = mhetesp32minikit
framework = arduino
monitor_speed = 115200
upload_speed = 921600

[env]
lib_deps =
  # Using a library name
  ArduinoUniqueID
  Board Identify
  Adafruit NeoPixel
  ESP32 I2C Slave

Bus connectivity is ok i can see ESP32 slave address when rpi is scanning. (tested with i2cdetect -y 1 and python I2C() =>scan() method).

But nothing happens when MASTER send i2c orders to the SLAVE.

My code is your examples code mixed.

#include <Arduino.h>
#include <Wire.h>
#include <WireSlave.h>

#define SDA_PIN 21
#define SCL_PIN 22
#define I2C_SLAVE_ADDR 0x14

void receiveEvent(int howMany);
void requestEvent();

void setup()
{
    Serial.begin(115200);

    bool success = WireSlave1.begin(SDA_PIN, SCL_PIN, I2C_SLAVE_ADDR);
    if (!success) {
        Serial.println("I2C slave init failed");
        while(1) delay(100);
    }

    WireSlave1.onReceive(receiveEvent);
    WireSlave1.onRequest(requestEvent);
}

void loop()
{
    // the slave response time is directly related to how often
    // this update() method is called, so avoid using long delays
    // inside loop()
    WireSlave1.update();

    // let I2C and other ESP32 peripherals interrupts work
    delay(1);
}

// function that executes whenever a complete and valid packet
// is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
    while (1 < WireSlave1.available()) // loop through all but the last byte
    {
        char c = WireSlave1.read();  // receive byte as a character
        Serial.print(c);            // print the character
    }

    int x = WireSlave1.read();   // receive byte as an integer
    Serial.println(x);          // print the integer
}

void requestEvent()
{
    static byte y = 0;
    
    WireSlave1.print("y is ");
    WireSlave1.write(y++);
}

My python script:

import time
from adafruit_extended_bus import ExtendedI2C as I2C
from Adafruit_PureIO import smbus

# scan i2c devices
i2c = I2C(bus_id=1)
print(i2c.scan())


address = 0x14
with smbus.SMBus(1) as smbus:
    for i in range(0x00, 0x0A):
        print("register read: %s" % i)
        r = smbus.read_byte_data(address, i)
        print(hex(r))
        time.sleep(.3)

So what can i do to help? i need use esp32 has i2c slave ;-)

Found this library

I have 2 UNO's talking with eachother with I2C. Both are standard in Slave_Receiver. But when one of them has data it will change to Master_Writer, send the 6 bytes data and the turning back to Slave_Receiver. This works great on 2 UNO's. But because I run out of memory on one UNO I exchanged it for an ESP32. And then came the problems. Compared both WIRE libraries and there is indeed some lack of programming. As for now I go testing with the library unless there is another solution for onRequest()/onReceive.

Error trying to send transmit string of 16 characters

Hi Gabriel,
I'm using your library in my BBC Microbit & ESP32 board. I took your advice and have the BBC Microbit signalling a pin on the ESP32 to act as an interrupt. Everything is working well with sending text smaller than 16 characters in length. So my string
"G,192.168.1.170" works fine. However if the string is longer such as "G1,192.168.1.170", then the following error occurs.

**sent: G1,192.168.1.170
assertion "heap != NULL && "free() target pointer is outside heap areas"" failed: file "/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/heap_caps.c", line 267, function: heap_caps_free
abort() was called at PC 0x40103957 on core 1

Backtrace: 0x40093a90:0x3ffdf8c0 0x40093cc1:0x3ffdf8e0 0x40103957:0x3ffdf900 0x4008593f:0x3ffdf930 0x400867a9:0x3ffdf950 0x4000bec7:0x3ffdf970 0x40138b3d:0x3ffdf990 0x4013902e:0x3ffdf9b0 0x400d2ff7:0x3ffdf9d0 0x400d66d9:0x3ffdfa20 0x400d2e3f:0x3ffdfad0 0x4008ff0d:0x3ffdfb00

Rebooting...
ets Jun 8 2016 00:22:57**

Any thoughts on how to resolve this?

Thanks John in York (UK)

Timing of Master reader

Describe the bug
Requesting some bytes from a slave is blocking the main loop for 3..6ms
In the implementation of slaveReq.request() is the delay function used in a while loop:
WireslaveRequest.cpp in Line 32:

// wait until slave fills its output buffer
delay(retryDelay_ * (attempts + 1));

The request is sent and then it stucks for some ms while waiting for the response.
Wouldn't it be possible to get things separated, sending the request, then going back to the main loop, doing a poll in every loop cycle and then read the response if available?

The actual implementation is killing my application which requires a fast CPU cycle.

To Reproduce
Use the sample code for master_reader and slave_sender

Additional context

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.