Hi,
I need to connect an ESP32 via I2C but can’t find a way to assign it an address to be sent bytes as a slave.
The Micropython docs I found only refer to init the SoftI2C inserting an address to whom send bytes, so the ESP must initiate the transmisison sending the request to it. But if a device wants to send a request to the ESP how does it know its I2C address?
Thanks for helping!
Hi.
I couldn’t find any relevant information regarding setting the ESP32 as an I2C slave using the official micropython firmware. So, unfortunately, I don’t think it is implemented.
However, there are some I2C slave features on other micropython distributions like the loboris distribution: https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/wiki/i2c
I hope this helps.
Regards,
Sara
Thanks Sara,
I didn’t found this. I’m a little scared about uploading this uPython firmware because I didn’t hear about it anywhere.
However it seems the only implementation with this feature. I’ll try a post to Micropython developers to know if it’s indeed so.
If I knew anything I’ll let you know!
Happy Easter!
Enzo
Hi.
That’s a very well-known firmware and supports many functions that are not supported on the official micropython firmware.
Then, let me know if you find anything.
Regards,
Sara
Sara,
this the response from the official MicroPython forum:
“The Loboris port is abandonware. It is based on a long-superseded version of firmware and is effectively unsupported.”
So the only way I can imagine is using the ESP as master, sending an inquiry to the slave (an Arduino Nano in my case) and waiting for its response.
If you have better ideas please let me know.
Thanks and nice regards!
Enzo
Hi.
Alternatively, you can try programming the ESP32 slave using Arduino IDE.
https://github.com/gutierrezps/ESP32_I2C_Slave
Regards,
Sara
Hi Sara,
unfortunately this is a part of a quite large software and develop it in C would be much more time consuming, for this reason I needed a uPython solution. However I’m managing this using ESP32 as a master which inquires the Arduino Nano for (in this case) a keypad scan. The Nano scans the keypad for a pressed key and throws back it or a predefined character after an assigned timeout. This is a workaround for the limited GPIOs number of the ESP32 (the keypad becomes only another I2C device and doesn’t take other GPIOs) and for avoiding a more complex thread structure to get out of the input request when no key is pressed for a given time.
Have a nice day,
Enzo
Hi again.
Unfortunately, there isn’t any uPython solution.
You have to see which workaround works best for your project.
I’m sorry that I can’t help much with this subject.
Regards,
Sara
Hi Sara,
thanks for your time. However I’m now facing another problem,
I could successfully send a string from my ESP32 to Arduino and it received it correctly but I couldn’t send anything from Arduino to ESP32 because I can’t set an address for the ESP!
I tried sending “ABCDE” to all addresses from 8 to 128 but ESP32 only read b’\x00\xff\xff\xff\xff’.
This is my uPython code:
from machine import SoftI2C, Pin
from utime import sleep
ard_I2C_address = 0x0A
bytes_to_read = 1
i2c = SoftI2C(scl=Pin(16), sda=Pin(17), freq=100000)
# dev = i2c.scan()
# print(dev)
def writeToI2C(ard_I2C_address, buf):
num_ACK = i2c.writeto(ard_I2C_address, buf, True)
return num_ACK
def readFromI2C(ard_I2C_address, bytes_to_read):
in_buf = i2c.readfrom(ard_I2C_address, bytes_to_read)
return in_buf
# Main test I2C write
buf = b’12345678901234567890123456789012′
num_ACK = writeToI2C(ard_I2C_address, buf)
print(“num_ACK:”, num_ACK)
# Main test I2C write
in_buf = “”
bytes_to_read = 5
while (1):
in_buf = readFromI2C(ard_I2C_address, bytes_to_read)
sleep(.1)
print(in_buf)
and this is Arduino code:
#include <Wire.h>
String send_buf = “ABCDE”;
void setup()
{
Wire.begin(0x0A);
Wire.onReceive(receiveEvent);
Serial.begin(115200);
}
void loop()
{
for(int x = 8; x < 129; x++)
{
sendPayload(send_buf, x);
delay(1000);
}
}
void receiveEvent(int howMany)
{
Serial.print(howMany);
Serial.print(” bytes available”);
Serial.print(“\n”);
while (Wire.available())
{
char c = Wire.read(); // receive byte as a character
Serial.print(c);
}
Serial.print(“\n”);
// delay(1000);
}
void sendPayload(String send_buf, byte dev)
{
Wire.beginTransmission(dev); // transmit to device ‘dev’
Wire.write(“ABCDE”);
Wire.endTransmission();
}
Where am I wrong? Any hint?
Have a nice day!
Enzo
Hi.
Try to run an I2C scanner sketch on the Arduino (with the ESP32 connected to it).
I found this example: https://gist.github.com/projetsdiy/f4330be62589ab9b3da1a4eacc6b6b1c
It should return the I2C address of I2C connected devices.
Regards,
Sara
I tried an Arduino scan yet but got no answer from the ESP32. Another I2C device (an LCD) in the same bus can be correctly seen: I let it to be sure the bus was ok.
It seems so strange to me that noone had these connection problem to solve. I searched for hours in the Net but didn’t find anything. I can try to implement the high/low levels for the request/answer using the uPython few instructions available but I’m not sure this will work. I’m in big troubles for this.
Nice regards,
Enzo
Hi again, Enzo.
Maybe the ESP32 is not set as an I2C device. Maybe you have to set something on the ESP32 so that it acts as an I2C device…
Unfortunately, I’m not very familiar with this subject… probably because there is little and useful information regarding this subject.
Regards,
Sara
Hi Sara,
I got it! I found the Wire API I was sure had to be there: Wire.onRequest(request handler). That’s just the “symmetrical” to the Wire.onReceive: it’s invoked when a request from the master is issued. A Wire.write(variable) into that sends back the reply to the master. If anyone could be interested this is the example minimal code:
/*********************************
* Wire send and receive example *
*********************************/
#include <Wire.h>
String rec_buf;
String send_buf;
int count = 0;
void setup()
{
Wire.begin(0x0A); // this slave I2C address
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
Serial.begin(115200);
}
void loop()
{
delay(100);
}
void requestEvent(void)
{
send_buf = “Got it! “;
Wire.write(send_buf.c_str());
}
void receiveEvent(int rec_bytes)
{
char rec;
rec_buf = “”;
Serial.print(rec_bytes);
Serial.print(” bytes received\n”);
while(Wire.available())
{
rec = Wire.read();
rec_buf += rec;
}
Serial.print(rec_buf);
Serial.print(“\n”);
}
Nice regards!
Enzo