Go Down

Topic: Extracting Data from SoftwareSerial (Read 1 time) previous topic - next topic

ahhreeyell

If I have an array of values being sent to me through the Software Serial library, and I want to extract the array so that I can use those values (i.e. for something such as mapping them to a servo), how would I go about doing that?

mrburnette

The Serial class has methods to accomplish parsing from a delimited ASCII stream:

http://arduino.cc/en/Reference/Serial

See: parseInt() and parseFloat()

There are numerous other ways to accomplish this, too.


PeterH


I have an array of values being sent to me through the Software Serial library


You need to know how the values are encoded, and then read the bytes from SoftwareSerial and decode them to get back the original values. How you do this would depend how they have been encoded.
I only provide help via the forum - please do not contact me for private consultancy.

tigerbomb8

It would be easier to help if you could supply some example input..

mrburnette

#4
Sep 03, 2013, 03:15 am Last Edit: Sep 03, 2013, 03:19 am by mrburnette Reason: 1
I agree with PeterH
Quote
You need to know how the values are encoded, and then read the bytes from SoftwareSerial and decode them to get back the original values.


By convention, the only way this makes sense is if the receiving array matches the type/size of the sending array. Then an agreement via handshaking dumps the array from the sending side to the receiving side over serial, looping element by element.  Delimiting each element allows the receiver to extract and store the received value.  One can only surmise that the array positions are meaningful to the receiver; ex. Array[5] perhaps representing a servo movement.

If the array is of type int, then Serial.parseInt() will suffice as would Serial.parseFloat if the array element were of type Float.  

Sending arbitrary updates from array to array only requires a syntax such as <element, delimiter, value>

The value add here would be enhancement for checksums or advanced handshaking prior to the received value being stored and utilized.


Ray

ahhreeyell

tigerbomb8:

To answer your question, I'm using two Arduinos, and each one has a GPRS shield. The first Arduino has an FSR (force-sensing resistor--basically a pressure sensor) attached to it, and I'm storing the values it produces when it's squeezed into an array. I then send the array of values to the other Arduino, using the SoftwareSerial library. I will need to parse those values so that I can map them to a servo and make the servo rotate a corresponding number of degrees.

Did all that make sense? If I wasn't clear, or you need more information, please tell me.

In terms of an output example, the values are between 125 and 250, and they are separated by a newline character, so they are all on separate lines. So an output example is always going to be a list of values between those two numbers, and it will never be more than 100 values, because I have the maximum value of the array set to 100.

ahhreeyell

mrbrunette: Unless I am mistaken, it seems as though that library is for Serial, not SoftwareSerial. Do you know of a similar library/commands for SoftwareSerial?

mrburnette

@ahhreeyell:

According to PaulS on this post:http://forum.arduino.cc/index.php?topic=185122.msg1371154#msg1371154

Quote

   
Re: 'class SoftwareSerial' has no member named 'parseInt'
« Reply #2 on: August 29, 2013, 04:28:30 am »

What version of the IDE are you using? Prior to 1.0, SoftwareSerial derived from a different base class that did not have a parseInt() method.


So, I'm betting with PaulS that it will work... Op on the other post indicated it worked on ATtiny with the arduino-tiny core.  But, I have not gone down to the Lab this morning to recompile a test to verify... maybe after another cup of coffee... maybe.


Ray

Robin2

I'm not sure if this will help, but I only figured it out yesterday - my knowledge of C, C++ is very limited. It would have saved me a lot of time with several sketches if I had a found a tutorial about this.

I define a struct with the variables I am expecting to receive - for example

Code: [Select]
struct testStruct {
  int val1;
  int val2;
  long val3;
  int val4[8];
};


This struct will take up 2 + 2 + 4 + 2*8 = 24 bytes

I then create a union that "connects" that struct with an array of bytes (make it a bit bigger for safety)

Code: [Select]
union testUnion {
  byte dataReceived[26];
  testStruct dataVals;
};


Now I can receive the data (in my case from my PC) into the dataReceived array and read it properly formatted from the struct, for example

Code: [Select]
int recVal1 = dataVals.val1;

By the way I haven't tested this code, but it's just like my working code.

...R

PeterH

When receiving messages like that, make sure you have some way to determine where each messages starts and ends. It's entirely possible for the serial interface to lose a byte, and if this happened all the subsequent messages would be misaligned with your data structure. If you can identify a byte sequence which you know will not appear in the message, you could use that as a marker. But, however you do it, you need to have a way to work out where each message starts and ends which does not rely on the sender and receiver staying perfectly synchronised.
I only provide help via the forum - please do not contact me for private consultancy.

Robin2

Agreed.

I should have said that I prefix my data with a "C" (just because I felt like it) so the Arduino doesn't start saving bytes until the C is received. Then I send an "F" after the data. Because it's binary data there is no single character that will never ever appear in the data so my Arduino code reads the expected number of data bytes and expects the next byte after that to be an "F". If it's not an F the whole transmission is ignored.

If I was sending ascii characters I would probably use the byte 254 to mark the start and 255 to mark the end knowing that neither of these would ever be part of the ascii data.

...R

PaulS

Quote
This struct will take up 2 + 2 + 4 + 2*8 = 24 bytes

No. It will take up AT LEAST 24 bytes. The compiler is free to pad the struct as much as it wants. That probably won't happen on the Arduino, but it is never safe to assume that the struct size matches the size of the objects in the struct.

PeterH


I should have said that I prefix my data with a "C" (just because I felt like it) so the Arduino doesn't start saving bytes until the C is received. Then I send an "F" after the data. Because it's binary data there is no single character that will never ever appear in the data so my Arduino code reads the expected number of data bytes and expects the next byte after that to be an "F". If it's not an F the whole transmission is ignored.


That's a good scheme.
I only provide help via the forum - please do not contact me for private consultancy.

Robin2

Thanks for this explanation. Based on experience I did suggest in my earlier post that the byte array be made longer than the struct as I got stung with very strange behaviour when the data going into the array overwrote the variable after the Union - however I thought (when the problem occurred) that I actually (accidentally) had the array smaller than the struct. The facts are now lost in the great cloud of deleted code.

...R


Quote
This struct will take up 2 + 2 + 4 + 2*8 = 24 bytes

No. It will take up AT LEAST 24 bytes. The compiler is free to pad the struct as much as it wants. That probably won't happen on the Arduino, but it is never safe to assume that the struct size matches the size of the objects in the struct.

Nick Gammon


Agreed.

I should have said that I prefix my data with a "C" (just because I felt like it) so the Arduino doesn't start saving bytes until the C is received. Then I send an "F" after the data. Because it's binary data there is no single character that will never ever appear in the data so my Arduino code reads the expected number of data bytes and expects the next byte after that to be an "F". If it's not an F the whole transmission is ignored.


Since 'C' is 67 in ASCII, let's hope val1, val2, val3 or val4 never contain the number 67. And don't get me started on the 'F' part. :)
http://www.gammon.com.au/electronics

Go Up