NodeMCU - Master and UNO - Slaves (I2C communication)

Hi all,

I have a NodeMCU as a master and two Arduino UNO's as slaves connected via I2C. The slaves collecting data from sensors and sending it to Master and displaying it in Serial Monitor. However I can receive data from 1 slave but not the other. Below is a simple code of 2 slaves connected to a master for better understanding. Please help me out and suggest where I am doing wrong.

Thanks in advance.

Master Code

#include <Wire.h>

void setup() {
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
}

void loop() {
  Wire.requestFrom(8, 6);    // request 6 bytes from slave device #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
  }


  Wire.requestFrom(9, 7);    // request 6 bytes from slave device #8

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


  delay(500);
}

Slave 1 Code

#include <Wire.h>

void setup() {
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onRequest(requestEvent); // register event
}

void loop() {
  delay(100);
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
  Wire.write("hello "); // respond with message of 6 bytes
  // as expected by master
}

Slave 2 Code


#include <Wire.h>

void setup() {
  Wire.begin(9);                // join i2c bus with address #9
  Wire.onRequest(requestEvent); // register event
}

void loop() {
  delay(100);
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
  Wire.write("world! "); // respond with message of 6 bytes
  // as expected by master
}

I2C-communication is blocking. I'm not familiar with the low-level-details of the I2C-Bus.
My guessing is If the number of bytes does not fit to the request this makes the I2C-bus hang.
Though it seems you are using the right numbers.

nodeMCU means an ESP8266-nodeMCU?

If your master is not using anything else you could simply define two softwareserial interfaces.

What is the maximum datalength in bytes that you want to transfer in your final application?

What is the required frequency that you send data from the slaves to the master?

What sensors are connected to the slaves? I mean what interface do the sensors have to communicate with the slave?

best regards Stefan

1. There is no hardware I2C Interface inside NodeMCU like the UNO. Therefore, you have to emulate the I2C Interface within NodeMCU by including the following code in setup() function. And connect NdeMCU and UNO-1 and UNO-2 as per diagram of Fig-1.

Wire.begin(D4, D3);   //D4 (GPIO-2) -= SDA, D3 (GPI-0) = SCL ; you can use other GPIO pins


Figure-1:

2. Upload the followinh test sketches in NodeMCU, UNO-1/SLve-1, and UNO-2/Slave-2.

NodeMCU Sketch:

#include <Wire.h>

void setup()
{
  Wire.begin(D4, D3); //SDA=D4, SCL=D3
  Serial.begin(9600);  // start serial for output
}

void loop()
{
  Wire.requestFrom(8, 1);    // request 6 bytes from slave device #8
  byte x = Wire.read();
  Serial.print("Reading 1-byte from SLve-1: ");
  Serial.println(x, HEX);
  //-----------------------
  Wire.requestFrom(9, 1);    // request  bytes from slave device #8
  byte y = Wire.read();
  Serial.print("Reading 1-byte from Slave-2: ");
  Serial.println(y, HEX);
  //------------------------
  delay(1000);
}

UNO-1/Slave-1 Sketch:

#include<Wire.h>

void setup()
{
  Serial.begin(9600);
  Wire.begin(8);  ////UNO-Slave Address
  Wire.onRequest(sendEvent);
}

void loop()
{  

}

void sendEvent()
{
  Wire.write(0x13);
}

UNO-2/Slave-2 Sketch:

#include<Wire.h>

void setup()
{
  Serial.begin(9600);
  Wire.begin(9);  ////UNO-Slave Address
  Wire.onRequest(sendEvent);
}

void loop()
{

}

void sendEvent()
{
  Wire.write(0x27);
}

3. Check that Serial Monitor of NodeMCU shows the following message that describes that NodeMCU is corretly acquiring data from bothe slaves.

Reading 1-byte from Slave-2: 27
Reading 1-byte from SLve-1: 13
Reading 1-byte from Slave-2: 27
Reading 1-byte from SLve-1: 13
Reading 1-byte from Slave-2: 27
Reading 1-byte from SLve-1: 13
Reading 1-byte from Slave-2: 27
Reading 1-byte from SLve-1: 13
Reading 1-byte from Slave-2: 27
Reading 1-byte from SLve-1: 13
Reading 1-byte from Slave-2: 27
Reading 1-byte from SLve-1: 13
Reading 1-byte from Slave-2: 27

4. Now, correct/modify your sketches of Post-1 in the light of the sketces of this post.

Hi,

Thanks for the suggestion. I was trying to execute your example but getting the output on the master serial monitor as follows. Could you please tell me what went wrong?

Master - NodeMCU

#include <Wire.h>

void setup()
{
  Wire.begin(D4, D3); //SDA=D4, SCL=D3
  Serial.begin(9600);  // start serial for output
}

void loop()
{
  Wire.requestFrom(8, 1);    // request 6 bytes from slave device #8
  char c = Wire.read();
  Serial.print("Reading 6-bytes from Slave-1: ");
  Serial.println(c, HEX);
  //-----------------------
  Wire.requestFrom(9, 1);    // request  bytes from slave device #8
  char d = Wire.read();
  Serial.print("Reading 7-bytes from Slave-2: ");
  Serial.println(d, HEX);
  //------------------------
  delay(1000);
}

