NMEAconverter is a utility that can parse incoming NMEA sentences/data, adjust and/or make calculations with the data, and then output a new NMEA sentence to have that adjusted data appear in OpenCPN. Examples include calculating true wind speed/angle from apparent wind data and boat speed information, changing units (degrees C to F or vice-versa, knots to km, etc.), or correcting malformed sentences created by some equipment where the sentence would otherwise be ignored by OpenCPN or displayed improperly.

Please note that there is no Toolbar Icon. NmeaConverter works from the Preferences button of the plug-in. Options|Plug-ins|NMEAConvertor –> Preferences

To use the plugin a basic understanding of NMEA sentences is required. Please see the User Manual (Advanced Features) for details on NMEA sentences and the fields each sentence contains. The basics of an NMEA sentence are:

  • Initial delimiter (usually $, sometimes !)

  • Talker ID (the instrument sending the data, two characters, optional)

  • Sentence name - three characters

  • Data, in fields, comma separated

  • End delimiter - *

  • Checksum

  • Carriage Return+Linefeed

Example $GPRMB,field1,field2,…field15*<0xChecksum><0x0D><0x0A>

        1 2   3 4    5    6       7 8        9 10  11  12  13|
        |   |   |   |    |   |       |   |        |   |   |   |   |   |

The basic format of a conversion command is:

NewSentence, Argument for Field 1, Argument for Field 2, ...Argument for field n

NewSentence = $IDYYY where ID is a talker ID you would like to use to denote sentences from the converter. The examples in this manual generally use XX as the talker ID for newly created sentences. YYY is the NMEA sentence identifier you would like to send. A simple conversion example - this sample takes the 5th and 6th fields of an MDA sentence and transmits a new MTA sentence:


Arguments can take the form of constants (numeric or text), values from an incoming NMEA sentence, or calculations using either or both constants and incoming data. In the simplest form an argument is an incoming NMEA sentence and field number - $GPRMC4 will get the fourth value in any RMC sentence received by OpenCPN from talker GP. See the User Manual (Advanced features) to figure out what sentence you want to send, what data fields are required, and how the fields are configured. You must build a complete version of the sentence you want to send, and put the right data/fields from the original source in the right places for the converter to work properly. A number of detailed examples are provided below for reference.

When inserting argument fields the wildcard “?” can be used to tell the converter to use data with any content where the “?” appears. The wildcard “??” at the front of an argument will tell the converter to use data from any talker sending the requested sentence (e.g. $??HDG3 will retrieve the third field from any HDG sentence regardless of sender). Be careful when using wildcards and the talker ID, especially when correcting malformed sentences. If you create a conversion that outputs the same sentence as any field used in the input (e.g. $XXHDG, $??HDG3,…..) you will create a loop that will crash the plugin (and OpenCPN). Every time the plugin evaluates it will see its own creation, because of the wildcard it will reevaluate, …

Once a conversion is defined you can select whether to send the calculated sentence on a fixed timing (every x seconds) or only when the incoming data is updated.

You do not need to add the end delimiter (*) or the checksum in your converter definitions - the converter will calculate the checksum and add the delimiter and checksum automatically.

Depending on the data you are manipulating you may want to go into the options setting "connections" and tell OpenCPN to ignore the original data. If you are making unit conversions, for instance, and do not ignore the original data you will end up with a display that flashes between the original value and the converted value. Setting the data to ignore will not affect the converter, the data will still be received there, it simply prevents the display of the data in OpenCPN.

