Go Down

Topic: [Solved] ESP8266 to Nano I2C Problems. (Read 24285 times) previous topic - next topic

Enigma644

Jul 17, 2015, 11:48 pm Last Edit: Jul 19, 2015, 06:09 pm by Enigma644 Reason: Solved: Subject edit.
I'm trying to get I2C working between an Arduino Nano and an ESP8266.
I'm using the ESP8266 Community libs v1.6.4-673-g8cd3697 from https://github.com/esp8266/Arduino

Master[ESP8266]:
Code: [Select]
#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]:
Code: [Select]
#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!

Hackscribble

Hi Enigma644

Quote
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?

Regards

Ray
Hackscribble.  Writing about making things
hackscribble@outlook.com

Enigma644

Yes. It's just the example code that comes with the Arduino IDE. ESP Master, Nano Slave.

File > Examples > Wire : master_reader,master_writer,slave_receiver,slave_sender.


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!

Hackscribble

In the ESP master, you could try setting the wire speed, in case it defaults to higher and this, with the absence of delays, is causing the problem.

Try adding after Wire.begin()

Code: [Select]
Wire.setClock(100000);
Hackscribble.  Writing about making things
hackscribble@outlook.com

Enigma644

#4
Jul 19, 2015, 12:59 am Last Edit: Jul 19, 2015, 05:44 am by Enigma644
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.

Hackscribble

Quote
Slave Nano still receives ok, but the ESP just gets the same junk data returned.
Ah, this wasn't clear from your original post.  So, on the ESP, you see the "Received[" OK but the data that follows is junk? Nothing received?

I would try testing by sending just a byte or two from the Nano to the ESP.

You could also look at the issues page on GitHub for the core in case a similar problem has been reported.

https://github.com/esp8266/Arduino/issues
Hackscribble.  Writing about making things
hackscribble@outlook.com

Enigma644

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]
Code: [Select]
#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]
Code: [Select]
#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);
}

habanero

I'm curious, why would you want to use I2C to connect the ESP8266 to an Arduino over Serial?

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.

habanero

#9
Jul 21, 2015, 05:51 am Last Edit: Jul 21, 2015, 05:54 am by habanero
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?

Enigma644

You can program the ESP8266 just like an Arduino rather than using it as a dumb serial device. See my first post for links to the ESP community libs.

mabbaco

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.

RSABear

This thread helped. The Blink of I2C!

Code: [Select]

void setup()
{
  Serial.begin(115200);
  Wire.begin();//for ESP8266-12E SDA=D4 and SLC=D5
}

Mardetuino

#13
May 08, 2016, 10:58 pm Last Edit: Jan 31, 2017, 06:57 am by mde110
For everybody else who have problems with ESP8266 as I2C master requesting values from Arduino slave.
Set the stretchlimit if ESp is impatient:
Code: [Select]
Wire.setClockStretchLimit(40000);    // in µs

Qdeathstar

For everybody else who have problems with ESP8266 as I2C master requesting values from Arduino slave.
Set the stretchlimit if ESp is impatient:
Code: [Select]
Wire.setClockStretchLimit(1500);    // in µs

HI, i just wanted to post and say that so far, this appears to have solved my problem. THANKS!
A creaking creeping shadow
stiff against the freezing fog
glares at a tickless watch.

Time has failed him -- all things shall pass.

Go Up