USB Serial 2 - errors

Stulish

Active Member
Licensed User
Longtime User
Hi all i am playing with the USB to serial lib, has anyone else found errors cropping up, for instance some of the data getting mixed up and put in the wrong place within the input stream.

I have been sending:

$PAMIV,01,100,100,100,100*6E
$PAMIV,02,50,0,10,0*69

every second at 4800 baud continuously for a few minutes

i put a try/catch statement in my code to see what was being sent, most of the time it seems fine but i received the following catch errors:

------------------------------------------------------------------------
Error Occurred: 05/12/2013 @ 13:53:03

NMEA: $1,100,100,100,100*6E
Buffer: PAMIV,0$1,100,100,100,100*6E
------------------------------------------------------------------------
Error Occurred: 05/12/2013 @ 13:54:20

NMEA: $PAMIV,01,100,100*6E
Buffer: $PAMIV,01,100,100*6E

$
------------------------------------------------------------------------
Error Occurred: 05/12/2013 @ 13:54:20

NMEA: $0,100,10PAMIV,02,50,0,10,0*69
Buffer: $0,100,10PAMIV,02,50,0,10,0*69
------------------------------------------------------------------------
Error Occurred: 05/12/2013 @ 13:56:16

NMEA: $PAMIV,01,100,100,100,100*MIV,02,56E
Buffer: $PAMIV,01,100,100,100,100*MIV,02,56E

$PA
------------------------------------------------------------------------
Error Occurred: 05/12/2013 @ 13:56:17

NMEA: $PAMIV,01,100,100,100,100MIV,02,*6E
Buffer: $PAMIV,01,100,100,100,100MIV,02,*6E

$PA
------------------------------------------------------------------------
Error Occurred: 05/12/2013 @ 13:56:20

NMEA: $PAMIV,01,100,100,100,100*MIV,02,6E
Buffer: $PAMIV,01,100,100,100,100*MIV,02,6E

$PA

Is this a problem with the library , i have output from one serial port to another on the PC and there are no errors over the same period.

I use NMEAinBuff to store what has arrived just in case a full sentence has not been received, below is the Astreams_Newdata sub:

B4X:
Sub Astreams_NewData (Buffer() As Byte)
   Dim lp As Boolean = True 
   Dim s1, s2 As Int 
   NMEAinBuff.Append(BytesToString(Buffer, 0, Buffer.Length, "UTF8"))
   s2 = NMEAinBuff.ToString.IndexOf(CRLF)
   s1 = NMEAinBuff.ToString.IndexOf("$")
   If s1<>-1 AND s2<>-1 AND s2>s1 Then 
      Do While lp
         Dim tempString,TS As String, retInt As Int 
         tempString = NMEAinBuff.ToString 
         retInt = tempString.IndexOf(CRLF)
         If retInt<>-1 AND retInt>8 Then 
            checkNMEA(tempString.SubString2(0,retInt-1))
            USBIN.Text = TS
            NMEAinBuff.remove(0,retInt+1)
            lp = True 
         Else
            lp=False
         End If
      Loop 
   Else      'if there is a $ and a CRLF but the start is after the CRLF then remove leading chars
      If s1<>-1 AND s2<>-1 AND s1>s2 Then
         NMEAinBuff.remove(0,s1)
      End If
   End If
End Sub

i am using version 2.3 of the USBSerial Library.

Any thoughts are appreciated.

Regards

Stu
 

agraham

Expert
Licensed User
Longtime User
Neither the library nor AsyncStreams can alter the order of data received and no-one else has reported anything like this. Either you are missing characters entirely (unlikely) or there is a logic error in your Sub Astreams_NewData. For example this looks odd to me

B4X:
checkNMEA(tempString.SubString2(0,retInt-1))
USBIN.Text = TS
NMEAinBuff.remove(0,retInt+1)
You are implicitly assuming the the start of the NMEA sentence is always at the start of the buffer and I'm not sure that it is always so.
 
Upvote 0

Stulish

Active Member
Licensed User
Longtime User
The transmitted sentence starts with $ and ends in CRLF (standard NMEA).

My thoughts were have a variable to hold the received data (NMEAinBuff) and complete the following steps:

1. append any new data as it arrives to the variable.

2. check the variable for a full sentence using indexOf (so if the NMEAinBuff holds a $ and a CRLF and the $ is before the CRLF then it should contain a full sentence).

3. If a full sentence is within the buffer then use the checkNMEA with the portion of the sentence that starts with $ and ends with CRLF.

4. remove the section just used from NMEAinBuff variable.

5. wait for more data to arrive and then carry out the same steps.

So are you saying the data could be received out of sync?

Of am i misunderstanding

thanks

Stu
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
So are you saying the data could be received out of sync?
No, I explicitly stated that neither the library nor AsyncStreams can alter the order of data received. Your stated algorithm is correct, I am questioning the implementation of it. I haven't got time to analyse it but, for example having identified a string between your s1 and s2 indices you pick it out from 0 and retInt-1 which is an implicit assumption that s1 = 0. I m not sure that it true. I would extract the string from s1 to s2and remove 0 to s2 as anything before s1 is irrelevant - might need some off-by-one correction, I can't be bothered to check!
 
Upvote 0

Stulish

Active Member
Licensed User
Longtime User
Sorry Andrew, i didn't realise that's what you meant.

