A quick hack/solution for using the PointPerfect L-band service as an RTK correction source for the AgOpenGPS system

Prerequisites for this solution to work (alternatives to some of these items may work, but it is up to you to test them out!):

  • simpleRTK2B (sold by digikey or ardusimple)
  • A high quality sma to tnc cable such is this one https://www.digikey.ca/en/products/detail/siretta-ltd/asmzg500a058l13/6096481
  • a Calibrated survey GNSS Tripleband+Lband antenna(IP67) or equivalent (sold by ardusimple, digikey, mouser etc.)
  • u.fl to sma cable
  • PointPerfect L-Band Corrections Receiver NEO-D9S (sold by ardusimple)
  • A personal computer with the latest AGOPENGPS and AGIO software installed as well as a working ethernet port.
  • Teensy 4.1
  • AOG 4.1 firmware (Autosteer_gps_teensy_v4_1.ino)
  • Arduino IDE 1.8.19
  • AiO 4.1/4.2 PCB or equivalent
  • You live/work in a geographic area which offers the PointPerfect service (please refer to the official ublox site for details)
  • You have been given permission by ublox to use the service
  • A clear unobstructed view of the southern sky
  • a thingstream account with a subscription to the pointperfect L-band service
  • 1.32 SingleAntennaRover.txt (firmware for F9p. Further modifications for enabling lband service must be made to the f9p by using the ucenter program. See PointPerfect L-band Configuration for instructions on that.)
  • The SparkFun u-blox GNSS Arduino Library - v3 installed via the Arduino IDE
  1. In the same directory as the Autosteer_gps_teensy_v4_1.ino file, create a new header file called secrets.h and insert the following code to the file:
// You can set the information below after signing up with the u-blox Thingstream portal 
// and adding a new New PointPerfect Thing (L-Band or L-Band + IP)
// https://portal.thingstream.io/app/location-services/things
// In the new PointPerfect Thing, you go to the credentials tab and copy and paste the IP Dynamic Keys here.
// The keys are valid from a particular GPS Week Number and Time of Week.
// Looking at the credentials tab, the current key expires 23:59 Feb 11th 2022.
// This means the next key is valid _from_ Midnight Feb 12th 2022.
// That is GPS Week 2196. The GPS Time of Week in seconds is 518400.
// Working backwards, the current key became valid exactly 4 weeks earlier (Midnight Jan 15th 2022).
// See: https://www.labsat.co.uk/index.php/en/gps-time-calculator
// The keys are given as: 32 hexadecimal digits = 128 bits = 16 Bytes
// The next example shows how to retrieve the keys using ESP32 WiFi and MQTT.
// You can cut and paste the keys and GPS week/time-of-week from that example into here.

const uint8_t currentKeyLengthBytes =   16; 
const char currentDynamicKey[] =        "<ADD YOUR L-Band or L-Band + IP DYNAMIC KEY HERE>";
const uint16_t currentKeyGPSWeek =      2254; // Update this when you add new keys
const uint32_t currentKeyGPSToW =       0;

const uint8_t nextKeyLengthBytes =      16; 
const char nextDynamicKey[] =           "<ADD YOUR L-Band or L-Band + IP DYNAMIC KEY HERE>";
const uint16_t nextKeyGPSWeek =         2258; // Update this when you add new keys
const uint32_t nextKeyGPSToW =          0;

Add your secret credentials to the appropriate places in the file and then save the file. The steps on getting these credentials is beyond the scope of this tutorial. Please browse the ublox documentation for more information on how to acquire the keys.

  1. Add the following 3 statements somewhere at the top but after the first initial comments of the Autosteer_gps_teensy_v4_1.ino file
#include "secrets.h"
#include <SparkFun_u-blox_GNSS_v3.h>

  1. Within the same file under the Serial port comment, add the following definition:
#define mySerial Serial7
  1. To avoid any errors during compilation, make sure to change the name of ubxPacket struct definition to something unique so that it does not conflict with the ubxPacket struct definition originating from the Sparkfun GNSS v3 header file. I renamed it to ubxPacket2, but you can rename it anything you’d like:
