GithubHelp home page GithubHelp logo

stevemarple / micronmea Goto Github PK

View Code? Open in Web Editor NEW
98.0 15.0 40.0 98 KB

A compact Arduino library to parse NMEA sentences.

License: GNU Lesser General Public License v2.1

C++ 67.33% Makefile 4.75% Python 27.93%
arduino arduino-library nmea nmea-parser gps gps-library gnss glonass

micronmea's Introduction

MicroNMEA

MicroNMEA is a compact Arduino library to parse a subset of NMEA sentences, which can originate from either GPS or GNSS receivers. Only two types of messages are parsed, $GPGGA (and its GNSS versions $GNGGA, $GLGGA, and $GAGGA) and $GPRMC (and its GNSS versions $GNRMC, $GLRMC, and $GARMC). From these two NMEA sentences MicroNMEA can output date, time, latitude, longitude, altitude, number of satellites used, horizontal dilution of precision (HDOP), course and speed. When other NMEA sentences are detected they can be passed to an optional callback function for decoding or logging. Checksum failures can be indicated with another optional callback function.

NMEA sentences can easily be sent to an output stream with the sendSentence() function which computes and appends the checksum, as well as the correct <CR><LF> terminators.

License

The MicroNMEA library is released under the GNU Lesser General Public License, version 2.1. http://www.gnu.org/licenses/lgpl-2.1.html

Initialization and basic usage

A MicroNMEA object must be defined with a pointer to a buffer and the buffer length:

char buffer[85];
MicroNMEA nmea(buffer, sizeof(buffer));

This approach enables the user to size the buffer appropriately according to use without requiring malloc(); for instance the buffer size can be increased if the temporal and spatial resolution reported have been increased by some properietary NMEA command.

Output data from the GPS/GNSS device must be passed to the library for processing:

while (gps.available()) {
    char c = gps.read();
    if (nmea.process(c)) {
        // Complete NMEA command read and processed, do something
        ...
    }
}

In the code fragment above gps is the output stream of the GPS/GNSS device.

Retrieving information from MicroNMEA

Location, date, time and various status information can be requested using the appropriate member functions which are described below. To obtain all of the information listed below MicroNMEA must process both GxGGA and GxRMC sentences:

char getNavSystem() const

Returns a single character indicating the navigation system in use:

P Navigation results based only on GPS satellites.
L Navigation results based only on GLONASS satellites.
A Navigation results based only on Galileo satellites.
N GNSS, navigation results from multiple satellite constellations.
\0 No valid fix
uint8_t getHDOP(void) const

Horizontal dilution of precision in tenths (i.e., divide by 10 to get true HDOP).

bool isValid(void) const

Validity of latest fix.

long getLatitude(void) const

Latitude in millionths of a degree, North is positive.

long getLongitude(void) const

Longitude in millionths of a degree, East is positive.

bool getAltitude(long &alt) const

Altitude in millimetres, returns true if the altitude was obtained from a valid fix.

bool getGeoidHeight(long &hgt) const

Height above WGS84 Geoid in millimetres, returns true if the height was obtained from a valid fix.

uint16_t getYear(void) const
uint8_t getMonth(void) const
uint8_t getDay(void) const
uint8_t getHour(void) const
uint8_t getMinute(void) const
uint8_t getSecond(void) const
uint8_t getHundredths(void) const

Date and time.

long getCourse(void) const

Course over ground, in thousandths of a degree.

long getSpeed(void) const

Speed over ground, in thousandths of a knot.

void clear(void)

Clear all stored values. isValid() will return false. Year, month and day will all be zero. Hour, minute and second time will be set to 99. Speed, course and altitude will be set to LONG_MIN; the altitude validity flag will be false. Latitude and longitude will be set to 999 degrees.

Callback and associated functions

void setBadChecksumHandler(void (*handler)(MicroNMEA& nmea))

setBadChecksumHandler() enables MicroNMEA to call a function when a bad NMEA checksum is detected. The callback function should accept a single parameter (a MicroNMEA object passed by reference) and return void.

void setUnknownSentenceHandler(void (*handler)(MicroNMEA& nmea))

setUnknownSentenceHandler() enables MicroNMEA to call a function when a valid but unknown NMEA command is received. The callback function should accept a single parameter (a MicroNMEA object passed by reference) and return void.

const char* getSentence(void) const

Return the current NMEA sentence. Useful when using callback functions.

char getTalkerID(void) const

Return the talker ID from the last processed NMEA sentence. The meaning is the same as the return value from getNavSystem(). If $GxGSV messages are received then talker ID could be from any of the GNSS constellations.

const char* getMessageID(void) const

Return the message ID from the last processed NMEA sentence, e.g, RMC, GGA. Useful when using callback functions.

Contributors

  • Steve Marple
  • Christopher Liebman
  • per1234
  • Noah-Jonathan Rosa
  • Philipp Tölke

Documentation

For documentation please see Read The Docs, https://micronmea.readthedocs.io/en/latest/.

micronmea's People

Contributors

liebman avatar per1234 avatar stevemarple avatar toelke avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

micronmea's Issues

isValid is always False

I am using the Portenta H7 with Portenta Cat. M1/NB IoT GNSS Shield, tying to run MicroNMEA_integration.ino example in the Arduino IDE. My GPS device is returning valid strings with data for $GPGGA and $GNRMC but it never sees them as valid.