For Reference from the User Manual (Advanced features - NMEA Sentences Page), sentences that can be displayed in OpenCPN include:

  • DBT - Depth Below Transducer

  • DPT - Depth of Water

  • GGA - Global Positioning System Fix Data

  • GLL - Geographic Position - Latitude/Longitude HDG Heading - Deviation & Variation

  • HDM - Heading - Magnetic

  • HDT - Heading - True

  • MTA - Air Temperature (obsolete)

  • MDA - Meteorological Composite (obsolete) Use XDR transducer instead.

  • MTW - Mean Temperature of Water

  • VLW - Distance Traveled through Water

  • MWD - Wind Direction & Speed

  • MWV - Wind Speed and Angle

  • RMC - Recommended Minimum Navigation Information

  • RSA - Rudder Sensor Angle

  • VHW - Water speed and heading

  • VTG - Track made good and Ground speed

  • VWR - Relative Wind Speed and Angle

  • VWT - True Windspeed and Angle (obsolete)

  • XDR - Transducer Values

  • ZDA -Time & Date - UTC, day, month, year and local time zone

  • AIVDO - Automatic Information System (AIS) position reports from own vessel

1. Getting Started

Install the plugin in accordance with the User Manual. (Install and enable plugins)

Then open the Preferences Dialog to set up your conversions.

nmea converter

If you see something like above please enlarge the nmeaSendObjectDlg window so it displays the “OK” and “Cancel” buttons.

2. First Test


This is a completely useless sentence that is sent every second to OpenCPN. Check also the NMEAdebug window in the picture above, and note that a checksum is added to the sentence. It is easy to change this one into something like:


Just enter this line into the NMEAConverter > Preference > New > Edit box and Save it. No VDR file is needed. That will fake a GPS position into OpenCPN, but still not very useful.

3. Use incoming data to send a different NMEA sentence

The real power of this plugin is that you can change the data of the sent sentence by cherry picking from incoming sentences. The reason I wrote this plugin was I wanted Dashboard to show the air temperature. To get the data, Dashboard needs an $xxMTA sentence, however I had a Airmar PB200 unit that is sending $xxMDA sentences.

An example: We have from the windset,

MDA- Meteorological (Obsolete)


and want: MDA- Air temperature


Note that the data needed is in fields 5 and 6 of the MDA sentence. (11.3 degrees Celsius)

Setting the format to


will give an output sentence:

$XXMTA, 11.3, C*26

Where $WIMDA5 is replaced by the 5th field of the $WIMDA sentence. etc.


As seen above, the $XXMTA sentence is sent each time a $WIMDA sentence is received and read by Dashboard.

For testing use VDR_pi or VDRplayer and run WIMDA+OCMDA.txt from this zip.

4. Do Math - Convert Units, e.g. Centigrade to Fahrenheit

But what if I was living in the US and preferred the reading to be in degrees Fahrenheit? Just change the format to:

$XXMTA, 9/5*$WIMDA5 32, F

The value is recalculated and displayed as degrees Fahrenheit.

Use the same file for testing use VDR_pi or VDRplayer and run WIMDA+OCMDA.txt from this zip

5. Force True Heading to COG

In NMEAconverter create a HDG (compass) sentence from your COG. Possible use when the autopilot is old and does not receive heading (true or magnetic).

Note: Since computation of the drift and surface current requires HDG, it is understood that while using Tactics_pi value for Current speed and direction will not be useful. All you will see is the speed difference between SOG and STW, which would force Current to be the vector component normal to the keel. That means the “current” display will always be directly from bow or stern, in other words the component of the current along the centerline of the boat, assuming your STW(speed through water) is calibrated correctly.


The NMEA file being run by VDR_pi is vdr2 - copie.xls

Tactics_pi and in particular, NMEAconverter_pi is using


Remember that setting HDT to COG will give you no drift angle at all (except maybe a small portion via the manual heel input), so you will not see any real current I suggest to set a fixed heel angle to 0 (see screenshot above), to avoid side effects with manual heel input at very low speeds and small speed differences between SOG and STW.

6. Calculate True Wind from Apparent Wind


Boat Speed ground (kts) = SOG Apparent wind speed (degrees) = AWS Apparent wind angle (degrees) = AWA

MWV - Wind Speed and Angle - Input


Field Number:

  1. Wind Angle, 0 to 360 degrees

  2. Reference, R = Relative, T = True

  3. Wind Speed

  4. Wind Speed Units, K/M/N

  5. Status, A = Data Valid

  6. Checksum


