LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Serial Read Binary Data - every few ms wrong data

waveform_output.PNGwaveform_recorder.pngHi,

 

every few milliseconds the data I receive via USB seems to have wrong data. I should see continuously 4 ramp signals (see code below). But I am seeing the ramp signals for a few milliseconds and then some garbage data and then the ramp signal again (compare the screenshot below)...

 

The example was based on https://forum.arduino.cc/t/arduino-due-native-usb-communication-serialusb/366130/3

 

Any ideas?

 

Arduino Code:

 

int x,b,i; uint16_t buf[4][256];

void setup() {  SerialUSB.begin(0);

  while(!SerialUSB);

  for(b=0; b<=3; b++)

     for(i = 0; i < 256; i++)  

      buf[b][i] = (uint16_t)i*(b+1)*32; }

 

void loop()

{  

SerialUSB.write((uint8_t*)buf[b], 512);

  b=(b+1)&3;

 delay(125);

}

 

 

 

 

 

 

 

Download All
0 Kudos
Message 1 of 9
(3,240 Views)

Hi bug,

 

don't use BytesAtPort when you know the number of bytes in the message!

Don't enable a TermChar for raw/binary data in the message!

Why use typecast when there is StringToU8Array?

Why swap bytes in a byte array???

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
0 Kudos
Message 2 of 9
(3,207 Views)

Oh, where to begin...

 

1. You are dealing with raw/binary/hex data.  Therefore, you need to disable the Termination Character.  You specifically have a TRUE wired to the enable for that.  Just change it to a FALSE.

2. DO NOT USE THE BYTES AT PORT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! (still not enough emphasis).  You are just introducing a race condition by using the Bytes At Port to tell the VISA Read how many bytes to read.  It will very quickly lead to an unsynchronization of the data.

3. You need a framing around your data so the receiver can make sure it is getting the right data in the right place.  My recommendation is to send 0x2 to start your frame, followed by the data, and then a checksum of some type (CRC or a simple U16 addition of the words being written).  Then on the LabVIEW side, you can just read 1 byte at a time until the 0x2 is read.  You can then read the rest of the message and verify the checksum.  If the checksum passes, you do whatever you need to with the data.  If it fails, throw out what you read (left to assume a bad or incorrect frame).

4. Use Unflatten From String to convert your data to a U16 array.  The Unflatten From String has an input to set the Endianness, so you won't need to handle the "Swap Bytes" either.

 

For more details, go watch this: VIWeek 2020/Proper way to communicate over serial



There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 3 of 9
(3,205 Views)

You generate an array of uint16 values, then transmit it over serial port and read it in LabVIEW as uint8 and leave it at that. Where oh where is here any discrepancy?????

 

Most likely you did that as you get otherwise strange artefacts from using Bytes at Serial Port, which can cut off your data mid word and then cause trouble. Bytes at Serial port is almost always the wrong thing to use and here too. Since you write the data in blocks of 512 bytes you should simply let the LabVIEW VI read that much of bytes too in each VISA Read and then convert it properly back to uint16 values.

 

But since the Arduino uses Little Endian byte order you should NOT use the Typecast function to do that. The LabVIEW Typecast always assumes Big Endian byte order. Instead you should use the Unflatten from String function where you can select what Endianness the byte stream side (string) is in.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 4 of 9
(3,203 Views)

Am I the only one who caught the timing? A delay 125 in the Arduino, Wait 100msec in the read loop. Guaranteed to upset any synchronization for bytes at port.

 

Crossrulz which one of the 255 ASCII characters is going to not be found in a valid U16?  Yeah, the read is going to have to be on count! Read 512 Char 

 

Read 512 char.  Sett tmo just above the Arduino delay to error when the arduino stops), string to U8 array, decimate array(2) join numbers U8 to U16.


"Should be" isn't "Is" -Jay
0 Kudos
Message 5 of 9
(3,187 Views)

@JÞB wrote:

Crossrulz which one of the 255 ASCII characters is going to not be found in a valid U16?  Yeah, the read is going to have to be on count! Read 512 Char 

 

Read 512 char.  Sett tmo just above the Arduino delay to error when the arduino stops), string to U8 array, decimate array(2) join numbers U8 to U16.