Also I think the code gets stuck in this loop as the stream of nmea strings is continuous:

    while (GPS.available()) {
        char c = GPS.read();

        // process is true when a valid NMEA string has been processed
        nmeaProcessStatus = nmea.process(c); // this does periodically become 1
    }

I changed it to:

    while (GPS.available()  && !nmeaProcessStatus) {
        char c = GPS.read();
        // process is true when a valid NMEA string has been processed
        nmeaProcessStatus = nmea.process(c);
    }

Then it does break from the loop but these lines always return no for nmea.isValid()

        // Output GPS information from previous second
        Serial.print("Valid fix: ");
        Serial.println(nmea.isValid() ? "yes" : "no"); //this returns no

Obtaining/calculating velocity vectors by NMEA protocol

Good day @stevemarple
For one project I need to get vectors/directions of velocities to the north, east and down.
The action takes place in the NED coordinate system.
The UBX protocol and of course the device itself somehow produces this data.
I have a GPS/GLONASS receiver GN02D.
It provides data only via the NMEA protocol.
gps-nmea-0183_img01

I can get VTG data - speed and heading over ground.
VTG_NMEA

My real data from module
$GNVTG,7.00,T,7.00,M,0.000,N,0.000,K,A*3D
For some reason, the VTG only issues GNSS, but does not issue GPS... perhaps because I conduct experiments in an apartment, and not in the open air.

Is it possible to somehow obtain the NED velocity vectors from these data?
NED_velocity
P.S.
It is also interesting how to get time in week format from the NMEA protocol, iTOW as it is in the UBX protocol.
iTOW
I would be grateful to the community for help.

Cannot get correct parsing of GPS+GLONASS data

I am trying to build a GPS+GLONASS receiver based on a GNSS dual module, and I have come across MicroNMEA. Since I use an Arduino Nano with it I had to modify the example demo to use SoftwareSerial for the GNSS module, and also use pin 2 for the PPS interrupt (which I connected to the module's PPS output). The module I'm using has a PPS LED so I know I have a fix. However the console output says I don't have a fix. I can provide samples of the module's raw output as well as serial console output and the modified sketch. Unfortunately it doesn't seem like I can attach a sketch or even a text file to github's issue tracker. The module doesn't have a reset input so I just ignored A0 and the reset mechanism.

Setup instructions

I like to use a Wemos D1 Mini to create a web api for the NMEA signals. Would you mind describing the hardware setup/configuration in order to get a gps object?

Where do I define the pins I attached the cable to?

What is the unit of speed

Hi! I get the data from actual driving, the results puzzled me. The output speed of 30km/h is about 12000, the output speed of 40km/h is about 16000, and the output speed of 50km/h is about 20000.

Can you tell me what the units of speed are?

Fuzzing

Hey, I was looking at your repository and it seemed like a good case for some fuzzing. I found some issues that you might want to address. Test cases are built using the test_MicroNMEA binary and American Fuzzy Lop. Hope this helps improving your work :).

crashes.zip

MemoryFree.h

is Not included, can you put a link in your README.md?

invalid buffer

Hi,

A strange behaviour happens when trying to print the MicroNmea buffer after processing a response that comes over the serial


  for (int =0; i < size(response) ; i++)
    {
       nmea.process(response[i])
       SerialUSB.print(response[i]);
    }
    SerialUSB.println();
    SerialUSB.println("___________________________________________");
    SerialUSB.println(nmeaBuffer);
    SerialUSB.println("___________________________________________");

response it the buffer with the characters read from the serial
nmeaBuffer is the MicroNMEA buffer used in MicroNMEA nmea(nmeaBuffer, sizeof(nmeaBuffer));

The serial output looks like this:

$GNGGA,065049.000,4535.6646,N,02528.0303,E,1,6,1.33,633.1,M,35.6,M,,*44
$GPGSA,A,3,16,18,27,10,08,21,,,,,,,1.56,1.33,0.82*0A
$BDGSA,A,3,,,,,,,,,,,,,1.56,1.33,0.82*1A                                                                 <- response
___________________________________________
$BDGSA,A,3,,,,,,,,,,,,,1.56,1.33,0.82*1A                                                                 <- nmeaBuffer
___________________________________________

What is even stranger is that nmea.isValid() returns true for the code above and I also can get all the necessary data like altitude, number of satellites etc

May be the case that the nmeaBuffer contains only the last line processed?

Invalid RMC messages exception

When trying to use this library on a ESP board, the following GPS message causes a Fatal Exception:

$GPRMC,194812.00,V,,,,,,,290317,,,N*74

Currently, as a work around, I check if _isValid is false and return false which seems to work, but either I haven't gotten a bad message or it's not optimal

Great module, thanks!

MicroNMEA doesn't handle CRLF line endings

When calling MicroNMEA::process(char), I have to omit part of the CRLF line ending sent by my NMEA GPS device to avoid resetting the buffer completely. If I do send the full CRLF, process returns false, and calls to functions such as getSentence return an empty string.

From reading through the code, I believe this is due to this logic in the process method, which null-terminates the buffer and resets the pointer on any null, , or characters. So CRLF will invoke that code twice, resulting in the pointer equal to the start of the buffer and _buffer[0] == \0;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.