Field Number:

  1. Blink Warning

  2. Latitude

  3. N or S

  4. Longitude

  5. E or W

  6. Time Difference A, uS

  7. Time Difference B, uS

  8. Speed Over Ground, Knots

  9. Track Made Good, degrees true

  10. Magnetic Variation, degrees

  11. E or W

  12. Checksum

MWV - Wind Speed and Angle - Output TW in Knots


Field Number:

  1. Wind Angle, 0 to 360 degrees

  2. Reference, R = Relative, T = True

  3. Wind Speed

  4. Wind Speed Units, K/M/N

  5. Status, A = Data Valid

  6. Checksum

Calculations Needed:

x =AWS*sin(AWA*3.14159265/180) y =(x/tan(AWA*3.14159265/180)) - SOG TWS (True Wind Speed) =x/sin(TWA*3.14159265/180) TWA (True Wind Angle) =atan(x/y)*180/3.14159265 *Formula from http://www.bethandevans.com/calculators.htm

The formula now needs to be completed: $XXMWV,


  1. $s were missing in the previous version

  2. Changed wind speed unit from K to N

  3. Deleted spaces after commas.

  4. In terms of sog vs. stw, as pointed out, in most cases, diff is negligible I believe.

  5. One thing about stw is that the sensor cannot capture the movement of a vessel due to tide (as high as 5 knots!).

  6. For my purpose, gps is good enough.

Observations by Rhythm Doctor:

One needs to be careful with this calculation. There are at least two different syntaxes for the reporting of relative wind angle. The older VWR and VWT sentences for relative and true wind are not recommended for new devices, but there are many older devices and SeaTalk converters that still use them (specifically, my own instruments). The sentences look like this (with II talker ID in this example):


1 084.0 Wind Angle 0 - 180 2 R Right of vessel heading (L = Left) 3 10.4 Wind Speed 4 N Wind Speed units Knots 5 5.4 Wind Speed 6 M Wind Speed units Metres per second 7 19.3 Wind Speed 9 K Wind Speed units Km/Hr

Newer devices use the preferred MWV sentence structure that looks like this (with II talker ID in this case):


1 084.0 Wind Angle 0 - 359 2 R Relative (T = True) 3 10.4 Wind Speed 4 N Wind Speed units Knots (K = KPH, M = MPH) 5 A Status (A= Valid)

Note that VWR/VWT and MWV work totally differently: VWR provides wind angles from 0-180 with an additional parameter of L or R, while MWV provides wind angles from 0-359 with no L or R. Converting your obsolete VWR sentence to the more modern MWV sentence would seem to be impossible without a conditional if() statement, which appears to not be supported (since I was unable to get it to work).

Here is the sentence that works best for me for converting VWR (relative/apparent wind) to VWT (true wind). Using the wildcard (instead of II, GP, or WI sender IDs) allows testing with others' VWR sentences, including Paul Elliot’s test NMEA files:


Note that there is an invisible <return> character at the end of this sentence (after the four commas). In my testing, things don’t work right without it. I recommend that you include it if you copy/paste this formula into the config dialog.

Transmitter Dan advises:

It is possible to replace the sender ID (GP or WI) with ?? which means any sender ID will be accepted. Using the wildcard will allow Paul Elliot’s test NMEA file to work with the NMEAconverter formula, using Seatalk - vYacht dialect:

$XXMWV,90-deg(atan(($??MWV3*cos(rad($??MWV1))-$GPRMC7)/$??MWV3*sin(rad($??MWV1)))),T,sqrt(sqr($??MWV3*sin (rad($??MWV1)))+sqr($??MWV3*cos(rad($??MWV1))-$GPRMC7)),N,A

Edit: In above formula’s 3.14159265 might be replaced by “pi”, and 3.14159265/180 can also be written as “deg”.

7. Normalize Degrees to less than 360

For True Wind Direction (TWD) = Sum between True Wind Angle (MWV) and True Heading (HDT)

nmeaconverter greater than 360 crop

Math Basis

Formula for re-orienting circular values i.e to keep angle between 0 and 359 is:

angle Math.ceil( -angle / 360 ) * 360

Generalized formula for shifting angle orientation can be:

angle Math.ceil( (-angle+shift) / 360 ) * 360

in which value of shift represent circular shift for e.g I want values in -179 to 180 then it can be represented as:

angle Math.ceil( (-angle-179) / 360 ) * 360

What is math.ceil? Java script function.

The Math.ceil() function returns the smallest integer greater than or equal to a given number. Note: Math.ceil(null) returns integer 0 and does not give a NaN error.

NMEAConverter has this comparable function:

ceil : the smallest integer greater than or equal to x

Homebrew MOD function:

=( Angle /360-INT( Angle /360))*360
nemaconverter normalize degrees crop


All data comes from Raymarine instrument with NMEA 0183. Here the two data values to have in OpenCPN:

  • True Heading

  • True Wind Direction 0-359


Max reports that it works well. - Thank you Max.

The formula to normalize the degrees to be between 0-360 is


8. Prepare Barometer Sensor Output for Dashboard


The BMP180 pressure sensor output from Raspberry Pi/OpenPlotter uses the sentence $OSXDR. This cannot be read by Dashboard. BMP180 Output Units are Bars i.e 1000 times the reading needed for display - mBar/hectoPascal. Any error in the output cannot be corrected. This formula creates an $xxMDA (deprecated) or $xxXDR sentence that can be used by Dashboard.


$MYXDR,P, 0.018 1/1000 * $OSXDR2,B,Barometer


$MYMDA, , ,0.0181/1000*$OSXDR2,,B,,,,,,,,,,,,,,,,M

(0.018 is an error correction and also adjusts the barometer pressure for a sea level reading)

Applying the settings

Found it necessary to tick the 'block incoming messages with wrong checksum' box when editing the sentence.

block incomming

When editing the sentence; starting a variable with '.' or '$' causes OpenCPN to freeze. Variables are being read by the plugin all the time and these characters are not recognized. Workaround is to type '0.' and then the number. Also 'OSXDR2' and then add the '$' in front, '$OSXDR2'.

osxdr variables
virtual mda

9. Fix incorrect ST60 Wind Speed Data

Ratsea has fixed an incorrect Raymarine ST60 conversion.


Dashboard displays incorrect wind speed data when using the ST60 Multi NMEA Output. The data is treated as Km/hr as it has the K unit identifier and is converted to knots/m per sec/Km/hr as per the Dashboard settings, it then incorrect as the data is already in Knots


Change the display units in the wind output sentence from ST60 Multi from K (kms/hr) to N (kts) as the Raymarine instrument incorrectly uses the K identifier for Knots and not the N, so that the Dashboard correctly displays the Wind Speed data in the units selected.


Using the NMEA converter, apply the conversion to the MWV sentence with a new ID - xx:


and tick 'Send after update all variable' With the instrument switched on and receiving the actual live data shows in Blue.

nmea con st60

The NMEA datastream then becomes:

$IIMWV,155,R,009.0,K,A*2E Input
$xxMWV,155,R,9.0,N,A*2B Corrected, the input line is also shown on the dashboard, but too quickly to notice


Whilst developing this code, I found that using the formula:


would also work if the 'Send every (n) seconds' was ticked, but the Dashboard would flash between the two values of Km/sec and knots. If the Send after update all… was ticked, then OpenCPN would freeze in a continuous loop trying to update the newly created NMEA sentence!

10. Use Wildcards

Now it is possible to use wildcards in the identifiers. So you could make it talkerid independent by using something similar to


and whatever character on the ? position will cause a hit.

Even more important, you might use it for special transducers sending the something like

$OWXDR,H,....or $OWXDR,C....


Note that field 1 is part of the identifier. As the comma is the NMEA separator, you can not use it as an identifier string, but by using a wildcard it works.

For example

 ....$OWXDR?H2... or $??XDR?H2....

will work. Cruiser Forum Post

10. Wildcards Example: Change Engine data format

