Odd zeroes when reading an integer array with Serial.read()

Hello there. I try to pass an integer array as an object from one Arduino to another, but have some odd zeroes on output. Here is my code:

Transmitter:

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

int arr[5] = {1, 2, 3, 4, 5};

void loop() {
  
  Serial.write((uint8_t*)arr, sizeof(arr));
  
}

Receiver:

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

void loop() {
  
  if (Serial.available() > 0) {
  
    int elem = Serial.read();
    Serial.println(elem);
    
    delay(100);
    
  } else {
  	
    Serial.println("No data");
  
  }
  
}

As an output I get 1 0 2 0 3 0 4 0 5 0 instead of 1 2 3 4 5

Please, let me know if anyone knows what I have been doing wrong.

looks like you are using a microcontroller where ints are stored as two bytes - hence you get two bytes displayed with a 0 after each value
try

byte arr[5] = {1, 2, 3, 4, 5};

read about little endian and big endian

Welcome to the forum.

I tried the Tinkercad simulation with two Arduino Uno's connected RX-TX and TX-RX.
Then I get: 79, 111, 34, 100, 99, 116.
I think that Tinkercad does not support overruling the data at port 0 (RX).

Shall we go through this from the start ?
Which Arduino boards do you use ?
How did you connect them ?
If the Receiver Arduino board has the Serial Monitor open, should the Serial port split itself ? Read data from the other board but send data to the computer ?

It is easier of you allow the Serial Monitor on both (using Serial) and communicate via an other port (for example Serial1).

Can you tell why you want two Arduino boards ? It is easier if you can do your project with a single Arduino board.

horace, Koepel, thank you very much for your replies. Actually, converting integer array into byte one has solved this problem. Thank you very much for your support and attention.

Koepel, possibly, you got those wrong numbers in TinkerCad because you didn't connect grounds of both boards. I had the same problem before.

Koepel, here is my project in TinkerCad if it may help: https://www.tinkercad.com/things/dQPmiOQGdc9-arduinorxtx/editel?sharecode=L9JVpjRGfd6sPvlIoDfl36JUaug6lIeMltOfWFfE7Fg

Try modifying your array to include values such as 256, 512, 1024
Then try 257, 513, 1025
Then 258, 514, 1026

See if you can notice a pattern.

If you have a calculator with programmer mode (even windows calculator has this mode), try entering the number in "decimal" mode, then change the calculator to "hexadecimal" mode and see if you can relate what you see in the calculator to what you are getting in the Serial monitor.

Koepel, excuse me, that link which I sent to you has become outdated because I sent it to more than one person. I didn't know such a thing could happen as I am new to TinkerCad. Here is a new one which I updated. It should work: Login | Tinkercad

Thanks, that works :smiley:

You could add a delay in the Transmitter sketch to reduce the stream of data a little.

You can remove the delay in the Receiver sketch and remove the: else No data part.
The Receiver sketch should be calling Serial.available() as much as possible. Preferably hundreds times per second. So the Receiver can come in action as soon as something is received. After something is received, the Receiver should return to calling Serial.available() as soon as possible.

Tinkercad has two options: Share a project and then others can change it or give a public link to a project that others can copy. If you see my changes, then anyone can change it with that link :scream:

Why to change the data type of the array?

The following sketch (tested on UNO) prints the elements of your int-type array.

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

int arr[5] = {1, 2, 3, 4, 5};

void loop()
{
  for (uint8_t i = 0; i < sizeof arr/2; i++)
  {
    Serial.print(arr[i], DEC);
    Serial.print(' ');
  }
  Serial.println();
  delay(1000);
}

Output:

1 2 3 4 5 
1 2 3 4 5 
1 2 3 4 5 

Notes:
1. int-type array holds 16-bit (2-byte) for every element/item/member of the array.
2. sizeof operator returns total number of bytes present in the array.

Because the "problem" is with Serial.writing the array, not Serial.printing.

Then the OP is using wrong method -- write() which handles 8-bit (byte) data; whereas, the declared array is of type int.

The OP is not necessarily using the wrong method - "wrong" would be missing out the cast.
What if the OP had wanted to transfer a struct?

If there is anything wrong, it is on the receiving end, where each byte is being read in individually and the value printed, instead of being read back into an integer array, then the values from the array printed.

2 Likes

Real transmission/reception int-type array between UNO and NANO using SUART(8, 9) Port.
TX (UNO) Sketch:

#include<SoftwareSerial.h>
SoftwareSerial SUART(8, 9);//SRX = 8, STX = 9
int arr[5] = {1234, 2345, 3456, 4567, 5789};

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

void loop()
{
  for (uint8_t i = 0; i < sizeof arr / 2; i++)
  {
    Serial.print(arr[i], DEC);
    Serial.print(' ');
    SUART.print(arr[i], DEC);//
    SUART.print(','); //delimitter
  }
  Serial.println();
  SUART.print('\n');  //terminating charcater
  delay(1000);
}

RX (NANO) Sketch:

#include<SoftwareSerial.h>
SoftwareSerial SUART(8, 9);//SRX = 8, STX = 9
char myData[30];
int arr[5];

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

void loop()
{
  byte n = SUART.available();
  if (n != 0)
  {
    byte m = SUART.readBytesUntil('\n', myData, 30);
    myData[m] = '\0'; //null character
    //Serial.println(myData);
    char *token;
    token = strtok(myData, ",");
    arr[0] = atoi(token);
    arr[1] = atoi(strtok(NULL, ","));
    arr[2] = atoi(strtok(NULL, ","));
    arr[3] = atoi(strtok(NULL, ","));
    arr[4] = atoi(strtok(NULL, ","));
    //-----------------------------------
    for (uint8_t i = 0; i < sizeof arr / 2; i++)
    {
      Serial.print(arr[i], DEC);
      Serial.print(' ');
    }
    Serial.println();
  }
}

NANO's Serial Monitor:

1234 2345 3456 4567 5789 
1234 2345 3456 4567 5789 

Hmm. Code smell.

1 Like

Arrived message length is almost known in this case, and it is 25. Considering a space for a null-character, 26 locations of the declared array would be occupied. I don't see any harm to keep the buffer_size argument of the readBytesUntil() method equal to the array_size. Anyway, the following code would be the safe one so that the method terminates before going to the beyond of the array_size. Would appreciate to hear your comment/opinion.

byte m = SUART.readBytesUntil('\n', myData, sizeof myData - 1);

it is for array of 10 bytes? So your code transmit 2.5 times more bytes than needs for data itself?
I think this is a bad advice to novice. The idea of OP's code was more correct than yours.
Converting the binary data to text first and than from text to int again is a very inefficient way to transmit. This is a common novice mistake and should be avoided.

You can send binary with at least 3-byte synchronization pattern, CHKSUM, and information as to the number of bytes in the message. There are various ways of exchanging data with relative merits/demerits.

All possible solutions are useful information for a user. We don't know really which one matches his interest.

int arr[5] = {-10001, -20002, -30003, -31010, -32020};

When "almost" isn't good enough