Slave 1

#include<Wire.h>

void setup()
{
  Serial.begin(9600);
  Wire.begin(8);  ////UNO-Slave Address
  Wire.onRequest(sendEvent);
}

void loop()
{  

}

void sendEvent()
{
  Wire.write(0x13);
}

Slave 2

#include<Wire.h>

void setup()
{
  Serial.begin(9600);
  Wire.begin(9);  ////UNO-Slave Address
  Wire.onRequest(sendEvent);
}

void loop()
{

}

void sendEvent()
{
  Wire.write(0x27);
}

Master - Serial Monitor

9:15:53.418 -> Reading 6-bytes from Slave-1: 13
19:15:53.418 -> Reading 7-bytes from Slave-2: FF
19:15:54.397 -> Reading 6-bytes from Slave-1: 13
19:15:54.443 -> Reading 7-bytes from Slave-2: FF
19:15:55.421 -> Reading 6-bytes from Slave-1: 13
19:15:55.421 -> Reading 7-bytes from Slave-2: FF
19:15:56.400 -> Reading 6-bytes from Slave-1: 13
19:15:56.447 -> Reading 7-bytes from Slave-2: FF
19:15:57.426 -> Reading 6-bytes from Slave-1: 13
19:15:57.426 -> Reading 7-bytes from Slave-2: FF
19:15:58.397 -> Reading 6-bytes from Slave-1: 13
19:15:58.444 -> Reading 7-bytes from Slave-2: FF
19:15:59.418 -> Reading 6-bytes from Slave-1: 13
19:15:59.465 -> Reading 7-bytes from Slave-2: FF
19:16:00.395 -> Reading 6-bytes from Slave-1: 13
19:16:00.441 -> Reading 7-bytes from Slave-2: FF
19:16:01.413 -> Reading 6-bytes from Slave-1: 13
19:16:01.459 -> Reading 7-bytes from Slave-2: FF
19:16:02.435 -> Reading 6-bytes from Slave-1: 13


It would appear that your second Uno is not properly connected to the bus since it is not responding. Wire.requestFrom() returns a status value. You should capture it and send it to the Serial Monitor.

You could also run the i2cScanner sketch to see what is detected on the bus.
Have you tried removing the working Uno and only have the other Uno connected?

@kpuvvala
1. Make connection between NodeMCU and UNO-2 only as per Fig-1 of Post-3. Do not forget to install the I2C Bus pull-up resistors.

2. Upload the following sketch in NodeMCU.

#include <Wire.h>

void setup()
{
  Wire.begin(D4, D3); //SDA=D4, SCL=D3
  Serial.begin(9600);  // start serial for output
  //----------------------------------------------------------------
  Wire.beginTransmission(9);
  byte busStatus = Wire.endTransmission();
  if(buStatus !=0)
  {
      Serial.print("UNO-2 is not found on I2C Bus.");
      while(1);   //wait for ever
   }
   Serial.println("UNO-2 is found on I2C Bus.");
}

void loop()
{
  Wire.requestFrom(9, 1);    // request  bytes from slave device #8
  byte y = Wire.read();
  Serial.print("Reading 1-byte from Slave-2: ");
  Serial.println(y, HEX);
  //------------------------
  delay(1000);
}

3. Upload the following sketch in UNO-2.

#include<Wire.h>

void setup()
{
  Serial.begin(9600);
  Wire.begin(9);  ////UNO-2/Slave-2 Address
  Wire.onRequest(sendEvent);
}

void loop()
{

}

void sendEvent()
{
  Wire.write(0x27);
}

4. Check that the Serial Monitor of NodeMCU shows: 27 at 1-sec interval.
5. Now Connect UNO-1/Slave-1 and check that both slaves are operational.

Yes I have tried the method you suggested. I could only connect either one slave and get the data transmitted to master. If I connect both, that's where I'm getting the error. I could only receive the one slave's data.

I have also made sure the connections are fine.

Do you have any other Arduino like NANO, UNO, or MEGA? If yes, then use one of them as Master in place of NodemCU and check that both slaves are working.

HI GolamMostafa,

Thank you very much for your help. I actually made that to work. However, I am trying to integrate my actual code to this example, but on the master's serial monitor I'm receiving values as "0". I can see all the sensor values on slave serial monitors but not on the master.

My actual plan was to connect three i2c sensors to each slave-UNO and receive the data on Master-NodeMCU(ESP8266) and then send them over to Googlesheets via firebase. Please help me out on this one.

Master - NodeMCU



//--------------------------------firebase-----------------
#include <FirebaseESP8266.h>
#include <esp8266wifi.h>//<ESP8266WiFi.h>
#include "FirebaseESP8266.h"  // Install Firebase ESP8266 library

#define FIREBASE_HOST "***********************************"                     //Your Firebase Project URL goes here without "http:" , "\" and "/"
#define FIREBASE_AUTH "******************" //Your Firebase Database Secret goes here

#define WIFI_SSID "************"
#define WIFI_PASSWORD "*************"
FirebaseData firebaseData;

//--------------------------------reset nodemcu------------------------------
int cnt = 3600;


#include <Wire.h>


