ESP32 problem with WIRE library

Good morning everyone…

I have a little big problem in my project where I'm using different libraries that work great without conflicts with each other.

But now I have to transfer variables between a NANO and an ESP 32 38 pin using the WIRE library through I2c.

Result I have no data transfer between the two processors LCD does not work and BME 680 is not recognized.

In summary

NANO has to send data of a variable (x in my case) through I2c

ESP 32 must receive data with I2c using WIRE library

ESP 32 connected with I2c a 24x4 LCD display

ESP 32 connected a BME 680 with I2c

GND in common 5V power supply.

etc.

All services with I2c work fine without WIRE library

As soon as I insert this into the project, there is no transfer between the NANO and the ESP 32.

The instructions work perfectly between NANO and ESP 32 using only the WIRE and eliminating the use of other peripherals that use I2c

Very small connections about 10cm.

Through the serial line, only the variable x of the Loop is updated with the print of the zero previously assigned, but not updated by the receiveEvent(int howMany).

Some idea? Should I use a different library? Are there any known issues with ESP 32 and the WIRE?

I've already searched for a similar problem on the net, but haven't found anything for my case.

Thanks in advance for your attention.

#include <Wire.h>  // Library for I2C communication
#define I2C_DEV_ADDR 0x55
#include <LiquidCrystal_I2C.h>  // Library for LCD

//------------------------------------------------------------------------ SENSOR BME 680 //

#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "MutichannelGasSensor.h"
#include "Adafruit_BME680.h"

#define SEALEVELPRESSURE_HPA (1022.6)  //(1013.25)
float correzione_temperatura = 2.08;
float correzione_pressione = 12.5;
Adafruit_BME680 bme;

float temperature;
float pressure;
float humidity;
float gas_resistance;
float readAltitude;

//------------------------------------------------------------------------ SENSOR BME 680 //

//--------------------------------------------------------------------------- LCD DISPLAY //

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

int x = 0;

void setup() {
  //--------------------------------------------------------------------------- LCD DISPLAY //
  Wire.begin((uint8_t)I2C_DEV_ADDR);  // Inizializzazione I2c
  Wire.onReceive(receiveEvent);
  Serial.begin(115200);  // Inizializzazione Seriale

  // ---- S E T U P -    LCD     ----//

  lcd.backlight();           //                                                // Backlight ON LCD
  lcd.begin(20, 4);          //                                                // Inizializzazione Display LCD 20x4

  // ---- S E T U P -    LCD     ----//

  // ---- S E T U P - BME 680    ----//

  if (!bme.begin()) {
    Serial.println(F("Could not find a valid BME680 sensor, check wiring!"));
    //while (1);
  }
  // Set up oversampling and filter initialization
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150);  // 320*C for 150 ms

  // ---- S E T U P - BME 680    ----//
}


void loop() {
  BME_680();  //   aggiorna valori dei Sensor
  delay(100);

  Serial.print("x nel loop ");
  Serial.println(x);

  lcd.setCursor(0, 0);
    lcd.print(x);
}


void receiveEvent(int howMany) {
  x = Wire.read();
  Serial.print("x nella ricezione evento ");
  Serial.println(x);
}


//------------------------------------------------------------------------ SENSOR BME 680 //

void BME_680() {

  if (!bme.performReading()) {
    Serial.println("Failed to perform reading :(");
    return;
  }
  temperature = bme.temperature - correzione_temperatura;  // fattore di correzione
  pressure = (bme.pressure / 100.0) + correzione_pressione;
  humidity = bme.humidity;
  gas_resistance = bme.gas_resistance / 1000.0;
  readAltitude = bme.readAltitude(SEALEVELPRESSURE_HPA);

  // Obtain measurement results from BME680. Note that this operation isn't
  // instantaneous even if milli() >= endTime due to I2C/SPI latency.
  if (!bme.endReading()) {
    Serial.println(F("Failed to complete reading :("));
    return;
  }
}

