#include //====================================================================== // Program: NMEAdiagnostic.ino // // Description: This program tries different baud rates until // valid NMEA sentences are detected. Some GPS devices may // have a binary mode that does not emit NMEA sentences. You // may have to send a special command or use a utility program // to configure it to emit NMEA sentences instead of binary messages. // // Prerequisites: // 1) Your GPS device has been correctly powered. // Be careful when connecting 3.3V devices. // 2) Your GPS device is correctly connected to an Arduino serial port. // See GPSport.h for the default connections. // // '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 configuration #ifndef NMEAGPS_RECOGNIZE_ALL #error You must define NMEAGPS_RECOGNIZE_ALL in NMEAGPS_cfg.h! #endif #ifdef NMEAGPS_IMPLICIT_MERGING #error You must *undefine* NMEAGPS_IMPLICIT_MERGING in NMEAGPS_cfg.h! \ Please use EXPLICIT or NO_MERGING. #endif #ifdef NMEAGPS_INTERRUPT_PROCESSING #error You must *NOT* define NMEAGPS_INTERRUPT_PROCESSING in NMEAGPS_cfg.h! #endif static NMEAGPS gps ; // This parses received characters static gps_fix all_data ; // A composite of all GPS data fields static uint32_t last_rx = 0UL; // The last millis() time a character was // received from GPS. static uint32_t valid_sentence_received = 0UL; static bool last_sentence_received = false; static uint32_t baudStartTime = 0UL; static uint8_t warnings = 0; static uint8_t errors = 0; //-------------------------- static void hang() { DEBUG_PORT.println( F("\n** NMEAdiagnostic completed **\n") ); if (warnings) { DEBUG_PORT.print( warnings ); DEBUG_PORT.print( F(" warnings") ); } if (warnings && errors) DEBUG_PORT.print( F(" and ") ); if (errors) { DEBUG_PORT.print( errors ); DEBUG_PORT.print( F(" errors") ); } if (warnings || errors) DEBUG_PORT.println(); DEBUG_PORT.flush(); for (;;) ; } // hang //-------------------------- // Baud rates to check static long baud_table[] = { 1200, 2400, 4800, 9600, 14400, 19200, 28800, 31250, 38400, 57600, 115200 }; static const uint8_t num_bauds = sizeof(baud_table)/sizeof(baud_table[0]); static const uint8_t INITIAL_BAUD_INDEX = 3; // 9600 static uint8_t baud_index = INITIAL_BAUD_INDEX; static bool triedDifferentBaud = false; //-------------------------- static void tryBaud() { long baud = baud_table[baud_index]; DEBUG_PORT.print( F("\n____________________________\n\nChecking ") ); DEBUG_PORT.print( baud ); DEBUG_PORT.print( F(" baud...\n") ); DEBUG_PORT.flush(); //if (baud == 9600) baud = 17000; gpsPort.begin( baud ); baudStartTime = millis(); } // tryBaud //-------------------------- static void tryAnotherBaudRate() { gpsPort.end(); while (gpsPort.available()) gpsPort.read(); if (baud_index == INITIAL_BAUD_INDEX) { baud_index = 0; } else { baud_index++; if (baud_index == INITIAL_BAUD_INDEX) baud_index++; // skip it, we already tried it if (baud_index >= num_bauds) { baud_index = INITIAL_BAUD_INDEX; DEBUG_PORT.print( F("\n All baud rates tried!\n") ); hang(); } } tryBaud(); triedDifferentBaud = true; } // tryAnotherBaudRate //------------------------------------ static const uint16_t MAX_SAMPLE = 256; static uint8_t someChars[ MAX_SAMPLE ]; static uint16_t someCharsIndex = 0; static void dumpSomeChars() { if (someCharsIndex > 0) { DEBUG_PORT.print( F("Received data:\n") ); const uint16_t bytes_per_line = 32; char ascii[ bytes_per_line ]; uint8_t *ptr = &someChars[0]; for (uint16_t i=0; i 1000UL; if ((ms_since_last_rx > 5) && waited_long_enough) { // The GPS device has not sent any characters for at least 5ms. // See if we've been getting chars sometime during the last second. // If not, the GPS may not be working or connected properly. bool getting_chars = (someCharsIndex > 0); // Try to diagnose the problem static uint8_t tries = 1; bool tryNext = false; if (!getting_chars) { if (tries++ >= 3) { errors++; DEBUG_PORT.println( F("\nCheck GPS device and/or connections. No data received.\n") ); tryNext = true; } } else if (valid_sentence_received) { uint8_t s = valid_sentence_received/1000; uint8_t ms = valid_sentence_received - s*1000; DEBUG_PORT.print( F("Valid sentences were received ") ); DEBUG_PORT.print( s ); DEBUG_PORT.print( '.' ); if (ms < 100) DEBUG_PORT.print( '0' ); if (ms < 10) DEBUG_PORT.print( '0' ); DEBUG_PORT.print( ms ); DEBUG_PORT.println( F(" seconds ago.\n" " The GPS update rate may be lower than 1Hz,\n" " or the connections may be bad." ) ); displaySentences(); hang(); } else { DEBUG_PORT.println( F("No valid sentences, but characters are being received.\n" " Check baud rate or device protocol configuration.\n" ) ); dumpSomeChars(); delay( 2000 ); tryNext = true; } if (tryNext) { tries = 1; tryAnotherBaudRate(); valid_sentence_received = 0UL; } } } // listenForSomething //------------------------------------ static void GPSloop() { while (gpsPort.available()) { last_rx = millis(); uint8_t c = gpsPort.read(); if (someCharsIndex < MAX_SAMPLE) someChars[ someCharsIndex++ ] = c; if (gps.decode( c ) == NMEAGPS::DECODE_COMPLETED) { all_data |= gps.fix(); valid_sentence_received = last_rx; if (gps.nmeaMessage == LAST_SENTENCE_IN_INTERVAL) last_sentence_received = true; DEBUG_PORT.print( F("Received ") ); DEBUG_PORT.println( gps.string_for( gps.nmeaMessage ) ); static uint8_t sentences_printed = 0; bool long_enough = (millis() - baudStartTime > 3000); if (long_enough || ( (sentences_printed++ >= 20) && (someCharsIndex >= MAX_SAMPLE) ) ) { displaySentences(); hang(); } } } if (!valid_sentence_received || (millis() - valid_sentence_received > 3000UL)) listenForSomething(); } // GPSloop //-------------------------- void setup() { DEBUG_PORT.begin(9600); while (!DEBUG_PORT) ; DEBUG_PORT.print( F("NMEAdiagnostic.INO: started\n") ); DEBUG_PORT.println( F("Looking for GPS device on " GPS_PORT_NAME) ); if (sizeof(gps_fix) <= 2) { warnings++; DEBUG_PORT.print( F("\nWarning: no fields are enabled in GPSfix_cfg.h.\n Only the following information will be displayed:\n ") ); trace_header( DEBUG_PORT ); } #if !defined( NMEAGPS_PARSE_GGA ) & !defined( NMEAGPS_PARSE_GLL ) & \ !defined( NMEAGPS_PARSE_GSA ) & !defined( NMEAGPS_PARSE_GSV ) & \ !defined( NMEAGPS_PARSE_RMC ) & !defined( NMEAGPS_PARSE_VTG ) & \ !defined( NMEAGPS_PARSE_ZDA ) & !defined( NMEAGPS_PARSE_GST ) warnings++; DEBUG_PORT.println( F("\nWarning: no messages are enabled for parsing in NMEAGPS_cfg.h.\n No fields will be valid, including the 'status' field.") ); #endif DEBUG_PORT.flush(); tryBaud(); } // setup //-------------------------- void loop() { GPSloop(); }