## Saturday, 24 March 2018

### The GPS Module Drift

Lately, I've been working on a simple LoRa tracker/receiver system using cheap available parts from Ebay. One of those parts were these NEO-7M u-blox breakout boards. I don't know whether they are genuine u-blox modules or some knock-offs, either way there is plenty of them on Ebay, Aliexpress, etc. and they seem to work (a predecessor to these, NEO-6M, was part of the tracker on my very first high altitude balloon). During tests, I noticed a varying degree of drift in reported position by stationary trackers which led me to doing a couple of comparisons and measurements, and consequently this blog post.
The modules arrived with small active ceramic antennas as pictured in the image above. To save some power in case of a need, I also ordered a couple of passive 2.4GHz PCB antennas that were advertised alongside the modules. At worst I could at least use their thin cable with the IPEX connectors to make a 1.575GHz wire/dipole antenna, I thought. However, as the following tests suggest, the 2.4GHz antenna seem to work fine at GPS frequencies as well. I tried to look for more information on both antennas, but as it often is with Ebay electronics, there weren't any datasheets nor specifications to be found. I tried to at least get an idea of the radiation patterns by skimming through datasheets of similarly constructed antennas. Generally, the PCB antennas tended to radiate like half-wave dipoles (a horizontal dipole in the way I positioned the antenna in the actual test) while the ceramic patch antennas radiated in one main lobe (upwards from the top if we consider the metal part of the antenna to be the bottom).
The setup I tested with is a simple high altitude balloon tracker put together from an Arduino Pro Mini, an RFM96W LoRa module, the NEO-7M module, an LF33CV external regulator to supply 3.3V to the tracker, and a LiPo battery.
The tracker was placed outside with a decent view of the sky. The surrounding terrain isn't flat so the GPS module couldn't see all the way to the horizon.
These images show the positioning of the antennas during the tests. Aside from comparing the two antennas, I wanted to see the difference between using the u-blox module in Continuous mode (default, calculating positional solutions every second) and one of the Power Saving Modes (PSM). Specifically, I chose Cyclic mode with 5 second updates. This led to four different setups: active antenna in PSM, passive antenna in PSM, active antenna in Continuous mode, and passive antenna in Continuous mode. Each setup ran for 30 minutes, and they were scheduled in succession. I should also note that since the data was transmitted in the usual UKHAS telemetry format, the resolution of the latitude and longitude readings was processed to 5 decimal places in the tracker while the GPS modules themselves output values good to 7 decimal places. That led to a maximum resolution of 1.1m in latitude terms and 0.7m in longitude terms at the latitude I was.

uint8_t setGGArate_off[16] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x24};
uint8_t setGLLrate_off[16] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x2B};
uint8_t setGSArate_off[16] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x32};
uint8_t setGSVrate_off[16] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x39};
uint8_t setRMCrate_off[16] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40};
uint8_t setVTGrate_off[16] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x47};
// _delay_ms(100);
uint8_t setNAVmode[44]     = {0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF,
0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27,
0x00, 0x00, 0x05, 0x00, 0xFA, 0x00, 0xFA, 0x00,
0x64, 0x00, 0x2C, 0x01, 0x00, 0x3C, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x52, 0xE8};
// _delay_ms(100);


This sequence of UBX messages illustrates the common part of the GPS module initialization for all four setups. By default u-blox modules output a set of NMEA messages every second. The first six commands change their output rate to zero so that the serial interface isn't flooded by them. The last UBX message sets the GPS receiver in Airborne mode which extends its operational limits to 50km in altitude (a must in high altitude balloon application).

uint8_t setupPSM_5s[52]    = {0xB5, 0x62, 0x06, 0x3B, 0x2C, 0x00, 0x01, 0x06,
0x00, 0x00, 0x00, 0x98, 0x03, 0x00, 0x88, 0x13,
0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x01,
0x00, 0x00, 0x4F, 0xC1, 0x03, 0x00, 0x86, 0x02,
0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x64, 0x40,
0x01, 0x00, 0x4C, 0xA3};
uint8_t setPSM[10]         = {0xB5, 0x62, 0x06, 0x11, 0x02, 0x00, 0x08, 0x01,
0x22, 0x92};
// _delay_ms(100);