float co2ppm1 = 0;
float co2temp1 = 0;
float co2hum1 = 0;
float pressure1 = 0;
float loadvoltage1 = 0;
float current1 = 0;

float co2ppm2 = 0;
float co2temp2 = 0;
float co2hum2 = 0;
float pressure2 = 0;
float loadvoltage2 = 0;
float current2 = 0;


void setup()
{

  //***********************************************************************
  Wire.begin(D4, D3); //SDA=D4, SCL=D3
  Serial.begin(115200);  // start serial for output

  //**************************************************************************************

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(300);
  }
  Serial.println();
  Serial.print("Connected with IP: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
  Firebase.reconnectWiFi(true);

  //**************************************************************************************
  Wire.beginTransmission(2);
  byte busStatus = Wire.endTransmission();
  if (busStatus != 0)
  {
    Serial.print("UNO-1 is not found on I2C Bus.");
    while (1);  //wait for ever
  }
  Serial.println("UNO-1 is found on I2C Bus.");

  //**********************************************************************************
  Wire.beginTransmission(8);
  //  byte busStatus = Wire.endTransmission();
  if (busStatus != 0)
  {
    Serial.print("UNO-2 is not found on I2C Bus.");
    while (1);  //wait for ever
  }
  Serial.println("UNO-2 is found on I2C Bus.");
  //**********************************************************************************

  //**********************************************************************************

}