Since hardware is involved it would be best if you posted an accurate annotated schematic of your circuit as you have it wired. Frizzy pictures are not considered schematics they are wiring diagrams and almost useless. Also post links to "Technical Information" for the hardware devices, links to places like azon generally give sales information, not technical information.

That library is called Wire. Although your PC might use an old case-insensitive filesystem you should always use the correct name in code and in references.

That would make a multi-master setup. Although is theoretically defined to be multi-master capable I have never seen a real system running reliably with such a setup. The Nano's Wire library isn't multi-master capable, I don't know if the ESP32 Wire library does implement that.

So you have to define one MCU as the master. As the ESP32 uses several slaves already I suggest to define the Nano as a slave. That means the ESP32 has to actively request that variable from the Nano.

Next problem: the Nano runs on 5V while the ESP32 runs on 3.3V. Although you could run the I2C bus on 3.3V for all connected devices it will be at the limit for the Nano, so your complete bus length (all I2C wire lengths summed up) must be very short (~ < 20cm). I recommend to use a level converter to connect the Nano to the others.

Once you fixed that post the sketches of both MCU if it still doesn't work.

Have you used level shifter between ESP32 and NANO as per Fig-1?


Figure-1:

Yes of course

I also try this solution. I was already thinking about this.

1. Upload the following sketch (your sketch of post #1 is slightly moderated) into ESP32.

#include <Wire.h>  // Library for I2C communication
#include <LiquidCrystal_I2C.h>  // Library for LCD
#include <Adafruit_Sensor.h>
#include "MutichannelGasSensor.h"
#include "Adafruit_BME680.h"

#define SEALEVELPRESSURE_HPA (1022.6)  //(1013.25)
float correzione_temperatura = 2.08;
float correzione_pressione = 12.5;
Adafruit_BME680 bme;

float temperature;
float pressure;
float humidity;
float gas_resistance;
float readAltitude;

LiquidCrystal_I2C lcd(0x27, 20, 4);

int x = 0;

void setup() 
{
  Serial.begin(115200);  // Inizializzazione Seriale
  Wire.begin(21, 22);  //SDA, SCL
  lcd.backlight();           //                                                // Backlight ON LCD
  lcd.intit();  //if not working, then lcd.begin();
  if (!bme.begin()) 
{
    Serial.println(F("Could not find a valid BME680 sensor, check wiring!"));
    //while (1);
  }
  // Set up oversampling and filter initialization
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150);  // 320*C for 150 ms
}

void loop() 
{
  BME_680();  //   aggiorna valori dei Sensor
  delay(100);

  Serial.print("x nel loop ");
  Serial.println(x);

  lcd.setCursor(0, 0);
    lcd.print(x);
}

void BME_680() 
{

  if (!bme.performReading()) {
    Serial.println("Failed to perform reading :(");
    return;
  }
  temperature = bme.temperature - correzione_temperatura;  // fattore di correzione
  pressure = (bme.pressure / 100.0) + correzione_pressione;
  humidity = bme.humidity;
  gas_resistance = bme.gas_resistance / 1000.0;
  readAltitude = bme.readAltitude(SEALEVELPRESSURE_HPA);

  // Obtain measurement results from BME680. Note that this operation isn't
  // instantaneous even if milli() >= endTime due to I2C/SPI latency.
  if (!bme.endReading()) {
    Serial.println(F("Failed to complete reading :("));
    return;
  }
}

2. If Step-1 works, then connect NANO with ESP32 using I2C Bus and level shifter as per Fig-1 of post #4.
3. Upload the following revised sketch in ESP32.

#include <Wire.h>  // Library for I2C communication
#include <LiquidCrystal_I2C.h>  // Library for LCD
#include <Adafruit_Sensor.h>
#include "MutichannelGasSensor.h"
#include "Adafruit_BME680.h"
#define nanoAddress 0x35

#define SEALEVELPRESSURE_HPA (1022.6)  //(1013.25)
float correzione_temperatura = 2.08;
float correzione_pressione = 12.5;
Adafruit_BME680 bme;

