Arduino: ESP8266 to ESP8266 i2c

Created on 14 Mar 2017  Â·  10Comments  Â·  Source: esp8266/Arduino

With added support for i2c slave from here by @bjoham, after modifying all files.

Master (ESP8266)

#include <Wire.h>

int x = 3;
void setup() {

  Wire.pins(4,5);
  Wire.begin();               // join i2c bus (address optional for master)
  Wire.beginTransmission(8); // transmit to device #8
  Wire.write(x);              // sends one byte
  Wire.endTransmission();    // stop transmitting
}

void loop() {

} 

Slave (ESP8266)

#include <Wire.h>

int x = 3;


void setup() {
  pinMode(D0,OUTPUT);
  Wire.pins(4,5);
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // register event
  //Serial.begin(9600);           // start serial for output
//  Serial.println("Got something?");
  digitalWrite(D0,LOW);
}

void loop() {
  delay(100);
  if (x == 3) {
    digitalWrite(D0, HIGH);
  }
  //If value received is 3 blink LED for 400 ms
  if (x == 0) {
    digitalWrite(D0, LOW);
  }
}              

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
    x = Wire.read();    // read one character from the I2C'
}

I have connected pins D1,D2,GND on both the boards(NodeMCU).

This doesn't seem to work. Any help will be appreciated.

Most helpful comment

Definitely something broken here the ESP8266 wire examples works with ESP Core 2.5.0 and don't with more recent one.

All 10 comments

It's a long shot but did you make it work ?

same issue. I found on esp8266 stuff commented out.
look at Wire.cpp. All the relevant code is commented out.

https://github.com/esp8266/Arduino/blob/master/libraries/Wire/Wire.cpp

void TwoWire::onReceive( void (*function)(int) ){
  (void)function;
  //user_onReceive = function;
}

void TwoWire::onRequest( void (*function)(void) ){
  (void)function;
  //user_onRequest = function;
}

I tested this with Arduino 1.8.8 and ESP8266 2.5.0 and it works now.

However, I can't get the ESP8266 to work as a slave with other devices such as the Micro:Bit or the Raspberry Pi, but between 2 x ESP8266, it works.

There is an example here by Matej Sychra. Notice that the Master also has to state it's I2C address in the Wire.begin(), which is not standard. I can't get the two ESP8266 to work together without this. Matej writes back from the slave to the master as a master, and not as a slave ... if that makes sense ... but even when I modify the code and writes back to master as a slave, the traditional way, I can't get it to work, unless I state the master's I2C address in the Wire.begin() ... in the master!

So while you can work between two ESP8266 with this version 2.5.0 using I2C, I am not sure that I2C in slave mode has been implemented perfectly in the ESP8266:
On the the Raspberry Pi, when I perform an I2C scan, ie. i2cdetect -y 1, it shows up 80% of the time, which, while seems high, should be and are for other devices, 100%!
And otherwise, I am not able to get any communication going over I2C with the ESP8266 as a slave and any other device as a master.

In January 2017, Bjorn Hammarberg added i2c slave in Wire.cpp which probably was released with this version 2.5.0. In all fairness, I don't actually know if this official means that there's is I2C slave support for the ESP8266. The documentation still only mentions support for master mode.

Good luck!

@gotfredsen slave support is released, but it is still considered experimental, which is why it's not documented.
I suggest opening a new issue, fill out the required info, add a MCVE sketch, and explain your details.

I found this thread when I thought I'd revisit 8266 slave mode. And still no luck getting a esp32 master talking to a 8266 slave - even with 2.5.0 (and the beta's after it). Looking at it with the logic analyser it's clear the 8266 is not sending back the ack from receiving it's address, and who knows why given the structure of the twi code...

It's amazing that nobody has written a library that works as a slave on the 8266 - I think I'll be staying with using nanos for slave for a while yet…

@gotfredsen esp8266 is not working as a slave I assume that onRequest and onReceive functions are not working these are codes

arduino master code:

include //Library for I2C Communication functions

void setup()

{

Serial.begin(9600);                       //Begins Serial Communication at 9600 baud rate
Wire.begin(0x42);                        //Begins I2C communication

}