This is the continuation of the initialization sequence in case of the power saving setups. The first message configures the power saving mode to Cyclic tracking, 5 second update period, 0 second on time, 0 second maxStartupStateDur, sets the doNotEnterOff flag, and enables periodic RTC and Ephemeris updates. The second message then actually sets the module in the power saving mode.

uint8_t setCONT[10]        = {0xB5, 0x62, 0x06, 0x11, 0x02, 0x00, 0x08, 0x00,
0x21, 0x91};
// _delay_ms(100);


This, on the other hand, is the continuation of the common initialization sequence in case of the default high power mode. The UBX message sets the module in the Continuous mode.

uint8_t requestPVT[8]      = {0xB5, 0x62, 0x01, 0x07, 0x00, 0x00, 0x08, 0x19};


Once the GPS module is set up, the tracker enters a loop of polling UBX-NAV-PVT (the form of the request message is above), parsing the received positional data, constructing the telemetry string, transmitting the LoRa packet (0.7s), delaying for 5 seconds, and repeating the cycle. In case of the Continuous mode setup, this leads to a received packet every 6 seconds. In case of the PSM setup, the cycle is prolonged to 10 seconds once the GPS receiver enters power saving operation, because the module responds only after the update period has elapsed, i.e. every 5 seconds, regardless of when it received the UBX message requesting UBX-NAV-PVT.
And these are the results depicting the horizontal drift in case of the active antenna in PSM setup (red) and the passive antenna in PSM setup (blue). The tracker stood where the white dot is in the pictures.
The data from the active antenna in Continuous mode setup (purple) and the passive antenna in Continuous mode setup (yellow) suggest that the dominant factor in the amount of drift is the chosen mode of operation while the antenna choice is less influential in these specific conditions.
These two charts show the variation in reported altitude for individual setups. Again, the difference between PSM and Continuous mode is clear while switching between the antennas is not that apparent.

 HORIZONTAL Act PSM Pass PSM Act CON Pass CON Mean absolute deviation (white dot) 8.2m 9.5m 3.0m 3.8m Maximum absolute deviation (white dot) 33.4m 30.4m 7.3m 7.3m Mean absolute deviation around the mean 7.7m 8.2m 1.9m 2.6m Maximum absolute deviation 30.0m 25.5m 6.7m 5.4m VERTICAL Act PSM Pass PSM Act CON Pass CON Mean absolute deviation around the mean 14.1m 10.3m 2.3m 3.0m Maximum absolute deviation 70.6m 42.0m 9.2m 8.9m

This table summarizes the results of horizontal and vertical drift for individual setups. I used this mapping site to get the coordinates for where the tracker stood (the white dot). Since I am not sure about its accuracy, the table contains the mean absolute deviation and the maximum absolute deviation both with relation to this point and to the mean value of the data set. The distances between coordinates were calculated as the distance between two points on the surface of a sphere using these equations. In case of the vertical drift, I used only the mean value of the specific data set to serve as the reference.

 Setup ACQ ACQ TX PSM PSM TX Sats Active ant-PSM 51mA 107mA 30mA 87mA 7.0 Passive ant-PSM 40mA 97mA 19mA 76mA 5.9 Active ant-CONTINUOUS 51mA 107mA 43mA 99mA 8.6 Passive ant-CONTINUOUS 40mA 97mA 33mA 90mA 8.4

Finally, the counterpart to increasing accuracy is increasing power consumption. This table contains an overview of the effects that mode and antenna switching had on the current drawn from the battery. Note that these are approximate values read from a display of a bench power supply. While supplying the LF33CV regulator with 4.0V, the ACQ readings represent the initial stages when the GPS module was in acquisition mode searching and locking onto satellites. LoRa transmissions during this phase are captured in the ACQ TX column. The PSM values represent consumption during idle moments after the module transitioned to normal operation or power saving mode in case of the power saving setups. The PSM TX column then contains corresponding readings for LoRa transmissions in this phase. All in all, the cost of using the active antenna is an increase in consumption of 10-11mA while the power saving mode decreases it in the range of 13-14mA. The last column then contains an averaged number of satellites reported by the module during individual fixes. Note that since the setups weren't run at the same time, this figure may be influenced by the change in the constellation over time (satellites moving in and out of sight at the particular location). In the end, it depends on what one is after. Either lower consumption while tolerating lower accuracy, or higher precision at the cost of higher consumption.