//*************************************************************************************
void loop()
{

  Serial.println(cnt);

  if (cnt == 0) {
    Serial.println("Reset..");
    ESP.restart();
  }

  cnt--;
  delay(1000);
  //***************************************************************************************************


  //***************************************************************************************************

  Wire.requestFrom(2, 40);    // request 37 bytes from slave device #1
  String reactor1, co2ppm1s, co2temp1s, co2hum1s, pressure1s, loadvoltage1s, current1s;
  do   // slave may send less than requested
  {
    char c = Wire.read(); // receive a byte as character

    reactor1 = reactor1 + c; //Keep saving whatever is comming

    co2ppm1s = reactor1.substring(0, 5); //slpit String from 0 to 4
    co2temp1s = reactor1.substring(6, 13); // Split from 5 to 11
    co2hum1s = reactor1. substring(14, 21); // Split from 12 to 19
    pressure1s = reactor1.substring(22, 27); // Split from 20 to 25
    loadvoltage1s = reactor1.substring(28, 33); // Split from 26 to 31
    current1s = reactor1.substring(34, 39); // Split from 32 to 37


  } while (Wire.available());
  Serial.print("Recieving float as String...");
  Serial.println();
  Serial.println();
  Serial.print("Reactor 1 Sensors: ");
  Serial.print(reactor1);

  Serial.println();
  Serial.print("CO2 PPM 1: ");
  Serial.print(co2ppm1s);
  Serial.println();
  Serial.println();

  Serial.print("CO2 TEMP 1: ");
  Serial.print(co2temp1s);
  Serial.println();
  Serial.println();

  Serial.print("CO2 HUM 1: ");
  Serial.print(co2hum1s);
  Serial.println();
  Serial.println();

  Serial.print("Pressure 1: ");
  Serial.print(pressure1s);
  Serial.println();
  Serial.println();

  Serial.print("Load Voltage 1: ");
  Serial.print(loadvoltage1s);
  Serial.println();
  Serial.println();

  Serial.print("Current 1: ");
  Serial.print(current1s);
  Serial.println();
  Serial.println();

  //***************************************************************************************************

  Serial.print("Converting string to float...");
  Serial.println();
  Serial.println();
  co2ppm1 = co2ppm1s.toFloat();
  Serial.print("CO2 PPM 1: ");
  Serial.print(co2ppm1);
  Serial.println();

  co2temp1 = co2temp1s.toFloat();
  Serial.print("CO2 TEMP 1: ");
  Serial.print(co2temp1);
  Serial.println();

  co2hum1 = co2hum1s.toFloat();
  Serial.print("CO2 HUM 1: ");
  Serial.print(co2hum1);
  Serial.println();

  pressure1 = pressure1s.toFloat();
  Serial.print("Pressure 1: ");
  Serial.print(pressure1);
  Serial.println();

  loadvoltage1 = loadvoltage1s.toFloat();
  Serial.print("Load Voltage 1: ");
  Serial.print(loadvoltage1);
  Serial.println();

  current1 = current1s.toFloat();
  Serial.print("Current 1: ");
  Serial.print(current1);
  Serial.println();

  delay(1000);

  //-----------------------------------------firebase-----------------------------------------------

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);   // connect to firebase
  Firebase.reconnectWiFi(true);



  /////////////Variable One - CO2 Sensor//////////////


  if (Firebase.setFloat(firebaseData, "Reactors/Array/Data1/Co2 PPM R1", co2ppm1)) {    // On successful Write operation, function returns 1
    Serial.println("Value Uploaded Successfully");
    Serial.print("Co2 = ");
    Serial.println(co2ppm1);
    Serial.println("\n");

    //val++;

    //  delay(4000);
  }

  else {
    Serial.println(firebaseData.errorReason());
  }


  ///////////////Variable Two - Co2 Humidity Sensor//////////////

  if (Firebase.setFloat(firebaseData, "Reactors/Array/Data1/Co2Hum R1", co2hum1)) {    // On successful Write operation, function returns 1
    Serial.println("Value Uploaded Successfully");
    Serial.print("Co2 humidity = ");
    Serial.println(co2hum1);
    Serial.println("\n");

    //val++;


  }

  else {
    Serial.println(firebaseData.errorReason());
  }


  ///////////////Variable Three - Co2 Temperature Sensor//////////////

  if (Firebase.setFloat(firebaseData, "Reactors/Array/Data1/Co2 Temp R1", co2temp1)) {    // On successful Write operation, function returns 1
    Serial.println("Value Uploaded Successfully");
    Serial.print("Co2 temp = ");
    Serial.println(co2temp1);
    Serial.println("\n");

    //val++;
    //  delay(4000);

  }

  else {
    Serial.println(firebaseData.errorReason());
  }


  ///////////////Variable Four - BMP280 Sensor//////////////

  if (Firebase.setFloat(firebaseData, "Reactors/Array/Data1/Pressure R1", pressure1)) {    // On successful Write operation, function returns 1
    Serial.println("Value Uploaded Successfully");
    Serial.print("hPa = ");
    Serial.println(pressure1);
    Serial.println("\n");

    //val++;

    //  delay(4000);
  }

  else {
    Serial.println(firebaseData.errorReason());
  }


  ///////////////Variable Five - INA219 loadvoltage//////////////

  if (Firebase.setFloat(firebaseData, "Reactors/Array/Data1/INA219 Load Voltage R1", loadvoltage1)) {    // On successful Write operation, function returns 1
    Serial.println("Value Uploaded Successfully");
    Serial.print("INA219 Load Voltage = ");
    Serial.println(loadvoltage1);
    Serial.println("\n");

    //val++;

    //  delay(4000);
  }

  else {
    Serial.println(firebaseData.errorReason());
  }


  ///////////////Variable Seven - INA219 Current//////////////

  if (Firebase.setFloat(firebaseData, "Reactors/Array/Data1/INA219 Current R1", current1)) {    // On successful Write operation, function returns 1
    Serial.println("Value Uploaded Successfully");
    Serial.print("INA219 Current = ");
    Serial.println(current1);
    Serial.println("\n");

    //val++;

    //  delay(4000);
  }

  else {
    Serial.println(firebaseData.errorReason());
  }


  //**********************************************************************************************

  Wire.requestFrom(8, 40);    // request 37 bytes from slave device #1
  String reactor2, co2ppm2s, co2temp2s, co2hum2s, pressure2s, loadvoltage2s, current2s;
  do   // slave may send less than requested
  {
    char d = Wire.read(); // receive a byte as character

    reactor2 = reactor2 + d; //Keep saving whatever is comming

    co2ppm2s = reactor2.substring(0, 5); //slpit String from 0 to 4
    co2temp2s = reactor2.substring(6, 13); // Split from 5 to 11
    co2hum2s = reactor2. substring(14, 21); // Split from 12 to 19
    pressure2s = reactor2.substring(22, 27); // Split from 20 to 25
    loadvoltage2s = reactor2.substring(28, 33); // Split from 26 to 31
    current2s = reactor2.substring(34, 39); // Split from 32 to 37


  } while (Wire.available());
  Serial.print("Recieving float as String...");
  Serial.println();
  Serial.println();
  Serial.print("Reactor 2 Sensors: ");
  Serial.print(reactor2);

  Serial.println();
  Serial.print("CO2 PPM 2: ");
  Serial.print(co2ppm2s);
  Serial.println();
  Serial.println();

  Serial.print("CO2 TEMP 2: ");
  Serial.print(co2temp2s);
  Serial.println();
  Serial.println();

  Serial.print("CO2 HUM 2: ");
  Serial.print(co2hum2s);
  Serial.println();
  Serial.println();

  Serial.print("Pressure 2: ");
  Serial.print(pressure2s);
  Serial.println();
  Serial.println();

  Serial.print("Load Voltage 2: ");
  Serial.print(loadvoltage2s);
  Serial.println();
  Serial.println();

  Serial.print("Current 2: ");
  Serial.print(current2s);
  Serial.println();
  Serial.println();

  //***************************************************************************************************

  Serial.print("Converting string to float...");
  Serial.println();
  Serial.println();
  co2ppm2 = co2ppm2s.toFloat();
  Serial.print("CO2 PPM 2: ");
  Serial.print(co2ppm2);
  Serial.println();

  co2temp2 = co2temp2s.toFloat();
  Serial.print("CO2 TEMP 2: ");
  Serial.print(co2temp2);
  Serial.println();

  co2hum2 = co2hum2s.toFloat();
  Serial.print("CO2 HUM 2: ");
  Serial.print(co2hum2);
  Serial.println();

  pressure2 = pressure2s.toFloat();
  Serial.print("Pressure 2: ");
  Serial.print(pressure2);
  Serial.println();

  loadvoltage2 = loadvoltage2s.toFloat();
  Serial.print("Load Voltage 2: ");
  Serial.print(loadvoltage2);
  Serial.println();

  current2 = current2s.toFloat();
  Serial.print("Current 2: ");
  Serial.print(current2);
  Serial.println();

  delay(1000);
  //-----------------------------------------firebase-----------------------------------------------

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);   // connect to firebase
  Firebase.reconnectWiFi(true);



  /////////////Variable Seven - CO2 Sensor//////////////


  if (Firebase.setFloat(firebaseData, "Reactors/Array/Data1/Co2 PPM R2", co2ppm2)) {    // On successful Write operation, function returns 1
    Serial.println("Value Uploaded Successfully");
    Serial.print("Co2 = ");
    Serial.println(co2ppm2);
    Serial.println("\n");

    //val++;

    //  delay(4000);
  }

  else {
    Serial.println(firebaseData.errorReason());
  }


  ///////////////Variable Eight - Co2 Humidity Sensor//////////////

  if (Firebase.setFloat(firebaseData, "Reactors/Array/Data1/Co2Hum R2", co2hum2)) {    // On successful Write operation, function returns 1
    Serial.println("Value Uploaded Successfully");
    Serial.print("Co2 humidity = ");
    Serial.println(co2hum2);
    Serial.println("\n");

    //val++;


  }

  else {
    Serial.println(firebaseData.errorReason());
  }


  ///////////////Variable Nine - Co2 Temperature Sensor//////////////

  if (Firebase.setFloat(firebaseData, "Reactors/Array/Data1/Co2 Temp R2", co2temp2)) {    // On successful Write operation, function returns 1
    Serial.println("Value Uploaded Successfully");
    Serial.print("Co2 temp = ");
    Serial.println(co2temp2);
    Serial.println("\n");

    //val++;
    //  delay(4000);

  }

  else {
    Serial.println(firebaseData.errorReason());
  }


  ///////////////Variable Ten - BMP280 Sensor//////////////

  if (Firebase.setFloat(firebaseData, "Reactors/Array/Data1/Pressure R2", pressure2)) {    // On successful Write operation, function returns 1
    Serial.println("Value Uploaded Successfully");
    Serial.print("hPa = ");
    Serial.println(pressure2);
    Serial.println("\n");

    //val++;

    //  delay(4000);
  }

  else {
    Serial.println(firebaseData.errorReason());
  }


  ///////////////Variable Eleven - INA219 loadvoltage//////////////

  if (Firebase.setFloat(firebaseData, "Reactors/Array/Data1/INA219 Load Voltage R2", loadvoltage2)) {    // On successful Write operation, function returns 1
    Serial.println("Value Uploaded Successfully");
    Serial.print("INA219 Load Voltage = ");
    Serial.println(loadvoltage2);
    Serial.println("\n");

    //val++;

    //  delay(4000);
  }

  else {
    Serial.println(firebaseData.errorReason());
  }


  ///////////////Variable Twelve - INA219 Current//////////////

  if (Firebase.setFloat(firebaseData, "Reactors/Array/Data1/INA219 Current R2", current2)) {    // On successful Write operation, function returns 1
    Serial.println("Value Uploaded Successfully");
    Serial.print("INA219 Current = ");
    Serial.println(current2);
    Serial.println("\n");

    //val++;

    //  delay(4000);
  }

  else {
    Serial.println(firebaseData.errorReason());
  }



  //***************************************************************************************************

  //------------------------


  delay(1000);
}