1. How can you prove that the fist byte you read is actually the first byte of a word?  You can't.  So you need some type of synchronization.  Sure, you could use a longer synchronization word.  I have seen 32-bit words used as the message header and then all of the data after that.  My advice wouldn't change much.  I would read 1 byte at a time until the first byte of the header word is read.  Then read the rest of the header (3 bytes using my 32-bit sync word example).  If those 3 bytes match, then read the 1024 bytes (512 U16 values) of data.

 

2. The Unflatten From String takes care of the String To Byte Array, Decimate Array, and the Join Numbers all in a single node.  For this application, set the Byte Order input to Little Endian, the Include Array Size to FALSE, and the data type as an array of U16.  Don't make things more complicated than necessary.



There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 6 of 9
(3,181 Views)

Thank you big time for your input!

 

I implemented from what you suggested and it works to most extent but for a few glitches. As you may see from the data you may notice in the beginning of each ramp some glitches...

 

I have not implemented your proposal from number 3, yet. Maybe this will remove the remaining glitches, too. Do you have though any simpler means? According to the thread from the Arduino forum it was working without a checksum or termination character ( https://forum.arduino.cc/t/arduino-due-native-usb-communication-serialusb/366130/3 ) .

 

Thanks - Peter

 

 

OutputOutputsnippetsnippet

0 Kudos
Message 7 of 9
(3,170 Views)

Why are you reading 8 bytes for a 2 byte word?  The data type for the Unflatten From String should be an array of U16 values.

 


@BugMeNont wrote:

I have not implemented your proposal from number 3, yet. Maybe this will remove the remaining glitches, too. Do you have though any simpler means? According to the thread from the Arduino forum it was working without a checksum or termination character ( https://forum.arduino.cc/t/arduino-due-native-usb-communication-serialusb/366130/3 ) .


Basic communication theory: you have to have a way to sync up your messages and/or prove the data is correct.  Go back to my last post.  There I suggested a U32 header word that you need to verify before you can trust the rest of the data you have (barring flipped bits or dropped bytes by the transmission process).  That is the simplest method I know to give a reasonable amount of confidence for a streamed, raw/binary/hex, homogeneous data frame (all messages are the same).



There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 8 of 9
(3,141 Views)

@crossrulz wrote:

Why are you reading 8 bytes for a 2 byte word?  The data type for the Unflatten From String should be an array of U16 values.

 


@BugMeNont wrote:

I have not implemented your proposal from number 3, yet. Maybe this will remove the remaining glitches, too. Do you have though any simpler means? According to the thread from the Arduino forum it was working without a checksum or termination character ( https://forum.arduino.cc/t/arduino-due-native-usb-communication-serialusb/366130/3 ) .


Basic communication theory: you have to have a way to sync up your messages and/or prove the data is correct.  Go back to my last post.  There I suggested a U32 header word that you need to verify before you can trust the rest of the data you have (barring flipped bits or dropped bytes by the transmission process).  That is the simplest method I know to give a reasonable amount of confidence for a streamed, raw/binary/hex, homogeneous data frame (all messages are the same).


Since the write to the serial buffer is always size 512 (that may be a bug as a 4x256 array of int16 would be 1024 bytes) all that is really needed for synchronization is to flush the buffer.  The open should handle that housekeeping task.  A double check for the expected warning that 1024 char were returned from the read and no timeout occurred is satisfactory.   

 

Again, Read the whole expected Buffer size setting the timeout to slightly above the 125ms delay in the Arduino code.  Remove the wait in the read loop.

 

There may still be a row|col swap since some languages are col|row.  Easy fix on either end once we see U16s coming across of the expected buffer size.

 

A U32 header doesn't really help either for raw data.  HOWEVER, I have worked on systems that will reserve 0xFF as a sync byte and Coerce  FFFF to FEFF BE in the data so your Arduino code could simple add a Coerce and send FFFF prepended to buf[ ] and a checksum and then LabVIEW could use Tim's method safely even when the eye closes(transmition bit error.) 


"Should be" isn't "Is" -Jay
0 Kudos
Message 9 of 9
(3,118 Views)