This class provides an API to communicate with a u-blox GNSS chip. The files here were originally part of the C027_Support library (https://developer.mbed.org/teams/ublox/code/C027_Support/ at revision 138:dafbbf31bf76) but have been separated out, primarily for use on the u-blox C030 board where the cellular interace portion of the C027_Support library will instead be provided through the new mbed Cellular API.

Dependents:   example-ublox-at-cellular-interface-ext example-low-power-sleep example-C030-out-of-box-demo example-C030-out-of-box-demo ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "greentea-client/test_env.h"
00003 #include "unity.h"
00004 #include "utest.h"
00005 #include "gnss.h"
00006  
00007 using namespace utest::v1;
00008 
00009 // ----------------------------------------------------------------
00010 // COMPILE-TIME MACROS
00011 // ----------------------------------------------------------------
00012 
00013 // How long to wait for a GNSS result
00014 #define GNSS_WAIT_SECONDS 120
00015 
00016 // ----------------------------------------------------------------
00017 // PRIVATE VARIABLES
00018 // ----------------------------------------------------------------
00019 
00020 // ----------------------------------------------------------------
00021 // PRIVATE FUNCTIONS
00022 // ----------------------------------------------------------------
00023 
00024 static void printHex (char * pData, uint32_t lenData)
00025 {
00026     char * pEnd = pData + lenData;
00027     uint8_t x;
00028 
00029     printf (" 0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F\n");
00030     while (pData < pEnd) {
00031         for (x = 1; (x <= 32) && (pData < pEnd); x++) {
00032             if (x % 16 == 8) {
00033                 printf ("%02x  ", *pData);
00034             } else if (x % 16 == 0) {
00035                 printf ("%02x\n", *pData);
00036             } else {
00037                 printf ("%02x-", *pData);
00038             }
00039             pData++;
00040         }
00041 
00042 
00043         if (x % 16 !=  1) {
00044             printf("\n");
00045         }
00046     }
00047 }
00048 
00049 // ----------------------------------------------------------------
00050 // TESTS
00051 // ----------------------------------------------------------------
00052 
00053 // Test sending a u-blox command over serial
00054 void test_serial_ubx() {
00055     char buffer[64];
00056     int responseLength = 0;
00057     int returnCode;
00058     bool gotAck = false;
00059     Timer timer;
00060 
00061     GnssSerial *pGnss = new GnssSerial();
00062 
00063     // Initialise the GNSS chip
00064     pGnss->init(NC);
00065 
00066     // Try this a few times as we might get no response
00067     // if the GNSS chip is busy
00068     for (int x = 0; (x < 3) && !gotAck; x++) {
00069         // See ublox7-V14_ReceiverDescrProtSpec section 30.11.15 (CFG-NAV5)
00070         // Set automotive mode, which should be acknowledged
00071         memset (buffer, 0, sizeof (buffer));
00072         buffer[0] = 0x00;
00073         buffer[1] = 0x01; // Mask: set dynamic config only
00074         buffer[2] = 0x04; // Dynamic platform model: automotive
00075         // Send length is 32 bytes of payload + 6 bytes header + 2 bytes CRC
00076         TEST_ASSERT_EQUAL_INT (40, pGnss->sendUbx(0x06, 0x24, buffer, 32));
00077         printf ("CFG_NAV5 command sent, try %d.\n", x);
00078         timer.start();
00079         while ((!gotAck) && (timer.read_ms() < 1000)) {
00080             // Wait for the required Ack
00081             returnCode = pGnss->getMessage(buffer, sizeof(buffer));
00082             if ((returnCode != GnssSerial::WAIT) && (returnCode != GnssSerial::NOT_FOUND)) {
00083                 responseLength = LENGTH(returnCode);
00084                 if ((PROTOCOL(returnCode) == GnssSerial::UBX)) {
00085                     printHex(buffer, responseLength);
00086                     // Ack is  0xb5-62-05-00-02-00-msgclass-msgid-crcA-crcB
00087                     // Nack is 0xb5-62-05-01-02-00-msgclass-msgid-crcA-crcB
00088                     TEST_ASSERT_EQUAL_UINT8(0xb5, buffer[0]);
00089                     TEST_ASSERT_EQUAL_UINT8(0x62, buffer[1]);
00090                     TEST_ASSERT_EQUAL_UINT8(0x05, buffer[2]);
00091                     TEST_ASSERT_EQUAL_UINT8(0x00, buffer[3]);
00092                     TEST_ASSERT_EQUAL_UINT8(0x02, buffer[4]);
00093                     TEST_ASSERT_EQUAL_UINT8(0x00, buffer[5]);
00094                     TEST_ASSERT_EQUAL_UINT8(0x06, buffer[6]);
00095                     TEST_ASSERT_EQUAL_UINT8(0x24, buffer[7]);
00096                     gotAck = true;
00097                 } else if ((PROTOCOL(returnCode) == GnssSerial::NMEA)) {
00098                     printf ("%.*s", responseLength, buffer);
00099                 } else {
00100                     printHex(buffer, responseLength);
00101                 }
00102             }
00103             wait_ms (100);
00104         }
00105         timer.stop();
00106         timer.reset();
00107     }
00108 }
00109 
00110 // Test getting a response from GNSS using the serial interface
00111 void test_serial_time() {
00112     GnssSerial *pGnss = new GnssSerial();
00113 
00114     bool gotLatLong = false;
00115     bool gotElevation = false;
00116     bool gotSpeed = false;
00117     bool gotTime = false;
00118     char buffer[256];
00119     int returnCode;
00120     double latitude;
00121     double longitude;
00122     double elevation;
00123     double speed;
00124 
00125     printf("GNSS: powering up and waiting up to %d second(s) for something to happen.\n", GNSS_WAIT_SECONDS);
00126     pGnss->init();
00127 
00128     memset(buffer, 0, sizeof(buffer));
00129     for (uint32_t x = 0; (x < GNSS_WAIT_SECONDS) && !gotTime; x++)
00130     {
00131         while (((returnCode = pGnss->getMessage(buffer, sizeof(buffer))) > 0) &&
00132                 !(gotLatLong && gotElevation && gotSpeed && gotTime))
00133         {
00134             int32_t length = LENGTH(returnCode);
00135 
00136             if ((PROTOCOL(returnCode) == GnssParser::NMEA) && (length > 6))
00137             {
00138                 printf(".");
00139 
00140                 // talker is $GA=Galileo $GB=Beidou $GL=Glonass $GN=Combined $GP=GNSS
00141                 if ((buffer[0] == '$') || buffer[1] == 'G')
00142                 {
00143 #define _CHECK_TALKER(s) ((buffer[3] == s[0]) && (buffer[4] == s[1]) && (buffer[5] == s[2]))
00144                     if (_CHECK_TALKER("GLL"))
00145                     {
00146                         char ch;
00147 
00148                         if (pGnss->getNmeaAngle(1, buffer, length, latitude) &&
00149                             pGnss->getNmeaAngle(3, buffer, length, longitude) &&
00150                             pGnss->getNmeaItem(6, buffer, length, ch) &&
00151                             ch == 'A')
00152                         {
00153                             gotLatLong = true;
00154                             latitude *= 60000;
00155                             longitude *= 60000;
00156                             printf("\nGNSS: location %.5f %.5f %c.\n", latitude, longitude, ch);
00157                         }
00158                     }
00159                     else if (_CHECK_TALKER("GGA") || _CHECK_TALKER("GNS"))
00160                     {
00161                         const char *pTimeString = NULL;
00162 
00163                         // Retrieve the time
00164                         pTimeString = pGnss->findNmeaItemPos(1, buffer, buffer + length);
00165                         if (pTimeString != NULL)
00166                         {
00167                             gotTime = true;
00168                             printf("\nGNSS: time is %.6s.", pTimeString);
00169                         }
00170 
00171                         if (pGnss->getNmeaItem(9, buffer, length, elevation)) // altitude msl [m]
00172                         {
00173                             gotElevation = true;
00174                             printf("\nGNSS: elevation: %.1f.", elevation);
00175                         }
00176                     }
00177                     else if (_CHECK_TALKER("VTG"))
00178                     {
00179                         if (pGnss->getNmeaItem(7, buffer, length, speed)) // speed [km/h]
00180                         {
00181                             gotSpeed = true;
00182                             printf("\nGNSS: speed: %.1f.", speed);
00183                         }
00184                     }
00185                 }
00186             }
00187         }
00188 
00189         wait_ms(1000);
00190     }
00191 
00192     printf("\n");
00193 
00194     // Depending on antenna positioning we may not be able to get a GNSS fix but we
00195     // should at least be able to receive the time from a satellite
00196     TEST_ASSERT(gotTime);
00197 }
00198 
00199 // ----------------------------------------------------------------
00200 // TEST ENVIRONMENT
00201 // ----------------------------------------------------------------
00202 
00203 // Setup the test environment
00204 utest::v1::status_t test_setup(const size_t number_of_cases) {
00205     // Setup Greentea with a timeout
00206     GREENTEA_SETUP(120, "default_auto");
00207     return verbose_test_setup_handler(number_of_cases);
00208 }
00209 
00210 // Test cases
00211 Case cases[] = {
00212     Case("Ubx command", test_serial_ubx),
00213     Case("Get time", test_serial_time),
00214 };
00215 
00216 Specification specification(test_setup, cases);
00217 
00218 // ----------------------------------------------------------------
00219 // MAIN
00220 // ----------------------------------------------------------------
00221 
00222 int main() {
00223 
00224     return !Harness::run(specification);
00225 }
00226 
00227 // End Of File