Array between 2 arduinos - I2C

Hey,
I am trying to send an array over I2C from arduino A to arduino B. and then back from Arduino B to Arduino A. (in practice the array will have to be updated with sensor values). it should be variables of the form int and the array would be quite large... ( [20] ) . does anyone have an example sketch similar to this?

Isaak

Try this link: https://www.arduino.cc/en/Tutorial/LibraryExamples/MasterWriter It gives you most of what you want. I used this as my search term "arduino i2c between arduinos". Remember I2C is a designed as communications between peripherals on the same board. Extending it beyond will require special drivers etc.

Yes I know, it's only between an Arduino mega and a NodeMcu with a distance of 10cm.

But I've been trying for a while and am not getting an array correct and complete from the Arduino mega (Master) to the NodeMcu (Slave) and vice versa ... (in case you were to ask yes I am using a level shifter).

Isaak

We are working in the blind without the salient information.

not getting an array correct and complete

In what way? A sample of the output is often very helpful in debugging. What is going in? What is coming out?

Post a schematic of the wiring. Post a photo of the wiring. Sometimes we see things that you may miss.

Post the code. Read the how to use this forum-please read sticky to see how to properly post code. Remove useless white space and format the code with the IDE autoformat tool (crtl-t or Tools, Auto Format) before posting code. If the code is too large to post it can be attached.

But that was not really my original question...

idv7:
does anyone have an example sketch similar to this?

Edit:
Look, actually I don't know how to do it and you will not benefit from my tests. That's why I ask if anyone knows how to do it?

Isaak

Well, you can wait for the perfect sketch to do exactly whay you want or you can help us to help you and get it done, probably sooner and you will learn more. Your choice.

Be careful with the size of the array elements, they may be different on a mega and nodemcu.

GroundFungus,

I think this is pretty generalized?

idv7:
I am trying to send an array over I2C from arduino A to arduino B. and then back from Arduino B to Arduino A. (in practice the array will have to be updated with sensor values).

david_2018,
would it be ok to take the lowest max array elements possible between the two boards?

idv7:
david_2018,
would it be ok to take the lowest max array elements possible between the two boards?

Not sure what you mean.
My comment was to point out that an int is a different number of bytes on a mega and a nodemcu, if I recall correctly, so a direct data transfer byte-for-byte will not work.

Do you know what for data transfer will work?

I think you can specify int16_t data types on both the mega and the node mcu and solve the different integer size issue.

There is a 32 byte buffer limit with the wire library, so the array size of 20 may need to be broken into two halves.

An alternative would be to send the integer data as text between the two devices using Serial. Take a look at Robin2's tutorial on Serial Input Basics.

idv7, I suggest to keep the Wire library for the Arduino board as it is. That means the maximum number of bytes is 32 as cattledog already wrote.
You could have read about the 32 bytes limit here: https://www.arduino.cc/en/Reference.Wire.

Do you really need 16 bit integers ?
Do you really need 20 of those ?
How often are they transferred ?
Can you tell more about the project ? What are the sensors and why you need to send data between the Arduino board and the NodeMcu ?

You can combine any combination of variables in a struct.
This is a tutorial by Robin2: https://forum.arduino.cc/index.php?topic=683181.0.
Using arrays would make the sketch a little shorter and easier, but the way it works is the same.

When splitting the data into two parts, then I suggest to add a 'id' at the beginning of the data, so you know which data belongs to each other. It is also possible to add a 'index' at the front so the Master can decide at which index of the array the data will be stored in the Slave.

The NodeMcu in Slave mode was not possible in the past. I hope it works flawless now.

NodeMcu as slave unfortunately does not work, but this is not such a big problem, the NodeMcu can also be master in my project.
I’ve done some testing to see what the maximum size of my integers may be … But I can’t even send 999, a string “hello NodeMcu” works perfectly …
So it should be possible to send a value of minimum 13 numbers, but as you can see my conversion is not working correctly … I am getting these (183207207207207207207207207207) values inside the nodemcu.
This is my current code:

// NodeMcu Code

#include <Wire.h>
void setup() {
  Serial.begin(9600);
  Wire.begin(D1, D2);
}

void loop() {
  Wire.requestFrom(8, 10);
  while (Wire.available()) {
    char c = Wire.read();
    int i = c - '0';
    Serial.print(i);
  }
  Serial.println();
  delay(1000);
}
// Arduino Code

#include <Wire.h>

char i = 999;

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

void loop() {
  delay(100);
}

void requestEvent() {
  Wire.write(i);
}

Isaak

It is easier to send and receive a whole package at once, either an array or a struct.

When you do a Wire.write( int) in the Slave, then only the 8 lowest bits are used and transferred as a byte.
999dec = 0x3E7, so you are sending 0xE7.
Then you substract ‘0’ in the Master which is 0x30.
0xE7 - 0x30 = 0xB7
Then you put that in a integer, so the first number you will see is 183 (183dec = 0xB7).
The other numbers are not send by the Slave, so you get all 0xFF, because the Slave does not use SDA anymore.
So you get nine of these: 0xFF - ‘0’ = 207

You get exactly what you have put in code. But it does not make any sense.

If they are all int16_t variables, then please transfer an array. Don’t send or receive it byte by byte, don’t convert it to readable ASCII text, but transfer as a whole package of binary data. See my previous post.

You can use SerialTransfer.h to easily and reliably transfer complex data between Arduinos via I2C, UART, and SPI. It comes with examples and is installable via the Arduino IDE

I am trying with SerialTransfer.h, but when I try to upload the tx code to the NodeMcu I get this error :

exit status 1
Fout bij het compileren voor board NodeMCU 1.0 (ESP-12E Module)

This was the error that was in red:

C:\Users\devos\Documents\Arduino\libraries\SerialTransfer\src\SPITransfer.cpp: In member function 'uint8_t SPITransfer::available()':
C:\Users\devos\Documents\Arduino\libraries\SerialTransfer\src\SPITransfer.cpp:111:29: error: 'SPDR' was not declared in this scope
  volatile uint8_t recChar = SPDR;
                             ^

I've tried both the rx and tx code but none of them want to compile for the NodeMcu. (compiling for an Arduino Mega works fine)

Isaak

Here is some code to transfer an int array between two Arduino via Serial, i already had some similar code that i just adjusted for your needs.

int m_intArray[20] {1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 11000, 12000, 13000, 14000, 15000, 16000, 17000, 18000, 19000, 20000};
int m_inputArray[20];


void setup() {
  Serial.begin(115200);
  Serial3.begin(115200); // Best to use a seperate Serial for COMS to avoid Seerial COMS conflicting with debug statments
  Serial.println(F("Arduino 2 started"));
  delay(1000);
}

void loop() {
  serialDataReceived(Serial3);
  sendArray(Serial3);
}

void sendArray(HardwareSerial& a_serial) {
  static unsigned long previousMillis = millis();
  if (millis() - previousMillis >= 10000UL) { // Make sure times are different on each arduino !!!
    Serial.println(F("Sending data"));
    printIntArray(a_serial, m_intArray, 20);
    previousMillis = millis();
  }
}

void serialDataReceived(HardwareSerial& a_serial) {
  if (a_serial.available() > 0) {
    static char responceBuffer[128];
    static int charCnt = 0;
    char c = a_serial.read();
    if ((c >= '0' && c <= '9') || c == '-' || c == ',') {
      if (charCnt < 128)
        responceBuffer[charCnt++] = c;
    }
    else if (c == '\n') {
      for (int& val : m_inputArray) val = 0;
      Serial.print(F("Received responceBuffer: ")); Serial.println(responceBuffer); // THIS IS JUST FOR DEBUGGING
      buffToIntArray(responceBuffer, m_inputArray, 20);
      for (char& val : responceBuffer) val = 0;
      Serial.print(F("Received array: ")); printIntArray(Serial, m_inputArray, 20); // THIS IS JUST FOR DEBUGGING
      charCnt = 0;
    }
  }
}