float temperature;
float pressure;
float humidity;
float gas_resistance;
float readAltitude;

LiquidCrystal_I2C lcd(0x27, 20, 4);
char recvMsg[10];
int x = 0;

void setup() 
{
  Serial.begin(115200);  // Inizializzazione Seriale
  Wire.begin(21, 22);  //SDA, SCL
  lcd.backlight();           //                                                // Backlight ON LCD
  lcd.intit();      //if not working, then lcd.begin();
  if (!bme.begin()) 
{
    Serial.println(F("Could not find a valid BME680 sensor, check wiring!"));
    //while (1);
  }
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150);  // 320*C for 150 ms

  // ---- S E T U P - BME 680    ----//
  Wire.beginTransmission(nanoAddress);
  byte busStatus = Wire.endTransmission();
  if(busStatus != 0)
  {
        Serial.print("NANO is not found.");
        while(1);  //wait for ever
  }
  Serial.println("NANO is found);
  Wire.beginTransmission(nanoAddress);
  Wire.print("Hello NANO!");
  Wire.endTransmission();
  //--------------------------------------
  Wire.requestFrom(nanoAddress, 3);
  for( int k = 0; k < 3; k++)
  {
        recvMsg[k] = Wire.read();
  }
  recvMsg[k] = '\0';  //null charcater
  Serial.println(recvMsg);  //shows: ok!
}

void loop()
 {
  BME_680();  //   aggiorna valori dei Sensor
  delay(100);

  Serial.print("x nel loop ");
  Serial.println(x);

  lcd.setCursor(0, 0);
    lcd.print(x);
}

void BME_680() 
{
  if (!bme.performReading()) {
    Serial.println("Failed to perform reading :(");
    return;
  }
  temperature = bme.temperature - correzione_temperatura;  // fattore di correzione
  pressure = (bme.pressure / 100.0) + correzione_pressione;
  humidity = bme.humidity;
  gas_resistance = bme.gas_resistance / 1000.0;
  readAltitude = bme.readAltitude(SEALEVELPRESSURE_HPA);

  // Obtain measurement results from BME680. Note that this operation isn't
  // instantaneous even if milli() >= endTime due to I2C/SPI latency.
  if (!bme.endReading()) {
    Serial.println(F("Failed to complete reading :("));
    return;
  }
}

4. Upload the following sketch in NANO (exchanging message with ESP)

#include<Wire.h>
#define nanoAddress 0x35
volatile bool process = false;
char myMsg[20];

void setup()
{
    Serial.begin(115200);
    Wire.begin(nanoAddress);
    Wire.onReceive(receiveEvent);
    Wire.onRequest(sendEvent);
}

void loop()
{
    if(process == true)
    {
        Serial.println(myMsg);
        process = false;
    }
}

void receiveEvent(int howMany)
{
    for(int j = 0; j < howMany;  j++)
    {
          myMsg[j] = Wire.read();
    }
    myMsg[j] = '\0';   //null charcater
    process = true;
}

void sendEvent()
{
     Wire.print("ok!");
}

5. Press RST button of NANO.
6. Press EN button of ESP32.
7. Check that Hello NANO! has appeared on SM of NANO.

1 Like

Carefully follow what GolamMostafa wrote, it might be the only way to make it work. Let us know how it goes and where you get stuck.

Why do you need the Nano board ? Can you do everything with the ESP32 ? You will avoid a lot of trouble. If you really need the Nano board, can you use Serial2 on the ESP32 ? You still need that level shifter.

1 Like

@patdepri:

Cross-posting HERE.

Your discussion in the Italian language section will be closed.

Guglielmo

First of all, thanks in advance to whoever replied.
I finally managed to fix it.
I made a big mistake using the NANO as a MASTER instead I HAD to do the opposite.

I'll briefly explain my project and why I stupidly ran into these errors.

I have a transmitter and a receiver with NANO, basically a remote control with a receiver (NANO with NRF24L01+ Mirf) because I need to transmit over a hundred meters distance.

NANO transmitter with push button (which I considered master).
NANO receiver (which I considered slave).

