Sending and receiving an array of integers over softwareserial

I want to communicate a large data from one arduino to another over softwareserial. The data consists entirely of integer values , so I plan to use an array. How can I do so?(both sending and receiving).Any example code will be appreciated.

How can I do so?

int someArray[] = { /* some values go here */ };

void loop()
{
   sendTheData();
}

void sendTheData()
{
   for(int i=0; i<sizeof(someArray) / sizeof(someArray[0]; i++)
   {
      Serial.print("<");
      Serial.print(i);
      Serial.print(",");
      Serial.print(someArray[i]);
      Serial.print(">");
   }
}

This will send something like "<0, 12><1, 45><2, 542>...".

It is easy to receive the data, and put each value in the appropriate position in the array on the receiver.

Since I am communicating with another arduino , should I replace Serial.print in the code with mySerial.write?

No stick to Serial.print(). It will make the debugging very much easier. For receiving the data have a look at the 3rd example in Serial Input Basics

How many elements are there in the array?

...R

3 elements!

sen_diptangshu:
3 elements!

I thought you said "large" in your Original Post.

The simplest way to send 3 elements is like this (adapted from @PaulS's code)
int someArray[] = { /* some values go here */ };

void sendTheData()
{
   Serial.print("<");
   for(int i=0; i<sizeof(someArray) / sizeof(someArray[0]; i++)
   {
      Serial.print(someArray[i]);
      Serial.print(",");
   }
   Serial.print(">");
}

That will send <23,456,93,>. You could make it more complicated so it doesn't include the final comma, but I don't think that's necessary.

...R

I am posting both the sender and receiver codes. But nothing gets printed on Serial Monitor. Where did I go wrong?

//sending
#include <SoftwareSerial.h>

SoftwareSerial mySerial(5,6); //rx pin,tx pin

void setup() {
  // put your setup code here, to run once:
mySerial.begin(9600);
}
int otp=1;
int a[]={1,5,125};

void loop() {
  // put your main code here, to run repeatedly:
if(otp==1){
  senddata;
  otp=0;
}
}

void senddata(){
   int i;
   mySerial.print("<");
   for(i=0;i<sizeof(a)/sizeof(a[0]);i++){
      mySerial.print(a[i]);
      mySerial.print(",");
    
   }
   mySerial.print(">");
}
//receiving
#include <SoftwareSerial.h>

SoftwareSerial mySerial(5,6);  //rx pin,tx pin

char recvchars[32];
boolean newdata=false;

void setup() {
  // put your setup code here, to run once:
mySerial.begin(9600);
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
recvdata();
Serial.print(recvchars);
delay(1000);
}
void recvdata(){
  static boolean recvinprogress=false;
  static byte ndx=0;
  char startmarker='<';
  char comma=',';
  char endmarker='>';
  char c;

  while(mySerial.available()>0 && newdata==false){
    c=mySerial.read();

    if(c==startmarker)recvinprogress=true;

    else if(c==endmarker){
      recvinprogress=false;
      ndx=0;
      newdata=true;
    }
    if(recvinprogress==true && c!=comma){
      recvchars[ndx]=c;
      ndx++;  
    }
    
    
  }
}
  senddata;

That is NOT calling the function. Function calls need parentheses, even when there is nothing to pass to the function (like Serial.read()).

So silly of me to have missed that out ! works perfectly now! Thnx!

Guys - lots of flaws in the code posted so far. First of all you are mixing string with binary. The first example wrote an int as if it was a string, and without converting it to string. The receiving side would need to parse the result for commas and <> and reassemble the array. The second example sent it as an array of char's. a char is a byte and is signed so your data better be within the value of -128 to +127. If you make it unsigned char, then you have between 0 and 256.

What would be best is to stick with binary. Know the size of the data you are sending - 1,2,4,8 bytes to cover the appropriate range, and plus or minus to determine if the value should be signed or unsigned.

Determine the block size. If you are sending megabytes you might send X blocks of upto 64K-1 (65535). So for example if you are sending blocks of upto 64K you would put a 2 byte header, and maybe a magic byte(s) (I'll explain later).

Magic bytes - these are useful to delineate your block. Your reading side would read 8 bytes. The first two would be, for example 0A 05, then CRC, control bytes and 2 byte length of the subsequent block.
If the first two bytes are NOT 0A 05, you are not in step with the sender, you could flush the incoming data until the line is quiet for say 1 second, then return an error.

0A 05 = magic bytes, I choose this because A = 1010 and 5 = 0101.
You might put a CRC or Checksum to validate the data since serial can get garbled.
FE 01 = control bytes - one bit set to tell the receiver this is the last block.
FF FF = 65535 - bytes.
amount of Data
Potentially a trailing magic number sequence - should be different from the start magic bytes.

This assures the reading side that it got a good block. The receiving side throws away everything except the data and keeps appending the data until the last block is read.

Note that the Control Bytes are a reverse image of each other. FE xor FF = 01. 01 xor FF = FE. This is a validation that your control byte is valid and not garbled. The CRC over the block is a second, and more important validation.

Since your array has no delimeters, reading it directly into memory is easy and fast (no processing). But the crc does require you to run through the array to validate the crc numbers match - otherwise the array or the crc is corrupt.

I know this sounds like alot, but write it once, and use it often. This is not anything new. Since serial is so prone to garbage, you need to know when that occurs, or your code will not work properly and it'll just drive you nuts. Leave CRC out until the end. But add it once you have communications working. Any developer who ignores error checking is not a developer. I consider it half the job.

Test this with USB serial - USB already has within the low level code all the validation, so it will automatically resend any data that is corrupted. When you use serial - without USB, none of that is done. So write initially using the USB connection and serial over USB. If you only ever need serial over USB, then remove all the error check and simply write the array with 2, 4 or 8 length bytes at the start of the array.

I can put together some code if you want, but I'm sure it's available in the open source since this is not new stuff. After a very quick search here is one example that just shows how to write a buffer:
https://blog.manash.me/serial-communication-with-an-arduino-using-c-on-windows-d08710186498

There is actually ONE issue with the above. If you want to send 64K per block, my length only allows 0..64K -1. So you could mandate that you can not send zero bytes. Then add one to the length on the receiving side. So a length of 0 means 1 to the receiver. (Why would you want to send zero bytes?)

JustGoFly:
What would be best is to stick with binary.

I disagree strongly.

Sending data in human readable format makes debugging very much easier. I would only send binary data if I had no option for performance reasons.

There is a mechanism for sending binary data with start- and end-markers at the start of this Python - Arduino demo. There is another approach in this Python Binary Data demo.

...R

The first example wrote an int as if it was a string, and without converting it to string.

What rubbish. You CLEARLY haven't a clue what print() does.

Having a strange and funny problem. For the ease of retrieving my array later on, instead of sending the actual numbers ,I am sending the reverses. Everything is working fine. But , for 3-digit integers , the integer after retrieval from string at receiver , gets reduced by 1. No clue what is going on!!!!

//sending
#include <SoftwareSerial.h>
#include <math.h>

SoftwareSerial mySerial(5,6); //rx pin,tx pin

void setup() {
  // put your setup code here, to run once:
mySerial.begin(28800);
}
int otp=1;
int a[]={rev(1),rev(5),rev(125)};

void loop() {
  // put your main code here, to run repeatedly:
if(otp==1){
  senddata();
  otp=0;
}
}

void senddata(){
   int i;
   mySerial.print("<");
   for(i=0;i<sizeof(a)/sizeof(a[0]);i++){
      mySerial.print(a[i]);
      mySerial.print(",");
    
   }
   mySerial.print(">");
}
int rev(int n){
  
  int i,reverse=0;
  while(n>0){
    int rem=n%10;
    reverse=reverse*10+rem;
    n=n/10;
  }
  return reverse;
}
//receiving
#include <SoftwareSerial.h>
#include <math.h>

SoftwareSerial mySerial(5,6);  //rx pin,tx pin

char recvchars[32];
boolean newdata=false;
int dataarray[3];

void setup() {
  // put your setup code here, to run once:
mySerial.begin(28800);
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
if(newdata==false){
  recvdata();

/*Serial.print(recvchars);
Serial.print("\n");
delay(100);

readintonum(recvchars,dataarray);
int i;
for(i=0;i<3;i++){
  Serial.println(dataarray[i]);*/
}


} 


void recvdata(){
  static boolean recvinprogress=false;
  static byte ndx=0;
  char startmarker='<';
  char comma=',';
  char endmarker='>';
  char c;

  while(mySerial.available()>0 && newdata==false){
    c=mySerial.read();

    if(c==startmarker)recvinprogress=true;

    else if(c==endmarker){
      recvchars[ndx]=c;
      recvinprogress=false;
      ndx=0;
      newdata=true;
    }
    if(recvinprogress==true){
      recvchars[ndx]=c;
      ndx++;  
    }
    
    
  }

  Serial.print(recvchars);
Serial.print("\n");
delay(100);

readintonum(recvchars,dataarray);
int i;
for(i=0;i<3;i++){
  Serial.println(dataarray[i]);
}
delay(100);
}

void readintonum(char* recvchars,int* dataarray){
  int i,count=0,num=0,arraycount=0;
  boolean started=false;
  for(i=0;i<32;i++){
     if(recvchars[i]=='<')started=true;
       
     if((started==true)&&(recvchars[i]==',')){
      count=0;
      dataarray[arraycount]=num;
      arraycount++;
      num=0;
     }
     if((started==true)&&(recvchars[i]>=48)&&(recvchars[i]<=57)){
         num=num+pow(10,count)*(recvchars[i]-48);
         count++;
     }
     if((started==true)&&(recvchars[i]=='>'))break;
  }
  return;
}

Sorry , in code 1 , a[2]=rev(225), not 125. The output obtained is 224.

sen_diptangshu:
Having a strange and funny problem. For the ease of retrieving my array later on, instead of sending the actual numbers ,I am sending the reverses.

I don't understand. Can you give some examples?

...R

Let me explain. values to be sent =1,5,225.
values I send in array a[]={rev(1),rev(5),rev(225)}={1,5,522}
receiver receives a[] as string . It parses the string and extracts numbers. But the numbers are 1,5,224. For any number consisting of 3 digits or more , the same thing happens,value gets reduced by 1.I have enclosed the output on the serial monitor of the receiver . Plz see it for reference.

sen_diptangshu:
Let me explain. values to be sent =1,5,225.

I should have been more specific. I want to see an example of what is received when you send that.

...R

Plz go through the following attachment .

Image from Reply #17 so we don't have to download it. See this Image Guide

...R

As you can see your image is unreadable. Please don't post pictures of text. Just copy and paste the text.

...R