void printIntArray(HardwareSerial& a_serial, const int* a_array, const int& a_size) {
  char responce[128];
  int position = 0;
  for (int i = 0; i < a_size; i++) {
    char buffer[8];
    itoa(a_array[i], buffer, 10);
    for (int n = 0; n < 8; n++) {
      if ((buffer[n] >= '0' && buffer[n] <= '9') || buffer[n] == '-') {
        responce[position++] = buffer[n];
      }
    }
    responce[position++] = ',';
  }
  responce[position++] = '\0';
  a_serial.println(responce);
}

void buffToIntArray(const char* a_responceBuffer, int* a_array, const int& a_size) {
  int arrayPos = 0, bufferPos = 0;
  char buffer[16];
  for (int i = 0; i < 128; i++) {
    if (a_responceBuffer[i] >= '0' && a_responceBuffer[i] <= '9') {
      buffer[bufferPos++] = a_responceBuffer[i];
    }
    else if (a_responceBuffer[i] == ',' && arrayPos < a_size) {
      a_array[arrayPos++] = atoi(buffer);
      bufferPos = 0;
      for (char& val : buffer) val = 0;
    }
    else if (a_responceBuffer[i] == '\0') {
      break;
    }
  }
}

@Power_Broker

Hello

I have found that you have created 2 libraries for Raspberry and Arduino in order to allow then to send list of values back and forth.

I have downloaded and installed your pySerialTransfer library on my raspberry 4 py Py2.7 and your library other SerialTransfer on Arduino Mega. I have checked that I have the serial port on Raspberry set on the same port as the Arduino at the same Braud. But I have got this error message see below.

"
Traceback (most recent call last):
File “/home/pi/Desktop/Project ABCD/PycharmProject/testserailcommunication.py”, line 29, in
while not link.available():
File “build/bdist.linux-armv7l/egg/pySerialTransfer/pySerialTransfer.py”, line 449, in available
recChar = int.from_bytes(self.connection.read(),byteorder=“big”)
AttributeError: type object ‘int’ has no attribute 'from_bytes
"

I suppose the issue here is that this library is made for py 3 not py 2.7.

I guess the following change needs to be done to run it in py 2.7.
int.from_bytes(self.connection.read(),byteorder=“big”) => int(codecs.encode(self.connection.read(), ‘hex’), 16)

Could you please update your library to py 2.7? I already tried but I have restricted access to library file in my Raspberry pi and I don’t know how to bypass it.

PS: I am working on a project. I need to send a list of value from sensors wired to a Arduino Mega board to a Raspberry pi 4 Py2.7. Then, I run an algorythme which will collect this list of value in order to create a new list of output value. Then, Raspberry will send this list of output value back to the Arduino Mega as all actuators are wired to the Arduino Mega board.

Cheers

idv7:
I am trying with SerialTransfer.h, but when I try to upload the tx code to the NodeMcu I get this error :

exit status 1

Fout bij het compileren voor board NodeMCU 1.0 (ESP-12E Module)




This was the error that was in red:


C:\Users\devos\Documents\Arduino\libraries\SerialTransfer\src\SPITransfer.cpp: In member function 'uint8_t SPITransfer::available()':
C:\Users\devos\Documents\Arduino\libraries\SerialTransfer\src\SPITransfer.cpp:111:29: error: 'SPDR' was not declared in this scope
  volatile uint8_t recChar = SPDR;
                            ^




I've tried both the rx and tx code but none of them want to compile for the NodeMcu. (compiling for an Arduino Mega works fine)


Isaak

Update your library and try again. The SPI portion of the library can cause issues with some boards because of the a** backwards way different boards implemented SPI API in their respective cores. The lack of standardization makes coding a lib for SPI a nightmare. Anyway, I implemented a fix for this some time ago, so update and try and it will work!

florianbus:
Could you please update your library to py 2.7?

I guess I can make it backwards compatible, but you need to realize that Python 2 is unsupported and you really should update your code to Python 3 or greater