Using wildcards is also useful when the data to be matched is in the data payload rather than the header. In the example below, we have engine data coming from the NMEA stream which contains the correct sender transducer ID, however is not the format required by the Engine Dashboard plug-in. Here is the original NMEA sentences:

[code] Engine RPM $ERRPM,E,0,2324.00,,A*69 Oil Pressure, Coolant Temp, and Engine Hours $ERXDR,P,4.04,B,ENGOILP0,C,75.25,C,ENGTEMP0,G,2024 .1,,ENGHRS0*01 Battery0 (Starter) Voltage and Shunt Current $ERXDR,U,13.75,V,BATVOLT0,I,0.8,A,BATCURR0*4D Battery1 (House) Voltage $ERXDR,U,13.27,V,BATVOLT1*14 [/code]

You can see that the two battery voltages are distinguished using different transducer IDs, BATVOLT0 and BATVOLT1

The following NMEA Converter plug-in code converts to sentences so that the Engine Dashboard can read them. For the sentence that contains multiple data elements, we can us the wildcard “$ERXDR?P2” to match on the particular sentence that has the data we need.

To get battery voltage and current, we need to make liberal use of the wildcard to match out to the “I” in order to distinguish from the BATVOLT1 sentence. this gets us the battery0 voltage and the DC shunt current.

For battery1, I have not figured out how to convert this because the only character that distinguishes it from battery0 is the “1” at the end.


See this CF #341 Post and ones preceding.

11. Convert Temperature C to Fahrenheit

Using convert C to F for temp ( $XXMTA, 9/5*$AIMTW5 32, F) with send after all updates variables checked.

  • As soon as I start to playback a NMEA stream via VDR plugin or VDRplayer.py OpenCPN crashes. A look at the O logs does not produce any clues.

  • As a side note I have compiled and used the Tactics plugin with the same NMEA file with VDRplayer and O and Tactics run just fine.

You are using an ..MTW sentence. Format according my info:

  • MTW - Mean Temperature of Water


  • This sentence has only 2 fields available, the first one given the temp value and the second just 'C' for 'Celsius'.

  • In your command sentence ($XXMTA, 9/5_$AIMTW5 32, F) )

  • You are requesting the 5th field of the MTW sentence, but that field does not exist. Try again with

 $XXMTA, 9/5*$AIMTW1 32, F

Used new formula provided above.. Still Crashed. I removed the


entry that came with NMEAConverter_pi install. OpenCPN no longer crashes with NMEAConverter_pi enabled with a NMEA stream present..and as provided for above

$XXMTA, 9/5*$AIMTW1 32, F

is showing the “Air Temp” in F in Dashboard on O. “I can never thank the volunteers enough for all these wonderful tools.”

12. Fix bad Heading Checksum

The problem with the incoming sentence:

$APHDM, 113,M*0A

Which in this case, is a magnetic heading of 113 degrees followed by a bad checksum.

Using the NMEA converter sentence, to delete the bad checksum and then add a new checksum after a forced comma,


Which gets converted to a new sentence of $IIHDM,113, *50 with a new checksum. This assigns the first field of the NMEA sentence from $APHDM (113) to a new virtual source of $IIHDM

correct head

Tim advises:

  • As you can see, I now have a heading indicator plus dashboard data. The NMEA debug window shows the data coming in and being converted.

  • I’m sure that I should tweak the conversion command to put M in for magnetic, plus tidy up commas and stuff (as per Hakan suggestion), but it is working well, so I am reluctant to “fix” it further just at the moment…