I considered the NANO receiver as master to send a variable to ESP32 through I2c, and here was the error.

ESP32 (which must receive the variable) has LCD DISPLAY, BME 680, etc. peripherals connected through I2c.
The latter could not be configured as SLAVE as it had to be configured as MASTER in order to drive LCD, BME etc. or I would have had to transfer the peripherals to the NANO.

In practice, my very serious and stupid mistake was to consider I2c as bidirectional sending and receiving, but this is not the case for various DISPLAYS and BMEs.

So communication does indeed have a direction, but also a direction to where (I don't know how to say it in English) to be clear from here ---> or from there <---.

ES 32 had to request the variable from the NANO used as a receiver and not that the NANO functioned as a Master with the claim to also drive the peripherals controlled by the ESP32.

This in very simple words. In reality, I have a few thousand extremely complex and interconnected lines of code on the ESP.
Someone more experienced would have written half of it, but I've just chewed C.

I also removed the resistors and level shifter and everything works fine.
I will put them back in the final printed circuit (maybe, boh...).

I didn't put all the code, it's only the relevant part.

Master ESP

#include <Wire.h>  // Library for I2C communication
void setup() {
  Wire.begin(); 
}
void loop() {
  a = 0;
  x = 0;
  request_1();

// BLA BLA BLA ecc ecc ecc
}

void request_1() {
  while (a == 0) {
    Wire.requestFrom(7, 1);
    while (Wire.available()) {
      x = Wire.read();
      if (x != 0) {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print(F("x  "));
        lcd.print(x);
        Serial.print(F("x  "));
        Serial.println(x);
        a = 1;
      }
    }
  }
}

Slave NANO

#include <Wire.h>
void setup() {
  Wire.begin(7);
  Wire.onRequest(trasm);
  Serial.begin(115200);  // Avvia Serial
}

void loop() {
  byte data[Mirf.payload];
  if (Mirf.dataReady())  
  {
    Mirf.getData(data); 

    adata = (unsigned int)((data[1] << 8) | data[0]);

    digitalWrite(Signal, LOW);
  }
  trasm();
}

// ------------------------------------------------------------------------------ L O O P //

void trasm() {
  if (adata == 1) {
    //Serial.print("pin = ");
    //Serial.println(adata);
    digitalWrite(LED_1, HIGH);  //accende il led
  } else {
    digitalWrite(LED_1, LOW);  //spegne il led
  }
  if (adata == 2) {
    //Serial.print("pin = ");
    //Serial.println(adata);
    digitalWrite(LED_2, HIGH);  //accende il led
  } else {
    digitalWrite(LED_2, LOW);  //spegne il led
  }
  
// BLA BLA BLA ecc ecc ecc

  if (adata != 0 && previous_adata != adata) {  
    previous_adata = adata;
    //Serial.print(F("adata 1 ")); Serial.println(adata);
    x = adata;
    //Serial.print(F("adata 2 ")); Serial.println(adata);
    if (x != 0) {
      Serial.print(F("x ")); Serial.println(x);
      Wire.write(x);
    }
  } else {  
    adata = 0;
    previous_adata = 0;
    x = 0;
    Leds_off();
    digitalWrite(Signal, LOW);
  }
}

thanks - thanks - thanks

Could you rename the onRequest handler function "requestEvent()" instead of "trasm()".
Keep the "requestEvent()" as short as possible, about three lines of code if possible.
It is not allowed to call the "requestEvent()" from the loop().

In the requestEvent(), always send data back. If you skip the Wire.write() then the Master does not know that something is skipped and it probably reads 0xFF.

trasm() is an interrupt context where print() is not recommended to be executed.

Ok thanks for the advice, I did what you said and it works great.
Thanks again, have a nice day everyone.

1 Like

Sorry I didn't know about this part of the regulation. There is always something to learn. I thought the two were independent.

Scusa non sapevo di questa parte del regolamento. C’è sempre da imparare. Pensavo che le due cose fossero indipendenti.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.