I2C Communication

HI, I´m kind of new with arduino, but it doesn´t mean I don´t have crazy ideas with this. Im working on a project with Arduino UNO with SD Card Shield and ESP8266. The main idea is to create a datalogger for DHT11 and analog Read from a sensor. Up to here everything is working. I have been reading for a while because I can´t send the float values for temp and humidity from DHT11 to the ESP8266, I can send text, and ints from slave (UNO) to Master (ESP8266) using Wire.write.

I am currently using the I2C anything and I can send messages from Master to Slave, but when I get to the Wire.requestFrom(SLAVE_ADDRESS) I get stucked. Don´t know if there is a conflict with libraries or what I´m doing wrong.

Master and Slave codes are attached.

Please your help. Also if you consider using SPI or UART is better, please let me know

nmcu_I2C.ino (1010 Bytes)

UNO_I2C.ino (3.97 KB)

The Arduino Uno has a 5V I2C bus and the ESP8266 has a 3.3V I2C bus. The pins of the ESP8266 are more or less 5V tolerant, so it will not get damaged, but the voltage of the I2C bus signals do not match.
Could you read this: How to make a reliable I2C bus · Koepel/How-to-use-the-Arduino-Wire-library Wiki · GitHub.

Serial/UART is better, but then you still have to fix the difference in voltage levels.
Can you do your project with a single ESP32 ? Avoid all the 5V/3.3V trouble by not using 5V sensors. That is a lot easier. By the way, the ESP32 does not have 5V tolerant pins !

Could you make the text layout of the sketch better ? Make every indent, every comma, every space, every new line, everything at the right place. A good sketch shows at the first glance the structure of the code.

The Uno Slave sketch:

Your 'volatile' flag 'haveData' and your 'volatile' variables are very good.

The onRequest handler needs only Wire.write(). It is allowed to use more than one Wire.write().
Remove your Wire.beginTransmission() and Wire.endTransmission() from sendEvent().

I prefer that you check if 'howMany' has exactly the right size.
So "if (howMany ==" instead of "if (howMany >=".

Do you know a 'struct' ? That is the best way to transfer the data. See the tutorial by Robin2: Use I2C for communication between Arduinos - Exhibition / Gallery - Arduino Forum.

The receiveEvent() function is not used yet.

The ESP8266 Master sketch:

There is no need to use 'volatile' variables. They are only used in the loop() and are not changed in a interrupt routine. The 'haveData' variable is not needed.

Could you remove the Event() function ?
Requesting data from the Uno is done in the loop() with normal functions.

The Wire buffer size of the Arduino Uno is 32. You can read only 32 bytes.

  Wire.requestFrom( 8, (sizeof( foo1) + (sizeof( bar)) );  //0x08 = 8;
  if( Wire.available() == (sizeof( foo1) + (sizeof( bar)) )
  {
    I2C_readAnything (foo1);
    I2C_readAnything (bar);

    Serial.print ("Received bar= ");
    Serial.println (bar);
    Serial.print ("Received foo1 = ");
    Serial.println (foo1);
  }
  else
  {
    Serial.println( "Error, no data or wrong amount of data");
  }

This tutorial shows a way of transferring float data from DHT11 of UNO-Slave to NodeMCU-Master using I2C Bus.

1. Make the following setup of Fig-1.

espMunoSi2c.png
Figure-1:

2. Upload the following Master Sketch into NodeMCU (ESP8266).

#include <Wire.h>

void setup()
{
  Serial.begin(115200);
  Serial.println("  ");
  Wire.begin(4, 5); // SDA = GPIO-4, SCL = GPIO-5
  Wire.beginTransmission(8);
  byte busStatus = Wire.endTransmission();
  if (busStatus != 0)
  {
    Serial.print("Slave is not found...!");
    while (1);
  }
  Serial.println("Slave is found.");
}

void loop()
{
  byte n = Wire.requestFrom(8, 10);
  Serial.print("Received Humidity: ");
  for (int i = 0; i < 5; i++)
  {
    Serial.print((char)Wire.read());
  }
  Serial.println(" %H");
  //---------------------------------
  Serial.print("Received Temp: ");
  for (int i = 5; i < 10; i++)
  {
    Serial.print((char)Wire.read());
  }
  Serial.println(" degC");
  Serial.println("============================");
  delay(2000);
}

3. Upload the following Slave Sketch into UNO.

#include<Wire.h>
#include "DHT.h"
#define DHTPIN A1
#define DHTTYPE DHT11   // DHT 11
DHT dht(DHTPIN, DHTTYPE);
float h, t;

void setup()
{
  Serial.begin(9600);
  dht.begin();
  Wire.begin(8);
  Wire.onRequest(sendEvent);
}

void loop()
{
  h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  t = dht.readTemperature();
  Serial.print("Humidity: "); Serial.print(h, 2); Serial.println("%H");
  Serial.print("Temp: "); Serial.print(t, 2); Serial.println("°C");
  Serial.println("===============================");
  //long bin32h = *(long*)&h;
  //Serial.println(bin32h, HEX);
  delay(2000);
}

void sendEvent()
{
  Wire.print(h, 2);  //data beig sent as ASCII charcaters
  Wire.print(t, 2);
}

4. Press RESET Key on UNO. We will observe the following Slave Serial Monitor
smSz.png

5. Press RESET Key on NodeMCU. We will observe the following Master Serial Monitor
espM.png

If you wish you can send binary values of Humidity and Temperature rom UNO to NodeMCU.

espMunoSi2c.png

espM.png

smSz.png

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