Go Down

Topic: Formatting an array for serial communication (Read 378 times) previous topic - next topic

mrExplore

Hi all,

I have a programming challenge. I have an array that needs to be sent over serial.
But on the recieving side, for real time data display, I need to process the entire array in ONE read:

socket.readUTFBytes(50)     (where 50 is the number of bytes to read from the buffer)


So let's say my array is:                                                 
[115,1278,47]
UTF8 bytes are sent over serial by arduino, one by one
To let the reciever decode the data I send it like this:         
S V 1 1 5 V 1 2 7 8 V 4 7
Wher S marks the start and V marks a value. The reciever now analyses EACH character one by one, this is way too slow.


What I would like to do instead is send:
S 0 1 1 5 1 2 7 8 0 0 4 7

(0115 = 115, 1278 = 1278, 0047 = 47)

The S to mark the start is still needed.

But the data would now have a fixed length in bytes and I could say:
socket.readUTFBytes(13)


What would be the best way to have the arduino send out
S 0 1 1 5 1 2 7 8 0 0 4 7  when the array is [115,1278,47] ?


Thanks for reading !

Robin2

I can't say I understand the problem you are trying to solve (or avoid).

What is receiving the data?

A common way to send data is as Comma Separated Values - for example <115,1278,47> with the <> marking the start and end of the message. That format is very easy to parse - see the parse example in Serial Input Basics

You could send the data in binary format but that makes the debugging a lot more difficult. For example if your three numbers are in an array
Code: [Select]
int testArray[3] = {115, 1278, 47};
Serial.write(&testArray, sizeof(testArray));

but  that very simple code does not have start- and end-markers so it is easy for the receiver to get mixed up. And if the receiver is a different type of computer you will need to consider whether it is little-endian (like an Arduino) or big-endian.

...R

 
Two or three hours spent thinking and reading documentation solves most programming problems.

wildbill

You can use sprintf to format integers with leading zeroes. The format string would be "%04d"

mrExplore

Thanks for the tips, The following solution works for me now:

Code: [Select]
    strToAs3 = "";    //clear the string to send

    for (int s = 0 ; s < intNumberOfRanges ; s++) {         //intNumberOfRanges is the length of the array

      int intValue = arrOutput[s];
     
      String strValue = String(intValue);
       
      int Length = strValue.length();
     
      if(Length == 1){
        strValue = "000" + strValue;
      }
      if(Length == 2){
        strValue = "00" + strValue;
      }
      if(Length == 3){
        strValue = "0" + strValue;
      }
     
      strToAs3 = strToAs3 + strValue;

    }//end for

    Serial.print("S");
    Serial.println(strToAs3);

aarg

If this is a school assignment, great. But the String class is not reliable on a tiny system like the AVR micro.
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

mrExplore

Thanks for mentioning that. It's not a school assignment btw
I'm trying to build a light reactive led strip, one arduino does the FHT analyses, the result goes to another arduino that does the light effects.

I would like to take it a step further now.

I have an arduino uno doing FHT frequency analyses. The result of the analyses is an array:
fht_log_out[] that holds 128 values

Now I would like to send to send this array to an arduino mega. What would be the way to go when not using the string method ?

aarg

#6
Jan 14, 2018, 02:58 pm Last Edit: Jan 14, 2018, 03:05 pm by aarg
What communication method are you going to use between the Uno and the Mega?

The cstring method was the original way of handling strings, long before the String class was even dreamed of. It uses char arrays. Here are the functions you will use:
http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html

But, for communication efficiency, it would behoove you to abandon the idea of sending fixed length ASCII numbers and send raw binary values instead.
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

mrExplore

#7
Jan 14, 2018, 03:07 pm Last Edit: Jan 14, 2018, 03:13 pm by mrExplore
Well, i was thinking of just connecting the tx/rx on both boards.
The link you give, looks a bit above my level to be honest.

It does not have to be a string per se, the goal is to get that array from one arduino to the other :)
So one array containing 128 values between 0 and 999.

Robin2

It does not have to be a string per se, the goal is to get that array from one arduino to the other :)
So one array containing 128 values between 0 and 999.
I mentioned two different approaches in Reply #1

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

mrExplore


aarg

Have you done calculations on the desired update rate for the LED's? 128 values is quite a lot, even at a high baud rate like 115200.
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

CrossRoads

"one array containing 128 values between 0 and 999."
That's going to use a 256 byte array of ints to accomodate 256 to 999.
int dataArray[128];

Then just send it, but not too fast so that the receive side can capture the data and put it in an array. Maybe something like this:
Code: [Select]

Sending:
Serial.write ("s");
for (x=0; x<128; x=x+1){
Serial.write (lowByte(dataArray[x]);
Serial.write (highByte(dataArray[x]);
}

Receive side
if (readingData == 0 && Serial.available()>0){ // see if "s" came in
if (Serial.read() == "s"){
readingData = 1;
index = 0;
}
else {
readingData = 0;
}
if (readingData == 1 && Serial.available() >0){  // "s" came in, save the data that follows
incomingArray[index] = Serial.read();
index = index+1;
}
if (index == 256){
readingData = 0;
// captured all data, now use word() to turn them back into ints
for (x=0; x<255; x=x+2){
intArray[x] = word(incomingArray[x+1], incomingArray[x]); // combine locations 1,0 into an int, then 3,2 ... 255,254
}


Make sense?


Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

mrExplore

Thanks for your input guys, I'm going back to the drawing board.

Two arduino's, one doing FFT/FHT, additional serial communication, this is a bit over my head :(

I'll focus on using an msgeq7 now.


Thanks anyway !

Robin2

Two arduino's, one doing FFT/FHT, additional serial communication, this is a bit over my head :(
If FFT has anything to do with Fourier Transformations then IMHO serial communication is great deal simpler :)

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Go Up