Our full technical support staff does not monitor this forum. If you need assistance from a member of our staff, please submit your question from the Ask a Question page.


Log in or register to post/reply in the forum.

Parse Airmar PB150 NMEA


KiwiPaul Jan 24, 2012 01:41 AM

As a newbie, I was hoping someone had an example programme or some hints on parsing multiple NMEA sentences to a CR1000 from a single sensor. We have an Airmar PB150 that is set to send the following NMEA sentences at 1 Hz:
$GPRMC,$GPGGA,$WIMDA,$WIMWV,$YXXDR

Some psuedo-code for what I want to do is:

Switch on PB150
Take wind readings (etc.) until GPS fix is valid
Once fix is made, store GPS position and average, min, max wind speed and direction
Shut down PB150

The two obvious approaches I can see are:

1. Grab enough to hold all sentences and Split string based on CRLF..then parse each string using the comma delimiter . However, the starting point will be random and the sentences will not always be in the same part of the split.

2.Grab each sentence using SerialinRecord and parse form there. However beginword and endword only seem to accept two characters. Should I just use MC, GA, DA, MV, DR ?

Any suggestions or tips are greatly appreciated.

Cheers.

-Paul

* Last updated by: KiwiPaul on 1/23/2012 @ 9:48 PM *


KiwiPaul Jan 24, 2012 05:32 AM

OK, I'm answering my own post with some progress notes.

I made some progress trying option 2 and can successfully parse the strings and log the data but have run into issues where the SerialInRecord is intermittant. This seems to happen as I try to add more strings and is likely a timing issue.

Here's some of the code, hopefully someone who's got more than 2 days experience with this will have some insight. thanks in advance.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Public RMCString As String * 75
Public RMC_Data(13) As String
Alias RMC_Data(2) = UTC_hhmmss 'UTC time in HHMMSS format
Alias RMC_Data(3) = RMC_Status 'Status A= Valid; V= Warning (no fix)
Alias RMC_Data(4) = RMC_Lat 'Lat in ddmm.mmm
Alias RMC_Data(5) = RMC_NorS 'Hemisphere N or S
Alias RMC_Data(6) = RMC_Long 'UTC time in HHMMSS format
Alias RMC_Data(7) = RMC_EorW
Alias RMC_Data(8) = RMC_SOG
Alias RMC_Data(9) = RMC_COG
Alias RMC_Data(10) = RMC_Date
Alias RMC_Data(11) = RMC_MagVar
Alias RMC_Data(12) = RMC_MagEW
Alias RMC_Data(13) = RMC_Mode

Public MDAString As String * 75
Public MDA_Data(6) As String
Alias MDA_Data(2) = MDA_Baro_In
Alias MDA_Data(4) = MDA_Baro_Bar
Alias MDA_Data(6) = MDA_AirTempC


Public MWVString As String * 20
Public MWV_Data(6) As String
Alias MWV_Data(2) = MWV_WindAngle
Alias MWV_Data(3) = MWV_Ref
Alias MWV_Data(4) = MWV_WindSpd
Alias MWV_Data(5) = MWV_Units
Alias MWV_Data(6) = MWV_Status

Public RMCBytes
Public MWVBytes
Public MDABytes

DataTable (PB150_Data,True,1000)
DataInterval(0,30,Sec,0)
Sample (1,RMC_Lat,String)
Sample (1,RMC_Long,String)
Sample (1,MDA_Baro_Bar,fp2)
Sample (1,MDA_AirTempC,fp2)
Maximum (1,MWV_WindSpd,FP2,False,0)
Minimum (1,MWV_WindSpd,FP2,False,0)
Sample (1,MWV_WindAngle,FP2)
WindVector (1,MWV_WindSpd,MWV_WindAngle,IEEE4,0,0,0,0)
FieldNames("MWV_Av_Spd_Kts,MWV_Av_Dir,MWV_SD_Dir")

EndTable


BeginProg
SW12(1)
PB150_On = true

Scan (1,Sec,0,0)
If PB150_On = true
SerialOpen (Com1,4800,0,0,1024)
SerialInRecord (Com1,MWVString,&H5756,0,&H0D0A,MWVBytes,00)
SplitStr (MWV_Data(),MWVString,",",5,5)
SerialInRecord (Com1,RMCString,&H4D43,0,&H0D0A,RMCBytes,00)
SplitStr (RMC_Data(),RMCString,",",13,5)
SerialInRecord (Com1,MDAString,&H4441,0,&H0D0A,MDABytes,00)
SplitStr (MDA_Data(),MDAString,",",6,5)
CallTable PB150_Data
If SerialInChk(Com1) > 800 Then SerialFlush (Com1)
ElseIf PB150_On = false
SW12(0)
EndIf


''''Turn the intrument on or off at set intervals
'''Remmed out for testing purposes assume always on

If IfTime(0,30,Min)
' SW12(1)
' PB150_On = true
ElseIf IfTime(5,30,Min)
' SW12(0)
' PB150_On = false
EndIf
NextScan
EndProg


KiwiPaul Jan 25, 2012 09:06 PM

Again, I'm updating my own post with some more progress notes. It seems that it is a timing issue with the SerialInRecord command.