Slave -1(UNO)


#include<Wire.h>
#include <avr/wdt.h>



//**************************************************** SCD30 **************************************************

#include "SparkFun_SCD30_Arduino_Library.h" //Click here to get the library: http://librarymanager/All#SparkFun_SCD30
SCD30 airSensor;

//************************************** BMP280 ***************************************

#include <Adafruit_BMP280.h>
Adafruit_BMP280 bmp; // use I2C interface
Adafruit_Sensor *bmp_temp = bmp.getTemperatureSensor();
Adafruit_Sensor *bmp_pressure = bmp.getPressureSensor();
float array3[1];

//********************************** INA219 ********************************************

#include <Adafruit_INA219.h>
Adafruit_INA219 ina219;
float shuntvoltage = 0;
float busvoltage = 0;

float power_mW = 0;

float array1[3];

//******************************************************************************************

float co21 = 0;
float co2hum1 = 0;
float co2temp1 = 0;
float pressure1 = 0;
float loadvoltage1 = 0;
float current1 = 0;

char co21s[4];
char co2temp1s[8];
char co2hum1s[7];
char pressure1s[6];
char loadvoltage1s[6];
char current1s[6];


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

   for (int i = 5; i > 0; i--) {
    Serial.print(i);
    delay(1000); // I sometimes need a few seconds to restart the serial console.
    wdt_enable(WDTO_4S);
  }

  
  Wire.begin(2);  ////UNO-1/Slave-1 Address
  Wire.onRequest(sendEvent);

  SensorInit(); // Initialize the displays

}

void SensorInit() {

  Serial.println("SCD30 Example");
  Wire.begin();


  if (airSensor.begin() == false)
  {
    Serial.println("Air sensor not detected. Please check wiring. Freezing...");
    while (1)
      ;
  }

  //************************************************************************************

  ina219.begin();
  ina219.setCalibration_16V_400mA(); // set measurement range to 16V, 400mA

  //************************************************************************************

  Serial.println(F("BMP280 Sensor event test"));

  if (!bmp.begin(0x76)) {
    Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
    delay(10);
  }


  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
                  Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
                  Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
                  Adafruit_BMP280::FILTER_X16,      /* Filtering. */
                  Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */

  bmp_temp->printSensorDetails();

}


