Sending 5 digit intigers over i2c bus between arduino and ESP32

Hi!
I'm trying to feed values from an arduino stored in a array to an ESP32 to help evaluate some unrelated code. The values I'm sending are in the form of an float, which I've already converted to ints by shifting the decimal point. This gives me a 5 digit whole number that I need to send over to the ESP32 over i2c.
i2c, as I've discovered can only handle values from 0 to 255, while I'm reaching up to about 40000. From reading other topics and forums I've seen that there are MANY ways to split up the data so that it can fit in the 8 bit packet, but since I'm not a very good programmer, I've been unsuccessful at any of the solutions I've come across yet. I'll add the send and recieve code below, and I appreciate any recomendations on how to make this work. Thanks!

Send

#include <Wire.h> 
int send;
int x;

int data[36] = {
10625,10526,10526,10526,10526,10526,10527,10527,10527,10527,10527,10526,10527,10527,10526,10527,10526,10527,10527,10526,10527,10527,10526,10526,10526,10526,10526,10525,10525,10525,10525,10525,10525,
};

void setup() {
  // Start the I2C Bus as Master
  Serial.begin(115200);

  Wire.begin(); 
}
void loop() {
  Wire.beginTransmission(9); // transmit to device #9
  Wire.write(send);              // sends x 
  Wire.endTransmission();    // stop transmitting
  Serial.println(send);

  x++;
  if (x > 36) {
    x = 0;
  }

  send = data[x];


  delay(100);
}

#include <Wire.h> 

int x = 0;

void setup() {
  Serial.begin(115200);
  // Define the LED pin as 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);
}
void receiveEvent(int bytes) {
  x = Wire.read();    // read one character from the I2C
}
void loop() {
  Serial.println(x);
  delay(100);
}

Welcome to the forum.

Why are you using the I2C bus ?
Can you use Serial2 on the ESP32 and SoftwareSerial on the Arduino board ?

Which Arduino board do you use ?
Do you have a I2C level shifter between the boards ?
How many floating point numbers do you have ?
If you use an Arduino Uno, then 32 bytes can be send in a single I2C session with Wire.write(). That are 8 floating point numbers if single precision floating point is used.
How long is the distance between the boards ? The I2C bus was not designed to go into a cable.

Please, provide a numerical of the float numbrs you want to transfer from Arduino UNO to ESP32 over the I2C Bus. I wiill show you a way of sending them without changing the basic nature of the float numbers (I mean -- no need to remove the decimal point).

Yes! You are right that the I2C bus is a byte-oriented protocol. It can send/receive one byte data (8-bit) during one bus cycle. However, note that you can send only 32-byte data in one GO (between beginTransmission() and endTransmission()) which restricts you sending only eight float numbers in one GO using write() method.

what is the project? describe it?
upload a schematic showing the components, power supplies and wiring of the system

why do you require two microcontrollers?
the ESP32 is far more powerful than the UNO - could you dump the UNO and just use the ESP32 ?
having to program two microcontrollers and the resultant communications makes the overall task complexity an order of magnitude greater

1 Like

Currently both microcontrollers are just connected with i2c pins and gnd. The ESP32 is being used for rocket avionics, and to test the avionic systems, I want to feed the ESP32 with barometric data to determine whether the code functions as I excpect. This is why I'm using an arduino to hold these barometric values and feed them to the ESP32.

There's a lot of critical timing required within the code for the avionics, and to keep it as simple as possible, I'd rather not put a very large amount of numbers in to the code. All I'm trying to figure out is how to send just one value at a time over a regular interval so that I can simulate a rocket launch in the code.

Hi Golem,
I have a very long string of numbers but here is a few of them:

105.25,
105.25,
105.25,
105.25,
105.25,
105.25,
105.26,
105.26,
105.26,
105.26,
105.27,
105.42,
105.7,
106.03,
106.52,
107.47,
108.49,
109.79,

Thank you Koepel,
Im using the i2c bus because I am familiar with it on both the arduino and ESP32
I did not know about software serial and serial2, would you recomend I use that instead?

I'm using an Arduino Uno
I do not have a level shifter and just realized that they operate at different voltages (!). It's been working so far (of course only with numbers less than 256), but I do not want to stress the ESP.
I have a LOT of floating point numbers, around 1300. If I store the variables in the Arduino flash, I should be able to cram them all in there.
How can I send these 32 bytes in a single session? Anything over 255 just gives jibberish on the ouptut.
The distance between the boards is a few cm.

The Wire.write() can use a pointer to memory and a variable for the number of bytes.
There is a Wire.readBytes(), but it has also a timeout. That timeout may not start in a interrupt, so you have to be sure that the bytes are available before using Wire.readBytes(). You can also use a loop with normal Wire.read() bytes.
Any data is a number of bytes in memory. Sometimes a pointer to that memory has to be cast to an other pointer.

How are you going to store data in Flash ?

I'm having doubts about the whole project. Can you answer the questions by horace in post #4 ?

Because of I2C Buffer limitation, you will be able to send only eight float numbers in one GO. If you have 40 float numbers, then you have to conduct 5 transactions. Here, I show you the procedures of sending eight float numbers from UNO (the Master) to ESP32 (the Slave) using I2C Bus. Note that a float number is saved as 4-byte (32-bit) data into memory according to IEEE-754 (binray32) standard. The memcpy() function can be used to convert a float numer into bytes and vice versa.

1. Build the following circuit (Fig-1) among 3.3V ESP32, Level Shifter, and 5V UNO.


Figure-1:

2. Upload the following sketches:
UNO Master Sketch:

#include<Wire.h>
#define slaveAddress 0x23 //0100011
float myData[] =
{
  123.45, 234.56, 345.67, 567.78,
  677.89, 778.91, 789.12, 891.22
};
byte destBytes[4];

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  //--------------
  Wire.beginTransmission(slaveAddress);
  for (int i = 0; i < 8; i++)
  {
    memcpy(&destBytes, &myData[i], 4);//convert float to bytes
    Wire.write(destBytes[0]);
    Wire.write(destBytes[1]);
    Wire.write(destBytes[2]);
    Wire.write(destBytes[3]);
  }
  Wire.endTransmission();
}

void loop()
{
  
}

ESP32 Slave Sketch:

#include<Wire.h>
#define slaveAddress 0x23 //0100011
volatile bool flag = false;

byte recData[32];
float myData[8];

void setup()
{
  Serial.begin(9600);
  Wire.begin(slaveAddress);
  Wire.onReceive(receiveEvent);
}

void loop()
{
  if (flag == true)
  {
    for (int i = 0, j = 0; i < 32; j++, i = i + 4)
    {
      memcpy(&myData[j], &recData[i], 4);//convert bytes to float
      Serial.println(myData[j], 2);
    }
    flag = false;
  }
}

void receiveEvent(int howMany)//32 bytes
{
  for (int i = 0; i < howMany; i++)
  {
    recData[i] = Wire.read();
  }
  flag = true;
}

3. Press the RESET Button of Master UNO.
4. Check that Serial Monitor of Slave shows:

123.45
234.56
345.67
567.78
677.89
778.91
789.12
891.22

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