Dsanduril reports: “The TMQ checksum includes the '$' delimiter character at the start of the sentence. Per NMEA standard the '$' delimiter at the start of the sentence and the '*' delimiter at the end of the sentence should not be included in the checksum. Checksum should be calculated by XOR of all characters between the delimiters. [Suggesting that the TMQ AP needs a firmware update to correct the error.”

From the Nmea Standard:

> The checksum is the 8-bit exclusive OR (no start or stop bits) of all characters in the sentence, including "," and "^" delimiters, between but not including the "$" or "!" and the "*" delimiters[emphasis added]. The hexadecimal value of the most significant and least significant 4 bits of the result is converted to two ASCII characters (0-9, A-F (upper case)) for transmission. The most significant character is transmitted first.

13. Change Validity Character - NMEA Converter with the SailAway Game/Simulator

The game SailAway sends realtime NMEA streams that can be used with plotter software, routing software, etc. The game developers have elected to send the RMC and GLL sentences with the “V” validity character, which indicates the data is invalid. OpenCPN rejects the data. An “A” character is required to show the data is valid.


NMEAconverter can easily adjust these sentences and recalculate the checksum so that the data is accepted in OpenCPN.


Thanks to Jurien72 and Rasbats CForum SOG/COG Problem

14. OpenCPN Magnetic Variation Reversed?

NMEA version 2 and onwards states that the RMC sentence must include an extra field Nbr 12 "FAA mode indicator" but the ECRMC sentence generated by OpenCPN when navigating to a waypoint does NOT include this field.

The NASA Clipper GPS Repeater (which displays all bearings in magnetic) requires NMEA version 2.0 (or later version) and it appears that if the GPS Repeater doesn’t see the extra field it just assumes West variation. (Magnetic variation here in NZ is 22 degrees East).

With the help of Dirk’s wonderful NMEAConverter plugin I was able to synthesise an XXRMC sentence from the incoming RMC from the GPS and adding an extra comma and "A" after the Magnetic Variation E or W field. By sending my "synthetic" XXRMC from OpenCPN instead of the ECRMC, the GPS Repeater magically shows the correct magnetic bearing of 338 degrees rather than 22 degrees previously when steering to a course of 0 degrees true.


$ECRMC,211808.00, A,4117.30837, S,17447.10970, E,0.007, ,310818,22.6,E*23
(RMC sentence generated by OpenCPN - no field after the last "E")
$XXRMC,211808.00, A,4117.30837, S,17447.10970, E,0.007, ,310818,22.6,E,A*23
(Synthesised RMC sentence with extra field after the last "E")

Could we please in the next release of OpenCPN, add the extra field in the ECRMC sentence to make it NMEA Version 2.3 compliant? This was fixed in the next release, so the above is not necessary.

15. Contribute your Formulas & Conversions

If you have an useful format formula please feel free to add it here.

Another future possibility is to do a comparison lookup of a boat’s Polar data and send a special NMEA sentence of the comparative result to the Dashboard using a special dedicated performance instrument, for example.

Calculations Supported

For calculations the following functions are supported:

Normal functions

abs : the absolute value, it removes the sign
ceil : the smallest integer greater than or equal to x
cub : x^3, safe way to compute such an exponent
deg : converts from radian to degree
exp : the exponential value
hvi : Heaviside's function, =0 if x<0, =1 if x>=0
int : the largest integer less than or equal to x
inv : inverts, 1/x
floor : not supported, see int
ln : the Napierian\natural logarithm
lnep : see ln
log : the logarithm base 10
rad : converts from degree to radian
sgn : the sign, -1 or1. Zero returns1.
sqr : x^2, safe way to compute such an exponent
sqrt : the root square
pi : 3.14159265
deg : 3.14159265/180

Trigonometric functions

acos : the secant (inverse of cosine)
acsh : the inverse of the hyperbolic cosine
asin : the cosecant (inverse of sine)
asnh : the inverse of the hyperbolic sine
atan : the cotangent (inverse of tangent)
atnh : the inverse of the hyperbolic tangent
cos : the cosine
cosh : the hyperbolic cosine
sin : the sine
sinc : the cardinal sine (radian)
sinh : the hyperbolic sine
tan : the tangent
tanh : the hyperbolic tangent

This makes it possible to do spreadsheet-like calculations. And as in a spreadsheet the trigonometric functions use radians.

In beta at this moment:

* An extra checkbox to allow for calculation in degrees instead of
* “E” bug is fixed.
* “pi” instead of 3.14159265
* “deg” instead of 3.14159265/180