#include #include //====================================================================== // Program: ublox.ino // // Prerequisites: // 1) You have a ublox GPS device // 2) PUBX.ino works with your device // 3) You have installed the ubxGPS.* and ubxmsg.* files. // 4) At least one UBX message has been enabled in ubxGPS.h. // 5) Implicit Merging is disabled in NMEAGPS_cfg.h. // // Description: This program parses UBX binary protocal messages from // ublox devices. It shows how to acquire the information necessary // to use the GPS Time-Of-Week in many UBX messages. As an offset // from midnight Sunday morning (GPS time), you also need the current // UTC time (this is *not* GPS time) and the current number of GPS // leap seconds. // // Serial is for debug output to the Serial Monitor window. // // License: // Copyright (C) 2014-2017, SlashDevin // // This file is part of NeoGPS // // NeoGPS is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // NeoGPS is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with NeoGPS. If not, see . // //====================================================================== #include #include //------------------------------------------------------------ // Check that the config files are set up properly #ifndef NMEAGPS_DERIVED_TYPES #error You must "#define NMEAGPS_DERIVED_TYPES" in NMEAGPS_cfg.h! #endif #if !defined(UBLOX_PARSE_STATUS) & !defined(UBLOX_PARSE_TIMEGPS) & \ !defined(UBLOX_PARSE_TIMEUTC) & !defined(UBLOX_PARSE_POSLLH) & \ !defined(UBLOX_PARSE_DOP) & !defined(UBLOX_PARSE_PVT) & \ !defined(UBLOX_PARSE_VELNED) & !defined(UBLOX_PARSE_SVINFO) & \ !defined(UBLOX_PARSE_HNR_PVT) #error No UBX binary messages enabled: no fix data available. #endif #ifndef NMEAGPS_RECOGNIZE_ALL // Resetting the messages with ublox::configNMEA requires that // all message types are recognized (i.e., the enum has all // values). #error You must "#define NMEAGPS_RECOGNIZE_ALL" in NMEAGPS_cfg.h! #endif //----------------------------------------------------------------- // Derive a class to add the state machine for starting up: // 1) The status must change to something other than NONE. // 2) The GPS leap seconds must be received // 3) The UTC time must be received // 4) All configured messages are "requested" // (i.e., "enabled" in the ublox device) // Then, all configured messages are parsed and explicitly merged. class MyGPS : public ubloxGPS { public: enum { GETTING_STATUS, GETTING_LEAP_SECONDS, GETTING_UTC, RUNNING } state NEOGPS_BF(8); MyGPS( Stream *device ) : ubloxGPS( device ) { state = GETTING_STATUS; } //-------------------------- void get_status() { static bool acquiring = false; if (fix().status == gps_fix::STATUS_NONE) { static uint32_t dotPrint; bool requestNavStatus = false; if (!acquiring) { acquiring = true; dotPrint = millis(); DEBUG_PORT.print( F("Acquiring...") ); requestNavStatus = true; } else if (millis() - dotPrint > 1000UL) { dotPrint = millis(); DEBUG_PORT << '.'; static uint8_t requestPeriod; if ((++requestPeriod & 0x07) == 0) requestNavStatus = true; } if (requestNavStatus) // Turn on the UBX status message enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_STATUS ); } else { if (acquiring) DEBUG_PORT << '\n'; DEBUG_PORT << F("Acquired status: ") << (uint8_t) fix().status << '\n'; #if defined(GPS_FIX_TIME) & defined(GPS_FIX_DATE) & \ defined(UBLOX_PARSE_TIMEGPS) if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_TIMEGPS )) DEBUG_PORT.println( F("enable TIMEGPS failed!") ); state = GETTING_LEAP_SECONDS; #else start_running(); state = RUNNING; #endif } } // get_status //-------------------------- void get_leap_seconds() { #if defined(GPS_FIX_TIME) & defined(GPS_FIX_DATE) & \ defined(UBLOX_PARSE_TIMEGPS) if (GPSTime::leap_seconds != 0) { DEBUG_PORT << F("Acquired leap seconds: ") << GPSTime::leap_seconds << '\n'; if (!disable_msg( ublox::UBX_NAV, ublox::UBX_NAV_TIMEGPS )) DEBUG_PORT.println( F("disable TIMEGPS failed!") ); #if defined(UBLOX_PARSE_TIMEUTC) if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_TIMEUTC )) DEBUG_PORT.println( F("enable TIMEUTC failed!") ); state = GETTING_UTC; #else start_running(); #endif } #endif } // get_leap_seconds //-------------------------- void get_utc() { #if defined(GPS_FIX_TIME) & defined(GPS_FIX_DATE) & \ defined(UBLOX_PARSE_TIMEUTC) lock(); bool safe = is_safe(); NeoGPS::clock_t sow = GPSTime::start_of_week(); NeoGPS::time_t utc = fix().dateTime; unlock(); if (safe && (sow != 0)) { DEBUG_PORT << F("Acquired UTC: ") << utc << '\n'; DEBUG_PORT << F("Acquired Start-of-Week: ") << sow << '\n'; start_running(); } #endif } // get_utc //-------------------------- void start_running() { bool enabled_msg_with_time = false; #if defined(UBLOX_PARSE_POSLLH) if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_POSLLH )) DEBUG_PORT.println( F("enable POSLLH failed!") ); enabled_msg_with_time = true; #endif #if defined(UBLOX_PARSE_PVT) if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_PVT )) DEBUG_PORT.println( F("enable PVT failed!") ); enabled_msg_with_time = true; #endif #if defined(UBLOX_PARSE_VELNED) if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_VELNED )) DEBUG_PORT.println( F("enable VELNED failed!") ); enabled_msg_with_time = true; #endif #if defined(UBLOX_PARSE_DOP) if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_DOP )) DEBUG_PORT.println( F("enable DOP failed!") ); else DEBUG_PORT.println( F("enabled DOP.") ); enabled_msg_with_time = true; #endif #if defined(UBLOX_PARSE_SVINFO) if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_SVINFO )) DEBUG_PORT.println( F("enable SVINFO failed!") ); enabled_msg_with_time = true; #endif #if defined(UBLOX_PARSE_TIMEUTC) #if defined(GPS_FIX_TIME) & defined(GPS_FIX_DATE) if (enabled_msg_with_time && !disable_msg( ublox::UBX_NAV, ublox::UBX_NAV_TIMEUTC )) DEBUG_PORT.println( F("disable TIMEUTC failed!") ); #elif defined(GPS_FIX_TIME) | defined(GPS_FIX_DATE) // If both aren't defined, we can't convert TOW to UTC, // so ask for the separate UTC message. if (!enable_msg( ublox::UBX_NAV, ublox::UBX_NAV_TIMEUTC )) DEBUG_PORT.println( F("enable TIMEUTC failed!") ); #endif #endif state = RUNNING; trace_header( DEBUG_PORT ); } // start_running //-------------------------- bool running() { switch (state) { case GETTING_STATUS : get_status (); break; case GETTING_LEAP_SECONDS: get_leap_seconds(); break; case GETTING_UTC : get_utc (); break; } return (state == RUNNING); } // running } NEOGPS_PACKED; // Construct the GPS object and hook it to the appropriate serial device static MyGPS gps( &gpsPort ); #ifdef NMEAGPS_INTERRUPT_PROCESSING static void GPSisr( uint8_t c ) { gps.handle( c ); } #endif //-------------------------- static void configNMEA( uint8_t rate ) { for (uint8_t i=NMEAGPS::NMEA_FIRST_MSG; i<=NMEAGPS::NMEA_LAST_MSG; i++) { ublox::configNMEA( gps, (NMEAGPS::nmea_msg_t) i, rate ); } } //-------------------------- static void disableUBX() { gps.disable_msg( ublox::UBX_NAV, ublox::UBX_NAV_TIMEGPS ); gps.disable_msg( ublox::UBX_NAV, ublox::UBX_NAV_TIMEUTC ); gps.disable_msg( ublox::UBX_NAV, ublox::UBX_NAV_VELNED ); gps.disable_msg( ublox::UBX_NAV, ublox::UBX_NAV_POSLLH ); gps.disable_msg( ublox::UBX_NAV, ublox::UBX_NAV_DOP ); } //-------------------------- void setup() { // Start the normal trace output DEBUG_PORT.begin(9600); while (!DEBUG_PORT) ; DEBUG_PORT.print( F("ublox binary protocol example started.\n") ); DEBUG_PORT << F("fix object size = ") << sizeof(gps.fix()) << '\n'; DEBUG_PORT << F("ubloxGPS object size = ") << sizeof(ubloxGPS) << '\n'; DEBUG_PORT << F("MyGPS object size = ") << sizeof(gps) << '\n'; DEBUG_PORT.println( F("Looking for GPS device on " GPS_PORT_NAME) ); DEBUG_PORT.flush(); // Start the UART for the GPS device #ifdef NMEAGPS_INTERRUPT_PROCESSING gpsPort.attachInterrupt( GPSisr ); #endif gpsPort.begin(9600); // Turn off the preconfigured NMEA standard messages configNMEA( 0 ); // Turn off things that may be left on by a previous build disableUBX(); #if 0 // Test a Neo M8 message -- should be rejected by Neo-6 and Neo7 ublox::cfg_nmea_v1_t test; test.always_output_pos = false; // invalid or failed test.output_invalid_pos = false; test.output_invalid_time= false; test.output_invalid_date= false; test.use_GPS_only = false; test.output_heading = false; // even if frozen test.__not_used__ = false; test.nmea_version = ublox::cfg_nmea_v1_t::NMEA_V_4_0; test.num_sats_per_talker_id = ublox::cfg_nmea_v1_t::SV_PER_TALKERID_UNLIMITED; test.compatibility_mode = false; test.considering_mode = true; test.max_line_length_82 = false; test.__not_used_1__ = 0; test.filter_gps = false; test.filter_sbas = false; test.__not_used_2__= 0; test.filter_qzss = false; test.filter_glonass= false; test.filter_beidou = false; test.__not_used_3__= 0; test.proprietary_sat_numbering = false; test.main_talker_id = ublox::cfg_nmea_v1_t::MAIN_TALKER_ID_GP; test.gsv_uses_main_talker_id = true; test.beidou_talker_id[0] = 'G'; test.beidou_talker_id[1] = 'P'; DEBUG_PORT << F("CFG_NMEA result = ") << gps.send( test ); #endif while (!gps.running()) if (gps.available( gpsPort )) gps.read(); } //-------------------------- void loop() { if (gps.available( gpsPort )) trace_all( DEBUG_PORT, gps, gps.read() ); // If the user types something, reset the message configuration // back to a normal set of NMEA messages. This makes it // convenient to switch to another example program that // expects a typical set of messages. This also saves // putting those config messages in every other example. if (DEBUG_PORT.available()) { do { DEBUG_PORT.read(); } while (DEBUG_PORT.available()); DEBUG_PORT.println( F("Stopping...") ); configNMEA( 1 ); disableUBX(); gpsPort.flush(); gpsPort.end(); DEBUG_PORT.println( F("STOPPED.") ); for (;;); } }