void loop()
{

  if (airSensor.dataAvailable())
  {
    Serial.print("co21(ppm):");
    Serial.print(airSensor.getCO2());
    co21 = airSensor.getCO2();


    Serial.print(" temp1(C):");
    Serial.print(airSensor.getTemperature(), 1);
    co2temp1 = airSensor.getTemperature();


    Serial.print(" humidity1(%):");
    Serial.print(airSensor.getHumidity(), 1);
    co2hum1 = airSensor.getHumidity();
    Serial.println();
    Serial.println();

    Serial.println();
    Serial.print(" Pre-stream data");
    Serial.println();
    Serial.print(co21);
    Serial.println();
    Serial.print(co2temp1);
    Serial.println();
    Serial.print(co2hum1);
    Serial.println();

  }

  //****************************************************************************************


  shuntvoltage = ina219.getShuntVoltage_mV();
  busvoltage = ina219.getBusVoltage_V();
  current1 = ina219.getCurrent_mA();
  power_mW = ina219.getPower_mW();
  loadvoltage1 = busvoltage + (shuntvoltage / 1000);

  Serial.println();
  Serial.println();
  Serial.print("Load Voltage 1:  "); Serial.print(loadvoltage1); Serial.println(" V");
  Serial.print("Current 1:       "); Serial.print(current1); Serial.println(" mA");
  Serial.println("");
  Serial.println();
  Serial.println();
  array1[0] = busvoltage;
  array1[1] = shuntvoltage;
  array1[2] = loadvoltage1;
  array1[3] = current1;

  //***************************************************************************************

  sensors_event_t temp_event, pressure_event;
  bmp_temp->getEvent(&temp_event);
  bmp_pressure->getEvent(&pressure_event);

  Serial.println();
  Serial.println();
  Serial.print(F("Temperature = "));
  Serial.print(temp_event.temperature);
  Serial.println(" *C");
  //
  Serial.println();
  Serial.print(F("Pressure = "));
  Serial.print(pressure_event.pressure);
  Serial.println(" hPa");
  //float pressure_pascal=pressure_event.pressure/1000 - 0.90883;
  Serial.println();

  array3[1] = temp_event.temperature;
  delay(1000);

  delay(500);
  wdt_reset();
}

void sendEvent()
{

  //Converting float value to char
  //The format (float, bytes, numbers of numbers after the decimal, char variable)
  dtostrf(co21, 4, 1, co21s);
  Wire.write(co21s); // appx 8 bytes
  Wire.write(",");

  dtostrf(co2temp1, 8, 4, co2temp1s);
  Wire.write(co2temp1s); // appx 8 bytes
  Wire.write(",");

  dtostrf(co2hum1, 7, 4, co2hum1s);
  Wire.write(co2hum1s); // appx 8
  Wire.write(",");

  dtostrf(pressure1, 6, 2, pressure1s);
  Wire.write(pressure1s); // appx 8
  Wire.write(",");

  dtostrf(loadvoltage1, 6, 4, loadvoltage1s);
  Wire.write(loadvoltage1s); // appx 8
  Wire.write(",");

  dtostrf(current1, 6, 4, current1s);
  Wire.write(current1s); // appx 8


  Wire.write("\n");

delay(1000);

}

Slave-2(UNO)


#include<Wire.h>
#include <avr/wdt.h>


//**************************************************** SCD30 **************************************************

#include "SparkFun_SCD30_Arduino_Library.h" //Click here to get the library: http://librarymanager/All#SparkFun_SCD30
SCD30 airSensor;

//************************************** BMP280 ***************************************

#include <Adafruit_BMP280.h>
Adafruit_BMP280 bmp; // use I2C interface
Adafruit_Sensor *bmp_temp = bmp.getTemperatureSensor();
Adafruit_Sensor *bmp_pressure = bmp.getPressureSensor();
float array3[1];

//********************************** INA219 ********************************************

#include <Adafruit_INA219.h>
Adafruit_INA219 ina219;
float shuntvoltage = 0;
float busvoltage = 0;

float power_mW = 0;

float array1[3];

//******************************************************************************************

float co22 = 0;
float co2hum2 = 0;
float co2temp2 = 0;
float pressure2 = 0;
float loadvoltage2 = 0;
float current2 = 0;

char co22s[4];
char co2temp2s[8];
char co2hum2s[7];
char pressure2s[6];
char loadvoltage2s[6];
char current2s[6];


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

  for (int i = 5; i > 0; i--) {
    Serial.print(i);
    delay(1000); // I sometimes need a few seconds to restart the serial console.
    wdt_enable(WDTO_4S);
  }


  Wire.begin(8);  ////UNO-1/Slave-1 Address
  Wire.onRequest(sendEvent);

  SensorInit(); // Initialize the displays
  
}