void loop()
{

Wire.beginTransmission(8);                // start transmit to slave (8)
Wire.write("Hi");                                 // sends 6 bytes value to slave
Wire.endTransmission();                   // stop transmitting


Wire.requestFrom(8,13);                   // request 13 bytes from slave (8)
while (Wire.available())                    // slave may send less than requested
 { 
  char c = Wire.read();                   // receive a byte as character
  Serial.print(c);                               // print the character
 }

Serial.println(); 

delay(500);

}

Esp slave code:

include //Library for I2C Communication functions

void setup()

{

Serial.begin(9600);                           //Begins Serial Communication at 9600 baud rate
Wire.begin(8);                                     //Begins I2C communication with Slave Address as 8
Wire.onReceive(receiveEvent);           //Function call when Slave receives value from master
Wire.onRequest(requestEvent);           //Function call when Master request value from Slave

}

void loop()
{
delay(500);
}

void receiveEvent (int howMany) //This Function is called when Slave receives value from master
{

while (Wire.available()) // slave may send less than requested
{
char c = Wire.read(); // receive a byte as character
Serial.print(c); // print the character
}
Serial.println();

}

void requestEvent() //This Function is called when Master wants value from slave
{
Wire.write("Hello NodeMcu"); // sends 13 bytes value to master
}

can you please help on this

@steminabox @devyte do you have some news/working examples for esp8266 working as i2c slave?
Documentation still not have something about slave mode on esp8266
I use the last esp8266 arduino core 2.6.3, and it's doesn't working esp8266 slave to esp8266 master.

Maybe someone can help?

Definitely something broken here the ESP8266 wire examples works with ESP Core 2.5.0 and don't with more recent one.

This needs fixing. I've wasted half a day trying to get two NodeMCU ESP8266's to communicate with one as slave and one as master. I'm using ESP code version 2.7.1. I'm using the example code straight from the ESP8266 examples in the Arduino IDE. Here's the master:

#include <Wire.h>
#include <PolledTimeout.h>

#define SDA_PIN 4
#define SCL_PIN 5
const int16_t I2C_MASTER = 0x42;
const int16_t I2C_SLAVE = 0x08;

void setup() {
  Wire.begin(SDA_PIN, SCL_PIN, I2C_MASTER); // join i2c bus (address optional for master)
}

byte x = 0;

void loop() {
  using periodic = esp8266::polledTimeout::periodicMs;
  static periodic nextPing(1000);

  if (nextPing) {
    Wire.beginTransmission(I2C_SLAVE); // transmit to device #8
    Wire.write("x is ");        // sends five bytes
    Wire.write(x);              // sends one byte
    Wire.endTransmission();    // stop transmitting

    x++;
  }
}

Here's the slave:

#include <Wire.h>

// D2 on NodeMCU
#define SDA_PIN 4
// D1 on NodeMCU
#define SCL_PIN 5

const int16_t I2C_MASTER = 0x42;
const int16_t I2C_SLAVE = 0x08;

void setup() {
  Serial.begin(115200);           // start serial for output

  for(uint8_t i = 5; i > 0; i--) {
    Serial.printf("count %d\n", i);
    delay(1000);
  }

  Wire.begin(SDA_PIN, SCL_PIN, I2C_SLAVE); // new syntax: join i2c bus (address required for slave)
  Wire.onReceive(receiveEvent); // register event
}

void loop() {
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(size_t howMany) {

  (void) howMany;
  while (1 < Wire.available()) { // loop through all but the last
    char c = Wire.read(); // receive byte as a character
    Serial.print(c);         // print the character
  }
  int x = Wire.read();    // receive byte as an integer
  Serial.println(x);         // print the integer
}

the trouble is that the i2c client on the 8266 - and the esp32 - is fundamentally (ie not the ardunio library) not usable. They have only meant it to be a dumb sensor ie put a value in the i2c buffer, the master will get it at some point, and you won't even know when.

So there is no point trying to do what you are doing above, it simply won't work, period.

Yes, it's its sad that they didn't do i2c client properly for the 8266/esp32 - it's one of the few failings of the chip.

I was looking at the esp-s2 the other day, and it might be a little bit better as it looks like you can access some of the underlying events - so you might be able to do a hack that makes it work a bit as a client.. maybe, as I haven't tried yet.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hoacvxd picture hoacvxd  Â·  3Comments

gosewski picture gosewski  Â·  3Comments

eliabieri picture eliabieri  Â·  3Comments

treii28 picture treii28  Â·  3Comments

markusschweitzer picture markusschweitzer  Â·  3Comments