struct ubxPacket2
  uint8_t cls;
  uint8_t id;
  uint16_t len; //Length of the payload. Does not include cls, id, or checksum bytes
  uint16_t counter; //Keeps track of number of overall bytes received. Some responses are larger than 255 bytes.
  uint16_t startingSpot; //The counter value needed to go past before we begin recording into payload array
  uint8_t *payload; // We will allocate RAM for the payload if/when needed.
  uint8_t checksumA; //Given to us from module. Checked against the rolling calculated A/B checksums.
  uint8_t checksumB;
  ////sfe_ublox_packet_validity_e valid;       //Goes from NOT_DEFINED to VALID or NOT_VALID when checksum is checked
  ////sfe_ublox_packet_validity_e classAndIDmatch; // Goes from NOT_DEFINED to VALID or NOT_VALID when the Class and ID match the requestedClass and requestedID
  1. MAKE SURE to find all instances of ubxPacket in Autosteer_gps_teensy_v4_1.ino and replace it with the unique name you gave the ubxPacket struct in step 4.

  2. Add following code just below the delay(10) line which is just after Serial.begin(baudAOG) in the Autosteer_gps_teensy_v4_1.ino file:

    Serial.println("F9P LBand Key Insertion");
  while (myGNSS.begin(mySerial) == false) //Connect to the u-blox module using Serial
    Serial.println(F("u-blox GNSS module not detected. Please check wiring."));
  Serial.println(F("u-blox GNSS module connected"));
  uint8_t ok = myGNSS.setDynamicSPARTNKeys(currentKeyLengthBytes, currentKeyGPSWeek, currentKeyGPSToW, currentDynamicKey,nextKeyLengthBytes, nextKeyGPSWeek, nextKeyGPSToW, nextDynamicKey);
  Serial.print(F("GNSS: configuration "));
  1. Once you have made the code changes above, save the file and upload it to the teensy 4.1.

  2. Plug in all of your expensive hardware to the AiO 4.1/4.2 board and then apply power to the AiO 4.1/4.2 baord.

  3. If everything is configured properly, you should eventually see an RTK fix in under a minute using the AGOPENGPS UI on your personal computer connected to the system via ethernet cable. I can confirm this is working on my own system.

IMPORTANT TO NOTE: the dynamic keys expire every 28 days. You are given two dynamic keys, so this fix should work unimpeded for a maximum time of 56 days. After day 56 you will have to edit the secrets.h with your newly updated dynamic keys. This should be a sufficient time window for anyone using it for agricultural purposes.

Lastly, keep in mind this is just a quick hack to integrating this service into the AgOpenGPS ecosystem. By no means is this the best fix, but it should allow someone who is more skilled at programming and has a better understanding of the code base to come up with something that might be worth incorporating to the official repository. Changes to the UI for dynamic key management would be a nice addition as well!

Hope this helps!

Have a happy new year everyone!


Pleased to see you got this one sorted out, sorry for not responding to your last messages.

A couple of us worked on this for a while and got it running on an R-Pi, but it all became too much of a faff for a subscription service so we abandoned it and moved back to a base / rover model using radios and a fixed reference point. It takes just a couple of minutes to deploy a radio base station which achieves the same effect and saves £360 a year. No need to spend £150 on a D9S board and a £200 L-Band antenna (BTW, these can be picked up for £70 from digikey, etc).

Yeah getting the l-band correction service to play nice with AOG was much simpler than I thought. We are just evaluating the PointPerfect service for the next year to see how it performs for agricultural use.

I am aware of the cost savings of using my own base station and I did some research on those, but our issue is that the tallest point on our property would be on the top of our grain leg. I am unsure as to whether having the base station on top of the leg would be stable enough to get a consistent reference point during a really windy day in the spring. The other issue would be the added attenuation coming in through the tnc to sma cable due to the length between the antenna and base station inside grain room. Using cellular and NTRIP server is not really reliable enough for us due to a few cellular dead zones in the fields. The only option would be to use 900 mhz radios. I have some LoRa modules and a gateway lying around but they can very limited in terms of bandwidth.

I went with that more expensive D9S module because It fits the footprint of my f9p from ardusimple. I have to work within the confines of one of those Hammond enclosures so it would be too much finicky business getting one of those cheaper modules to fit within the same enclosure as the AIO 4.1 std board.

@bluerabbit, what radios do you recommend when communicating with a base station?

We are just using the below which are pretty of much plug and play, just needs the right config dumping to the RTK2B boards:

They work well enough just so long as you have LoS. You shouldn’t need a massive pigtail between the device and antenna if you wanted to put one of these on a silo, it would be better to just run a powered USB extender to the device from a battery. Get a 12V 36ah lifepo4 battery with an inverter and it will run for a week.

I mount ours on a tripod in the field and run it off a 30,000mah 5V USB charger, runs for a good few days off one of those.

A small solar panel would power one of these.