void SensorInit() {

   Serial.println("SCD30 Example");
  Wire.begin();


  if (airSensor.begin() == false)
  {
    Serial.println("Air sensor not detected. Please check wiring. Freezing...");
    while (1)
      ;
  }

  //************************************************************************************

   ina219.begin();
  ina219.setCalibration_16V_400mA(); // set measurement range to 16V, 400mA

  //************************************************************************************

   Serial.println(F("BMP280 Sensor event test"));

  if (!bmp.begin(0x76)) {
    Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
    delay(10);
  }


  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
                  Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
                  Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
                  Adafruit_BMP280::FILTER_X16,      /* Filtering. */
                  Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */

  bmp_temp->printSensorDetails();

}


void loop()
{

if (airSensor.dataAvailable())
  {
    Serial.print("co22(ppm):");
    Serial.print(airSensor.getCO2());
    co22 = airSensor.getCO2();


    Serial.print(" temp2(C):");
    Serial.print(airSensor.getTemperature(), 1);
    co2temp2 = airSensor.getTemperature();


    Serial.print(" humidity2(%):");
    Serial.print(airSensor.getHumidity(), 1);
    co2hum2 = airSensor.getHumidity();
    Serial.println();
    Serial.println();

    Serial.println();
    Serial.print(" Pre-stream data");
    Serial.println();
    Serial.print(co22);
    Serial.println();
    Serial.print(co2temp2);
    Serial.println();
    Serial.print(co2hum2);
    Serial.println();

  }

  //****************************************************************************************

  
shuntvoltage = ina219.getShuntVoltage_mV();
  busvoltage = ina219.getBusVoltage_V();
  current2 = ina219.getCurrent_mA();
  power_mW = ina219.getPower_mW();
  loadvoltage2 = busvoltage + (shuntvoltage / 1000);

  Serial.println();
  Serial.println();
  Serial.print("Load Voltage 2:  "); Serial.print(loadvoltage2); Serial.println(" V");
  Serial.print("Current 2:       "); Serial.print(current2); Serial.println(" mA");
  Serial.println("");
  Serial.println();
  Serial.println();
  array1[0] = busvoltage;
  array1[1] = shuntvoltage;
  array1[2] = loadvoltage2;
  array1[3] = current2;

//***************************************************************************************

sensors_event_t temp_event, pressure_event;
  bmp_temp->getEvent(&temp_event);
  bmp_pressure->getEvent(&pressure_event);

  Serial.println();
  Serial.println();
  Serial.print(F("Temperature 2 = "));
  Serial.print(temp_event.temperature);
  Serial.println(" *C");
  //
  Serial.println();
  Serial.print(F("Pressure 2 = "));
  Serial.print(pressure_event.pressure);
  Serial.println(" hPa");
  //float pressure_pascal=pressure_event.pressure/1000 - 0.90883;
  Serial.println();

  array3[1] = temp_event.temperature;
  delay(1000);

    
  delay(500);
  wdt_reset();
}

void sendEvent()
{
    
//Converting float value to char
//The format (float, bytes, numbers of numbers after the decimal, char variable)
     dtostrf(co22, 4, 1, co22s);
  Wire.write(co22s); // appx 8 bytes
  Wire.write(",");
  
    dtostrf(co2temp2, 8, 4, co2temp2s);
  Wire.write(co2temp2s); // appx 8 bytes
  Wire.write(",");

  dtostrf(co2hum2, 7, 4, co2hum2s);
  Wire.write(co2hum2s); // appx 8
  Wire.write(",");

  dtostrf(pressure2, 6, 2, pressure2s);
  Wire.write(pressure2s); // appx 8
  Wire.write(",");

  dtostrf(loadvoltage2, 6, 4, loadvoltage2s);
  Wire.write(loadvoltage2s); // appx 8
  Wire.write(",");

  dtostrf(current2, 6, 4, current2s);
  Wire.write(current2s); // appx 8
  


  delay(1000);
  
    Wire.write("\n");

  
}

