1
Vote

RS232 communication is not synchronized

description

From what I found currently the driver will pull the data untill the read buffor is full and then fire an event to process this data. However there is no synchronization with the input so very often begining of the buffor doesn't align with begining of the message.

I added some tracing to help me debug this. If you look at attached screenshot you will see that buffer always contains 52 bytes. For 3-axis acceleerometer my Arduino sketch sends 15 bytes starting with 934 header and as you can see these bytes are repeated somewhere in the middle of the buffer.
 
Obviously this causes to loose lots of readings or some readings being reported not correctly as different devices.

I found that the RS232 code can be configured to send events when specific character is recognized in input (for example \0 or \n) but I'm not sure how to rewrite the driver to take advantage of this http://msdn.microsoft.com/en-us/library/ms810467.aspx. Another soultion would be to implement simple state-machine parser and look for synchronization characters in the input stream. As I said before I would also like to change the format to be more user friendly and use coma delimited fields and variable length messages.

file attachments

comments

bjepson wrote Jan 21, 2010 at 2:49 AM

Donn had a couple of thoughts/questions on this:

1) The driver uses a 2400 baud connection in its default configuration. (This was due to a limitation with the BS2.) What baud rate are you using on the Arduino, and, is it possible that the driver baud rate needs to be synchronized with the Arduino?

The baud rate for the driver is set in RS232Connection.cpp in the RS232Connection() constructor (see below):

RS232Connection::RS232Connection()
{
//
// initialize generial TTY info
//
m_hCommPort = NULL;
m_fConnected = FALSE;
m_fLocalEcho = FALSE;
m_bPort = 1;
m_dwBaudRate = CBR_2400; // <<<<<<<
m_bByteSize = 8;
m_bParity = NOPARITY;
m_bStopBits = ONESTOPBIT;
m_fAutowrap = TRUE;
m_fNewLine = FALSE;
m_fDisplayErrors = TRUE;
And, 2) I’d experimented with the COMMTIMEOUTS value that we pass to the SetCommTimeouts method (same module). If memory serves, I’d observed something similar to what you are observing when COMMTIMEOUTs was set to certain values. (It’s been quite awhile since I’d touched this code; may need to look close in the debugger with your sources.)

kobush wrote Jan 21, 2010 at 6:46 AM

I tried other baud rates - currently it works at 9600. I didn't made any changes to COMMTIMEOUTS.
Maybe increasing the baud rate made the problem visible because now connection doesn't timeout before receiving more than one reading to the buffer. But still I think we should implement better handling not relaying on comm timeouts but actually parsing the incomming data stream.

I think that utilizing the WaitCommEvent function to capture the packet termination character should be good solution for now.

kobush wrote Jan 23, 2010 at 6:11 AM

I tried reducing the baud rate back to 2400 but thid didn't help. I can see that the RS232 connection is waiting to fill the whole data buffor before sending it to SensorBaseDriver::ProcessReadData.

kobush wrote Jan 23, 2010 at 7:37 AM

However when I changed the update rate in the sensor from 100ms to 200ms it started working. I checked the value of COMMTIMEOUTS and it's currently set to 120ms. So it will now timeout before receiving another update from the sensor. I updated the Basic_WiiNunchuck sample to report in 150ms intervals.

I still think this implementation is not optimal and will try to implement proper parsing from buffered data.

bjepson wrote Jan 24, 2010 at 12:39 AM

Donn had some more ideas about this:

In looking through the driver source, I noticed that I hadn’t set the EofChar in the DCB structure. There’s scant documentation for this member, but, the docs imply that it can be used to signal the end of data (http://msdn.microsoft.com/en-us/library/aa363214(VS.85).aspx)

So, I set EofChar to ‘\0’, extended the length of the packets by one additional character in RS232Connection.h, and modified the firmware to send a NUL at the end of each packet.

The following listings shows the results; note that rather than waiting for the buffer fill-up (as was happening prior to setting EofChar), we now see far less data in the buffer. (The new issue appears to be bytes dropping off of the “front” of the packet. So, in the first instance, we see the last seven bytes “0200100”; but, we’ve lost first seven “6161000”. I’m wondering if this is a timing issue that can be resolved with the correct COMMTIMEOUTS setting.)

Below is a log of output generated via Tracepoints in Visual Studio; I’m tracing the values of hrStatus and m_pReadBuffer within the call to RS232Target::OnCompletion.

** Readbuff (EofChar is NUL in driver)

!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 "0200100"
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 ""
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 "00200100"
!hrStatus: 268435714
!m_pReadBuffer: 0x00215bf8 "0"
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 "61610000200100"
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 "0100100"
!hrStatus: 268435714
!m_pReadBuffer: 0x00215bf8 ""
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 "61610000100100"
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 "0100100"
!hrStatus: 268435714
!m_pReadBuffer: 0x00215bf8 ""
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 "61610000100100"
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 "0100100"
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 ""
!hrStatus: 268435714
!m_pReadBuffer: 0x00215bf8 "00200100"
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 "61610000100100"
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 "0100100"
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 ""
!hrStatus: 268435714
!m_pReadBuffer: 0x00215bf8 "00100100"
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 "61610000100100"
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 "0200100"
!hrStatus: 268435714
!m_pReadBuffer: 0x00215bf8 ""
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 "61610000200100"
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 "0200100"
!hrStatus: 268435714
!m_pReadBuffer: 0x00215bf8 ""
!hrStatus: S_OK
!m_pReadBuffer: 0x00215bf8 "61610000200100"

**Readbuff (EofChar not set in driver)

!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "6161010010010061610100000100616101001001006161010010XW"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "0100616101000001006161010000010061610100100100616101XW"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "0000010061610200000100616101000001006161010000010061XW"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "6101000001006161020010010061610100000100616101000001XW"
!hrStatus: 268435714
!m_pReadBuffer: 0x001b5bf8 "006161010000010061610100000100"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "6161010010010061610100000100616101000001006161010010XW"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "0100616101000001006161020010010061610100000100616101XW"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "0000010061610100000100616101000001006161010000010061XW"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "6101000001006161010010010061610100000100616101000001XW"
!hrStatus: 268435714
!m_pReadBuffer: 0x001b5bf8 "0061610100000100"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "6161010000010061610100000100616101000001006161010000XW"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "0100616102001001006161010010010061610100100100616101XW"
!hrStatus: 268435714
!m_pReadBuffer: 0x001b5bf8 "0000010061610100000100"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "6161010000010061610100000100616101000001006161010000XW"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "0100616101000001006161020000010061610100100100616102XW"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "0010010061610100100100616101000001006161010000010061XW"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "6101000001006161020010010061610100100100616101001001XW"
!hrStatus: 268435714
!m_pReadBuffer: 0x001b5bf8 "006161010010010061610100000100"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "6161010000010061610200000100616101000001006161010000XW"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "0100616101001001006161010000010061610100000100616101XW"
!hrStatus: S_OK
!m_pReadBuffer: 0x001b5bf8 "0000010061610100000100616101000001006161010000010061XW"
The program '[5820] WUDFHost.exe: Native' has exited with code 0 (0x0).

donnm wrote Jan 30, 2010 at 10:32 PM

I believe we've solved the issue here by: 1) Running at 9600 baud, 2) Setting the EofChar in the DCB structure, 3) Extending the length of the packet size by one byte (to account for the EofChar), 4) Adjusting the COMMTIMEOUTS.ReadIntervalTimeout, and 5) Updating the firmware to send the EofChar as the last byte in each packet.

donnm wrote Jan 30, 2010 at 10:46 PM

I'm attaching a screenshot that shows trace output for a 2-axis Memsic accelerometer in Visual Studio.

wrote Jan 30, 2010 at 10:46 PM

wrote Feb 13, 2013 at 3:20 AM