GPS NMEA-Sentence from serial port

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

GPS NMEA-Sentence from serial port

Dimitri Minich
Hello all,
I'm trying to read NMEA-Sentences from a GPS-Mous. Using this code I got
some problems:

serial := SerialIO connectTo: 'COM3'.
serial enableRTS.
t := true asValue.
cnt := 0.
[ [ t value] whileTrue:
    [ | data |
    data := serial read: 1.
    ( data size > 0 ) ifTrue: [ Transcript show: data].
    cnt := cnt + 1.
   ]
] forkAt: 3.

" to stop "
t value: false. serial disconnect.

The first 10-20 sentences are read correctly, but after that I got some
wrong data like this:

$GPVTG,0.00,T,,M,0.00,N,0.0,K*60
OK!
$GPGGA,090700,4853.7425,N,00913.0326,E,0,00,0.0,357.6,M,357.6,M,0.0,0000*51
OK!
$GPGLL,4853.7425,N,00913.0326,E,090700,V*31
OK!
$GPGSA,A,1,04,20,11,20,04,20,20,04,03,04,20,04,0.0,0.0,0.0*35
OK!
$GPGSV,3,1,12,04,11,200,00,20,26,134,00,,20,102PV,,10,,30,104,,7$S32,0,4,,,2
301005GC0V54,13E0.10.W
NOT OK!
P057,0.60,,63600*
NOT OK!
G,.203E013$S,4024,03,0..05$V1,1000,,1922647$S,2,20,,060,,,7GV,20004,,264,100
NOT OK!
.5033E004207$G9254032,007,7M005$L87,0.6003
NOT OK!
GA0100000,,0,*
NOT OK!
G314,,264,420,102GV,0,,0,,264,23*
NOT OK!

I'm using this dcb data:

dcb
baudRate: CBR_4800;
parity: NOPARITY;
stopBits: ONESTOPBIT.

Does any body know, why does it act so?
Thanks


Reply | Threaded
Open this post in threaded view
|

Re: GPS NMEA-Sentence from serial port

Ian Bartholomew-18
Dimitri,

> Does any body know, why does it act so?

As you are only reading a single byte at a time I would guess that you are
not keeping up with the data flow into the underlying windows control and it
is overflowing.

Try changing

data := serial read: 1.
( data size > 0 ) ifTrue: [ Transcript show: data].

to

data := serial read: 1000.
data isEmpty ifFalse: [Transcript nextPutAll: data]

Let me know if you still have problems and I'll have another think - there
are a few other possible causes.

Regards
    Ian


Reply | Threaded
Open this post in threaded view
|

Re: GPS NMEA-Sentence from serial port

Dimitri Minich
Hi Ian,
thanks for your answer!

> As you are only reading a single byte at a time I would guess that you are
> not keeping up with the data flow into the underlying windows control and
it
> is overflowing.

you are right this was the problem.

> data := serial read: 1.
> ( data size > 0 ) ifTrue: [ Transcript show: data].
>
> to
>
> data := serial read: 1000.
> data isEmpty ifFalse: [Transcript nextPutAll: data]
>
> Let me know if you still have problems and I'll have another think - there
> are a few other possible causes.

It works fine, but to parse this string I need to read each character.
With character = '$' statrts every new sentence. So I have to look for each
'$' or for cr to filter a sentence from stream.
Any idea for this?


Reply | Threaded
Open this post in threaded view
|

Re: GPS NMEA-Sentence from serial port

Ian Bartholomew-18
Dimitri,

> you are right this was the problem.

Good news.

> It works fine, but to parse this string I need to read each character.
> With character = '$' statrts every new sentence. So I have to look for
> each '$' or for cr to filter a sentence from stream.
> Any idea for this?

The easiest way is to split it into two parts.  The first scans the serial
port every second (the timings can obviously be adjusted if needed) and
stores any newly arrived text in a SharedQueue.  I've used a SharedQueue to
make it process safe - there are two processes accessing one data structure
and we will just want to avoid both accessing at the same time.

serial := SerialIO connectTo: 'COM1'.
serial enableRTS.

run := true.
buffer := SharedQueue new.
[[
    Processor sleep: 1000.
    (text := serial read: 1000) isEmpty
        ifFalse: [buffer nextPut: text asString].
    run] whileTrue]
    forkAt: Processor userBackgroundPriority.

The second process scans the SharedQueue and when any new text appears it is
appended to the end of the working String.   Once you have two $ characters
in this String (you therefore have at least one complete line) the first
line is removed and displayed.

s := String new.
[[
    Processor sleep: 100.
    buffer size > 1 ifTrue: [s := s , buffer next].
    (s occurrencesOf: $$) > 1
        ifTrue: [
            index := s nextIndexOf: $$ from: 2 to: s size.
            Transcript print: (s copyFrom: 1 to: index - 1).
            s := s copyFrom: index].
    run] whileTrue] forkAt: Processor userBackgroundPriority.

run := false.
serial disconnect.

NB: There are lots of ways of doing this (circular buffers, streams) and I'm
not saying the above is the best, neatest or most efficient!.  I think using
a ReadWrite stream and #nextLine would be better but the Dolphin
implementation of #nextLine makes this a bit messy.

Regards
    Ian