I have another question regarding this setup, currently I am using 24.7k ohms Pull-up resistors. I will be adding more slaves (total 6 slaves - UNO's) to the Master-NodeMCU. Is the pull-up resistance value enough for all the 6 slaves? Each slave will have the similar i2c sensors connected.

Any help regarding this will be much appreciated.

Thank you in advance.

To make your project working, you have to follow these steps:
1. Connect NodeMCU and UNO-1 as per Fig-1. Check that the reading (from 0.00 V to 5.00 V) in the Serial Monitor of Master changes as the Pot1 is rotated.


Figure-1:

2. Post the Master/Slave sketches and readings of the Master Serial Monitor to get help for the next step.

3. Tell the names/link of the sensors that you want to connect with UNO-1.

  1. Yes I can see the changes in the voltage as Pot1 is rotated

  2. Code as follows

Master-Node


// Include the required Wire library for I2C
#include "Wire.h"

int LED = 11;

int x = 0;

void setup() {

// Define the LED pin as Output

pinMode (LED, OUTPUT);

// Start the I2C Bus as Slave on address 9

Wire.begin(9);

// Attach a function to trigger when something is received.

Wire.onReceive(receiveEvent);

//bit rate for data transfer over Serial communication

Serial.begin(9600);

}

void receiveEvent(int bytes) {

x = Wire.read(); // read one character from the I2C

}

void loop() {

//potentiometer value from sensor

int ledPWM = map(x, 0, 255, 0, 1023);

analogWrite(LED, ledPWM);

Serial.print("X is: ");

Serial.println(x);

Serial.print("PWM is: ");

Serial.println(ledPWM);

delay(1000);

}

Slave - UNO


#include "Wire.h"

int x = 0;

int sensorPin = A0;

int sensorValue = 0;

void setup() {



Wire.begin();

Serial.begin(9600);

}

void loop() {

sensorValue = analogRead(sensorPin);

Serial.println(sensorValue);

Wire.beginTransmission(9);

// transmit to device #9

Wire.write(sensorValue);

delay(1000);

Wire.endTransmission();

// stop transmitting

}

Output Serial Monitor at Master

12:59:48.569 -> 0
0
12:59:49.553 -> 0
12:59:50.581 -> 0
12:59:51.556 -> 0
12:59:52.587 -> 0
12:59:53.571 -> 0
12:59:54.556 -> 0
12:59:55.559 -> 0
12:59:56.543 -> 38
12:59:57.575 -> 0
12:59:58.569 -> 256
12:59:59.553 -> 385
13:00:00.564 -> 623
13:00:01.544 -> 1010
13:00:02.575 -> 1023
13:00:03.551 -> 1023
13:00:04.536 -> 1023
13:00:05.565 -> 1023
13:00:06.538 -> 1023
13:00:07.561 -> 1023
13:00:08.543 -> 1023
13:00:09.572 -> 1023


  1. I will be basically connecting 3 i2c sensors and an analog sensor for each slave-uno as follows

BMP280 (I2C)
SCD30 (I2C)
INA219 (I2C)
MQ-8 (Analog)

And the output of the Master Serial Monitor of my project is as follows

13:12:41.949 -> CO2 HUM 2: 0.00
13:12:41.949 -> Pressure 2: 0.00
13:12:43.346 -> Value Uploaded Successfully
13:12:43.346 -> Co2 = 0.00
13:12:43.346 -> 
13:12:43.346 -> 
13:12:43.630 -> Value Uploaded Successfully
13:12:43.630 -> Co2 humidity = 0.00
13:12:43.630 -> 
13:12:43.630 -> 
13:12:44.145 -> Value Uploaded Successfully
13:12:44.145 -> Co2 temp = 0.00
13:12:44.145 -> 
13:12:44.145 -> 
13:12:44.520 -> Value Uploaded Successfully
13:12:44.520 -> hPa = 0.00
13:12:44.520 -> 
13:12:44.520 -> 
13:12:45.545 -> Recieving float as String...
13:12:45.545 -> 
13:12:45.545 -> Reactor 1 Sensors: 
13:12:45.545 -> Pressure 1: 
13:12:45.545 -> 
13:12:45.545 -> Converting string to float...
13:12:45.545 -> 
13:12:45.545 -> CO2 PPM 1: 0.00
13:12:45.545 -> CO2 TEMP 1: 0.00
13:12:45.545 -> CO2 HUM 1: 0.00
13:12:45.545 -> Pressure 1: 0.00
13:12:46.842 -> Value Uploaded Successfully
13:12:46.842 -> Co2 = 0.00
13:12:46.842 -> 
13:12:46.842 -> 
13:12:47.401 -> Value Uploaded Successfully
13:12:47.401 -> Co2 humidity = 0.00
13:12:47.401 -> 
13:12:47.401 -> 
13:12:47.680 -> Value Uploaded Successfully
13:12:47.680 -> Co2 temp = 0.00
13:12:47.680 -> 
13:12:47.680 -> 
13:12:48.005 -> Value Uploaded Successfully
13:12:48.005 -> hPa = 0.00
13:12:48.005 -> 
13:12:48.005 -> 
13:12:48.005 -> Recieving float as String...
13:12:48.005 -> 
13:12:48.005 -> Reactor 2 Sensors: 

Getting all 0 values if both the slaves are connected. But getting the desired values if only one slave is connected.

Who is Master -- NodeMCU or UNO-1?

You are not following my guide lines!!!

Hi,

It's actually working quite well. Thanks for your help though, really helped me a lot.

Hi GolamMostafa,

Do you happen to know if there's a fix for i2c hanging? The slaves are sending the sensor data to the Master but after 30-45mins the transmission stops. After a quick restart of the system, getting the data again. I can post the code if that helps you to get better understanding.

Any help on this, would be highly appreciated.

The latest version of the Wire library does include a timeout feature. If you do detect some sort of timeout, you can always do a Wire.begin() to reinitialize everything.

Could you please tell me where I can do that, at what point exactly?

As part of setup, you need to tell the wire library to use timeouts and to reset the bus if a timeout occurs.

void setup()
...
  Wire.begin();
  Wire.setWireTimeout(5000, TRUE);  // timeout in microseconds, reset
...

and then, after every transaction, you need to test the timeout flag. You will also need to clear it if it gets set

// do some request
if ( Wire.getWireTimeoutFlag() ) {
  // react to it
  Wire.clearWireTimeoutFlag();
}

Since your code had your slave devices unilaterally sending data on the bus which it totally wrong, I can't say exactly where to place this other than after your transactions.