For example, sending out the NMEA sentences ($GPRMC,$WIMDA,$WIMWV,$YXXDR)from the PB150 at 1 Hz it only takes aoubt 400 msec to Xmit, therefore there's about 600 msec of nothing being Xmitted. Trying to grab and parse all four of these sentences doesn't seem to work. It always finds the first one and generally the second, but rarely the third and fourth. Changing the order of the sentences in the code doesn't make any differece. Also changing the scan rate makes a little difference but not much. I tried 100, 250, 500 and 750 msec as well as different second intervals.

I was able to get it to work by doing the following:

1. Changing the Xmit on the instrument to 2Hz. This means there's about 800msec of data coming through every second. (i.e. better chance of finding the string I need)
2. Grabbing/parsing two sentences and then putting in a 333 msec delay. This seems to put the instrument into a different sequence on the incoming data stream.
3. Grabbing/parsing the second two sentences.

While this works it seems a bit clumsy to force a delay in the middle of the scan just so the CR1000 will see the right part of the NMEA stream.

Any thoughts or suggestions on why this works or another (cleaner) way to skin the cat?

Cheers.


Steele9170 Jul 22, 2014 09:49 AM

Did you ever have any luck getting this Weatherstation to work I am trying to use a WX-110 with the CR800 and we can't get the datalogger to see the sensor at this point. Any help with wiring/programming would be great. Thanks


KiwiPaul Jul 22, 2014 09:09 PM

Yes, I've been successful getting it to work for the PB150 and 150WX which are both setup as RS232 NMEA instruments. You need to ensure that the unit you have is outputting NMEA sentences and not Can Bus NMEA 2000 for any of the code I posted to work.
If your instrument is NMEA have a look at this page for some wiring help:

http://faq.airmar.com/index.php?action=artikel&cat=2&id=230&artlang=en

For the CR800 (using COM1[C1,C2]) you would wire it as follows:

Red - 12V
BLK+ORG - GND
Ylw - C1
Wht - C2
Bare - GND

If you're still stuck drop me a note:
paul.barter@cawthron.org.nz

Good luck


SolutionConsulting Sep 2, 2014 02:01 AM

We have built a Airmar NMEA to SDI-12 and Modbus adapter suitable for use with any Airmar Wx sensor. This may be easier to deal with than parsing serial input.

Email me at jtume@pacdatasys.com.au if you are interested.


JDavis May 24, 2016 05:16 PM

I think the only problem is probably that you need to add 100 to the option code for SerialInRecord. That will enable local pointer mode. Then it doesn't matter which order the NMEA sentences are in the buffer. Not using local pointers is the most likely cause of the intermittent errors you were having.

Here is a piece from a program where I read in several different NMEA strings from a device.

'Get the HEHDT, HEROT, GPVTG, and TSS1 NMEA strings from PortB of the V104.
'Go to http://hemispheregnss.com/gpsreference/Data_Messages.htm for definition of each NMEA string
SerialInRecord (ComV104,v104b_string_in(1),&H4454,0,&H0D0A,bytes_ret_hehdt,101) '4454 is DT
SerialInRecord (ComV104,v104b_string_in(2),&H4F54,0,&H0D0A,bytes_ret_herot,101) '4F54 is OT
SerialInRecord (ComV104,v104b_string_in(3),&H5447,0,&H0D0A,bytes_ret_gpvtg,101) '5447 is TG
SerialInRecord (ComV104,v104b_string_in(4),58,0,&H0D0A,bytes_ret_tss1,101) '58 is :


ClaraLC Oct 29, 2021 01:47 PM

Hello everybody,

I'm a little bit late on this post, but I'll take my chance since it's highly correlated with what I'm doing. I'm working with an ultrasonic anemometer, same NMEA protocol as the Airmar device. I had a lot of struggle with the settle of my program since my measurements showed a signal with large steps of constant speed even if the captor was placed in a very inhomogeneous flow (with ponctual gusts).

Finally the response of JDavis unlocked me because all I had to do was to add 100 to the option code for SerialInRecord. I don't have any step anymore and it seems that my gusts are now well measured. 

Which brings me now to question myself about what this option really do? I would be very grateful if someone could explain to me the meaning of this "local pointer" and what's the difference with the regular option. 

Thank you,

Cheers,

C. 


JDavis Nov 1, 2021 06:18 PM

The comport has one ring buffer. When new data comes in, it overwrites old buffer data and advances the write pointer. The write pointer keeps track of where the end of new data is.

The buffer has a read pointer to keep track of where data was last read out. When you read data with and instruction like SerialInRecord(), the read pointer advances. The next read instruction will start at the new read pointer location. Data already read out of the buffer is ignored.

You can run into problems with multiple read instructions on the same port. SerailInRecord() will advance the read pointer past data it is not looking for. Effectively the first SerialInRecord() could erase data from the buffer the second SerialInRecord() is looking for.

When you add 100 to have a local read pointer, each SerialInRecord() is using its own read pointer. They share a buffer. However, as long as you don't do a SerialFlush() it behaves like each SerialInRecord has its own copy of the data.

Log in or register to post/reply in the forum.