I take everything from 0 instead of S1 because if there is anything before the $ then it will either be the end of an old sentence that it will never get the beginning of or it is corrupt data. either way it is dis-guarded.

Thanks

Stu
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
I take everything from 0 instead of S1 because if there is anything before the $ then it will either be the end of an old sentence that it will never get the beginning of or it is corrupt data.
That's correct for discarding the data but not necessarily for checkNMEA(), if it does what I assume, as it will see the unwanted data - if any.
 
Upvote 0

Stulish

Active Member
Licensed User
Longtime User
The check NMEA sub looks for the $ and then populates views:

B4X:
Sub checkNMEA(TS As String)
   Dim g As Int
   g= TS.IndexOf("$")
   If g<>-1 Then 
      If g>0 Then TS=TS.SubString(g) 'If there is data in front of the $ then remove it
      PopulateNMEAdata(TS)   'display the received NMEA data routine
   End If
      'If no start $ is present even though it ends with CRLF then only 
      'part of the sentence has been received. The full entry will be deleted 

End Sub

But looking back at it i have created 2 subs and made it a bit convoluted when i didn't need too, so i will go back and streamline it better.

Thanks

Stu
 
Upvote 0

Stulish

Active Member
Licensed User
Longtime User
I am starting to think that the errors occur because i have the everything within one activity. and i am wondering if the New Data event occurs while the data is being used and this is what is causing the corruption of data. The reason for this is that the errors are so random, sometimes they can occur 3 or 4 times in as many seconds and at others it will take 4 minutes before one error occurs.

Would it be better to have the USB Serial within a service (if so are there any examples)

Thanks

Stu
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
i am wondering if the New Data event occurs while the data is being used and this is what is causing the corruption of data.
This is not possible as long as the data is only being used by code running on your main thread. The NewData event of AsyncStreams runs on the main thread and so will only run when the thread is not doing anything else. Furthermore AsyncStreams will queue events on the main thread if you don't process them as quickly as they come in so you won't lose data that way either.
 
Upvote 0

Stulish

Active Member
Licensed User
Longtime User
Thanks Andrew,

Like you said i have used the USBSerial Library and no errors occurs, it is only within my app so i must be doing something.

I will keep looking

Thanks

Stu
 
Upvote 0

Stulish

Active Member
Licensed User
Longtime User
Andrew, and anyone else who can help,

I have found the errors occur because i have a timer running, In my app i stopped all timers and there were no errors, as soon as i enable the timer errors occur.

Initially i had the timer set to 250ms, and i generally got about 3 or 4 errors a minute, i have increased the timer to 1s and it is down to about 1 error per minute.

These are totally random occurrence, it must be when the timer kicks in during a astream_newdata event.

My question is does anyone have a way around this?

The timer is used to update the information on the display. The way i have coded there are 5 panels all displaying different information, only the panel that is currently displayed will be updated using a timer, the others will get updated immediately when selected and then use the timer for updates.

Should i look at removing the timer and once a full sentence is received update each panel?

My thought is that this could be a problem with others using timers with astream data.

Regards

Stu
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
it must be when the timer kicks in during a astream_newdata event.
A Timer Tick event cannot run during a NewData event. Both run on the main thread and if either is running when the other comes due the one running will run to completion before the other can start.

Are you using DoEvents in the Timer Tick event, or anywhere else for that matter? If so then try removing them all. DoEvents has the potential to reorder the NewData events on the message queue as it reposts most queued events and so might put an earlier NewData event behind a later one.

Are you manipulating NMEAinBuff anywhere other than in the NewData event? If so then don't.

Try different settings of the UsbTimeout property. Start by increasing it to 1000 and see if that makes any difference.
 
Upvote 0

Stulish

Active Member
Licensed User
Longtime User
Thanks andrew, i will give your ideas a go.

I am not manipulating the NMEAinBuff anywhere else but the astream_newdata sub, i think i have some do events so i will go and have a look at them, once i am back at my PC.

I will also have a look at the time out also. On my app the NMEA stopped receiving data a couple of times when i had left it running for more than 30mins, i created a small app without any other gumph and it ran all night with no stoppages so i am doing something, but i will look at the DoEvents and timeout first.

But thanks for all your support and suggestions

It is appreciated

:)
 
Upvote 0

Rigsby

Member
Licensed User
Longtime User
Andrew, and anyone else who can help,

I have found the errors occur because i have a timer running, In my app i stopped all timers and there were no errors, as soon as i enable the timer errors occur.

Initially i had the timer set to 250ms, and i generally got about 3 or 4 errors a minute, i have increased the timer to 1s and it is down to about 1 error per minute.

These are totally random occurrence, it must be when the timer kicks in during a astream_newdata event.

My question is does anyone have a way around this?

The timer is used to update the information on the display. The way i have coded there are 5 panels all displaying different information, only the panel that is currently displayed will be updated using a timer, the others will get updated immediately when selected and then use the timer for updates.

Should i look at removing the timer and once a full sentence is received update each panel?

My thought is that this could be a problem with others using timers with astream data.

Regards

Stu

If it's any help, I use a global string to catch all the data from the newdata event. Then use a timer every 250ms to update a scrolling edittext with the data. I had to do this because the overhead of updating the edittext at every newdata event was just too much. Works with USB >> RS232 adaptor very well. So at least with me the timer works well.

I have only tried at 8 data bits, none parity, so can't vouch for 7 and even, not that it should make much difference.
 
Upvote 0
Top