#include <Wire.h>
#define I2CAddressESPWifi 6
int x=32;
void setup()
{
Serial.begin(115200);
Wire.begin(0,2);//Change to Wire.begin() for non ESP.
}
void loop()
{
Wire.beginTransmission(I2CAddressESPWifi);
Wire.write(x);
Wire.endTransmission();
x++;
delay(1);//Required. Not sure why!
Wire.requestFrom(I2CAddressESPWifi,10);
Serial.print("Request Return:[");
while (Wire.available())
{
delay(1);
char c = Wire.read();
Serial.print(c);
}
Serial.println("]");
delay(500);
}
Slave[Nano]:
#include <Wire.h>
#define I2CAddressESPWifi 6
void setup()
{
Serial.begin(115200);
Wire.begin(I2CAddressESPWifi);
Wire.onReceive(espWifiReceiveEvent);
Wire.onRequest(espWifiRequestEvent);
}
void loop()
{
delay(1);
}
void espWifiReceiveEvent(int count)
{
Serial.print("Received[");
while (Wire.available())
{
char c = Wire.read();
Serial.print(c);
}
Serial.println("]");
}
void espWifiRequestEvent()
{
String ts = getTime();
Serial.print("Sending:[");
Serial.print(ts.c_str());
Serial.println("]");
Wire.write(ts.c_str());
}
String getTime(){
int sec = millis() / 1000;
int min = sec / 60;
int hr = min / 60;
String ts = "U:";
if (hr<10) ts+="0";
ts += hr;
ts +=":";
if ((min%60)<10) ts+="0";
ts += min % 60;
ts +=":";
if ((sec%60)<10) ts+="0";
ts += sec % 60;
return(ts);
}
If I use the same code above with an Uno as Master, it works fine!
Wiring wise, I just have straight connections from the ESP GPIOs to the A4/A5 on the Nano. I've tried using 4K7 pull ups, but it doesn't make a difference.
What's strange is if you use the default example code for I2C master/slave it works ok, but as soon as you try and speed things up with faster requests like this, it just doesn't work on the ESP.
Any help on debugging this would be greatly appreciated!
What's strange is if you use the default example code for I2C master/slave it works ok
Just to confirm, using this other code with the same wiring between the devices, you got I2C to work ok with ESP8266 as master and Nano as slave? Can you post that code?
I think it works because there are long delay commands in the example code.
More importantly, the above code works with a Nano Slave, Uno Master, but NOT a Nano Slave, ESP Master!
Wire.setclock didn't work
Tried values from 10 to 10,000,000. Didn't seem to make any difference. Slave Nano still receives ok, but the ESP just gets the same junk data returned.
I think I've figured it out.. It looks like if I do any calculations in the Wire.onRequest() handler that it doesn't have time to create the response and I just get garbage. So now in my master I'm using the first char transmission to trigger building the data response into a global, then waiting before doing Wire.requestFrom and now I'm getting a response back!
Even doing a Serial.print() in the slave Wire.onRequest() interrupt handler seems to be enough to stop it from working!
I'm guessing there must be a bug in the ESP wire lib that's not letting it wait long enough for a response?
Surely I should be able to do some calculations in Wire.onRequest??
There's nothing in the wire interrupt handler docs that says the response needs to be quick.
Working Code:
[Slave_Nano]
#include <Wire.h>
#define I2CAddressESPWifi 6
char response[11] ="0123456789";
void setup()
{
Serial.begin(115200);
Wire.begin(I2CAddressESPWifi);
Wire.onReceive(espWifiReceiveEvent);
Wire.onRequest(espWifiRequestEvent);
}
void loop()
{
delay(1);
}
void espWifiReceiveEvent(int count)
{
Serial.print("Received[");
while (Wire.available())
{
char c = Wire.read();
Serial.print(c);
}
Serial.println("]");
//calc response.
String ts = getTime();
strncpy(response,ts.c_str(),sizeof(response)-1);
}
void espWifiRequestEvent()
{
/*Serial.print("Sending:[");
Serial.print(response);
Serial.println("]");*/
Wire.write(response);
}
String getTime(){
int sec = millis() / 1000;
int min = sec / 60;
int hr = min / 60;
String ts = "U:";
if (hr<10) ts+="0";
ts += hr;
ts +=":";
if ((min%60)<10) ts+="0";
ts += min % 60;
ts +=":";
if ((sec%60)<10) ts+="0";
ts += sec % 60;
return(ts);
}
[Master_ESP]
#include <Wire.h>
#define I2CAddressESPWifi 6
int x=32;
void setup()
{
Serial.begin(115200);
Wire.begin(0,2);//Change to Wire.begin() for non ESP.
}
void loop()
{
Wire.beginTransmission(I2CAddressESPWifi);
Wire.write(x);
Wire.endTransmission();
x++;
delay(1);//Wait for Slave to calculate response.
Wire.requestFrom(I2CAddressESPWifi,10);
Serial.print("Request Return:[");
while (Wire.available())
{
delay(1);
char c = Wire.read();
Serial.print(c);
}
Serial.println("]");
delay(500);
}
I'm only using Serial for debugging. Once live the ESP8266 will be running a web server and reading data from the Arduino; in this case providing a remote display for my 3D printer.
Enigma644:
I'm only using Serial for debugging. Once live the ESP8266 will be running a web server and reading data from the Arduino; in this case providing a remote display for my 3D printer.
No, by "over" I meant instead of serial. I thought that the ESP8266 was meant to work using serial, not I2C. Are you referring to the actual module itself, with all GPIO pins exposed, and not the version that's mounted on a breadboard-friendly breakout board that's meant to work with serial?
Actually this thread is very helpful. I have an ESP01 hooked to a pro mini using the I2c buss. The benefit here is that the arduino can power down the esp to save power. As the arduino, who monitors sensors and the like determines that a status transmission is necessary, it raises the power up pin on the ESP. The ESP then initializes and requests the status info from the arduino (being that the ESP can only be the master) for transmission.
I like the flexibility of creating my own protocols (other than using the AT command set) and leaving the serial for debugging. With two instances of the Arduino IDE open on the desktop, with my logic analyzer hooked to the I2c bus, I can easily modify, upload and debug the code in rapid fashion.
When I have a project that does not need battery life, I favor the ESP12e. This whole environment is a lot of fun.
mde110:
For everybody else who have problems with ESP8266 as I2C master requesting values from Arduino slave.
Set the stretchlimit if ESp is impatient:
Arghh. oh I thought it was in Arduino code - the issue I'm having is an ESP talking I2c to an actual Arduino (well, an Atmega1284). Multiple byte returns failing and crashing the ESP.
Well, the esp can only be Master, and the Arduino has to be the slave... but while adding that line did improve my i2c performance, it didn't solve it. The arduino receives the request and responds, but for some reason the esp8266 doesn't always see it (sometimes it always does, though)..