How to send RTCM corrections via I2C for Base, Rover

I have to ZEP-F9Ps each connected to a Sparkfun Blackboard via Qwiic. Each board has an XBee shield and an XBee 3.

I have successfully configured one setup as a base with ~1.5m accuracy on its own. I can also transmit messages between the two XBees on the shields.

Using my rover Blackboard, I can output the RTCM messages to a serial console, and I see a mess of characters that looks like it should be the correction data I need. The data is also coming in at roughly 1 per second as the tutorials suggest they should. All that is left in my mind is getting that data to the rover ZED board. Since I have it connected by Qwiic, I should just be able to transmit the data using wire transmission to the default address of the ZED board, however I do not see any RTCM messages being passed to the board using uCenter.

I have read nearly every tutorial online about this and I have scoured overr github to find something that works. It sounds like there is a fair amount of difficulty getting this correction data sent to the board over I2C despite the tutorials treating it like a walk in the park problem.

All I am wondering is if there are examples where people have successfully made a base and rover setup with this method, if someone has a code snippet to properly transmit the RTCM data back to the rover via I2C,or any other advice.

Hi @AdamGronewold,

Our u-blox GNSS Arduino Library has the function you are looking for: pushRawData .

This example should get you going. It uses RELPOSNED to give you the relative position of the rover from the base. The RTCM data is received on Serial1 and pushed to the GNSS via I2C.

https://github.com/sparkfun/SparkFun_u- … mation.ino

Best wishes,

Paul

Hi @PaulZC

Thanks for getting back to me so quickly. I’ve seen a lot of your work on GitHub because of the Sparkfun library, and it really seems like an effort is being made to make the library as user friendly as possible - so thank you for being so responsive to consumers like me. Means a lot.

Apologies in advance for a long response. I just want to be thorough, both for you and for a future person who may have the same difficulties. I’d like to explain what I think is happening in code first, so that you know if I’m misunderstanding. As far as I can tell this is the section you are talking about:

#ifdef USE_SERIAL1
    uint8_t store[256];
    while ((Serial1.available()) && (numBytes < 256)) // Check if data has been received
    {
      store[numBytes++] = Serial1.read(); // Read a byte from Serial1 and store it
    }
    if (numBytes > 0) // Check if data was received
    {
      //Serial.print("Pushing ");
      //Serial.print(numBytes);
      //Serial.println(" bytes via I2C");

      myGNSS.pushRawData(((uint8_t *)&store), numBytes); // Push the RTCM data via I2C - using restarts to break up long I2C pushes
      numBytes = 0; // Reset numBytes
    }
#endif

My interpretation of the “while ((Serial.available…” line is “while we have less than 256 bytes waiting on Serial1, we should store them in ‘store’. Once we have 255 bytes, we push them to the receiver module via I2C and reset the number of bytes to zero”

I have a few questions about this:

  1. We are resetting the number of bytes to zero and waiting for 255 bytes before we send them, but the pushRawData function has conditionals to store messages 1 byte long so I2C doesn’t misinterpret it as a read. The comments there suggest that stored byte is just tacked on to the next set of bytes we push. Is this just redundancy to be safe?

  2. Do I need to modify this code to send a a received RTCM message to the module all at once?

  3. Should I transmit each RTCM message all at once? Here is the transmit code from the base, which basically follows Example3 from the library:

void SFE_UBLOX_GNSS::processRTCM(uint8_t incoming) 
{
  myXBee.write(incoming);
}

My interpretation is that I am transmitting it byte by byte. So, maybe the problem is that I am just not sending my data cleanly? Or do I need to be doing something with processRTCMframe instead? The comment ahead of processRTCMframe "RTCM 3.2 bytes look like this:

// Byte 0: Always 0xD3

// Byte 1: 6-bits of zero

// Byte 2: 10-bits of length of this packet including the first two-ish header bytes, + 6.

// byte 3 + 4 bits: Msg type 12 bits

// Example: D3 00 7C 43 F0 … / 0x7C = 124+6 = 130 bytes in this packet, 0x43F = Msg type 1087" suggests that maybe I just need to do some identification of bytes on the base side first so I can send them all at once.

  1. The comment you most recently added to that example says that we should use stops on long RTCM pushes. Could you provide some more info of when this is needed? The Sparkfun hookup guide says 1-2k bytes are transmitted each second.

Sorry for the trouble in advance; I purchased the modules because, with the library, they seemed pretty plug and play but I’m having more trouble than I expected I would. Not expecting you to babysit my code or spoon feed me a custom solution, but with how common it is to use XBee to transmit data I figured the Sparkfun code would work basically out of the box following basic configuration of the radios and GNSS modules. Thanks again Paul!

Hi again Paul,

Just to update, I am incredibly confident that my base is sending corrections in a fashion that should be manageable on the receiver side. After a few more hours of headbanging, I think I am nearing the final stage (knock on wood).

Making changes to example 5 only to include the XBee instead of serial1, and removing a few print statements to reduce size, this is the type of output I get in the console:

relPosN: 0.0000

relPosE: 0.0000

relPosD: 0.0000

relPosLength: 0

relPosHeading: 0

relPosHPN: 0

relPosHPE: 0

relPosHPD: 0

relPosHPLength: 0

accN: 0.0000

accE: 0.0000

accD: 0.0000

gnssFixOk:

diffSolution:

relPosValid:

carrier Solution Type: None

isMoving:

Pushing 63 bytes via I2C

Pushing 32 bytes via I2C

Pushing 32 bytes via I2C

Pushing 64 bytes via I2C

Pushing 64 bytes via I2C

Pushing 63 bytes via I2C

relPosN: 0.0000

relPosE: 0.0000

relPosD: 0.0000

Checking for RTCM messages in uCenter through the packet console and through message view gives me nothing. All I am seeing is NMEA.

Thanks again

Hi,

I don’t have any XBee boards to test. In fact, I don’t think I’ve ever used them. (I have used our BlueSMiRF boards, but they are quite different.) But I will try and help if I can…

Looking first at the code snippet. That code checks if new serial data is available. If it is, it will read up to 256 bytes, and then push them to the GNSS. If less than 256 bytes are available, then those bytes are still pushed (if (numBytes > 0)). If more than 256 bytes are available, then the first 256 bytes are pushed. The rest will be left in the serial RX buffer until the next pass around the loop.

Example5 is paired with Example3. Example3 generates the RTCM data on Serial1. Those two examples work well together, but Serial is a very forgiving and reliable interface. You can use it as a test. Take your XBee’s out of the loop. Do you get a differential fix using a wired serial link? If so, then you know that something about your XBee link isn’t quite right.

You cannot push a single byte to the GNSS. That confuses it as it thinks you are trying to set a register address. So pushRawBytes plays nice and stores a single byte until it next has data to push. The single bytes gets sent first.

processRTCM is indeed called every time a single RTCM character is received. You will, I think, need to buffer these and send them to XBee in ‘chunks’ of appropriate size. I would suggest reusing most of the code from the code snippet, but change it so it sends say 16 or 32 bytes at a time (whatever is appropriate for XBee - I don’t know what it expects) and includes a timeout so if you still have unsent data in your buffer and it was (say) 50 millis since you last received any data, then send what you have. You (probably) don’t need to worry about sending ‘whole’ RTCM messages, but you will need to chunkify them.

Using I2C stops vs. restarts is predominantly an ESP32 thing. The ESP32 does not support restarts, you need to end each I2C transaction with a stop. But the library now takes care of that automatically:

https://github.com/sparkfun/SparkFun_u- … pp#L57-L63

https://github.com/sparkfun/SparkFun_u- … 5854-L5862

Now then, you are using the SparkFun BlackBoard? That uses an ATMega328P processor which only has 2kBytes of RAM, and 32kBytes of program memory (flash). The GNSS library uses a lot of RAM, and what you’re trying to do with your XBee stuff needs even more. Be careful that you don’t run out of memory… If I compile Example5, I see:

Sketch uses 30982 bytes (96%) of program storage space. Maximum is 32256 bytes.

Global variables use 1176 bytes (57%) of dynamic memory, leaving 872 bytes for local variables. Maximum is 2048 bytes.

and that does not include the extra 256 bytes for the “store”. You have precious little memory left for your stack and XBee buffer. You may need to upgrade to boards with more memory. You can’t go wrong with any of our ESP32-based boards.

I hope this helps!

Paul

Hi Adam,

I’ve done a bit more reading of the XBee 3 documentation. Once you have those modules paired and set to Transparent mode, then they should work just fine.

I guess you are using SoftwareSerial to communicate with the XBee? I wonder if you are losing data that way? The processor has a lot to do when it is communicating with the GNSS module via I2C. I wonder if SoftwareSerial - which relies on interrupts - is dropping data?

The XBee 3 supports SPI as well as UART. I wonder if using SPI might be more successful? But I’m only seeing one XBee SPI Arduino library and it is years old… It looks like it could eat up many hours to get it going.

https://github.com/cjbearman/xbee-wifi-spi-arduino

I wonder if you would have more success switching to a board that supports (at least) two hardware serial ports? One for USB and a separate one for “Serial”? Looking at our boards, the Artemis RedBoard would do the job.

Best wishes,

Paul

Hi Paul,

Just starting with a sanity check. As of right now all I have in my setup is 1 Blackboard, an XBee, an XBee shield, and an RTK2 for my base. Here is the code running on the Arduino. The survey-in parameters are intentionally left extremely inaccurate, because connectivity is the main concern at the moment.

#include <SoftwareSerial.h> //communication for Xbee

#include <Wire.h> //needed for GNSS and LCD if available

#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //[http://librarymanager/All#SparkFun_u-blox_GNSS](http://librarymanager/All#SparkFun_u-blox_GNSS)



SFE_UBLOX_GNSS myGNSS;

SoftwareSerial myXBee(2, 3); // RX, TX



void setup() {

  //---------------------------------Setup-----------------------

  myXBee.begin(38400); //begin xbee on serial line

  Serial.begin(38400);

  Wire.begin(); //Join the bus as master. By default .begin() will set I2C SCL to Standard Speed mode of 100kHz

  //Wire.setClock(400000); //Optional - set I2C SCL to High Speed Mode of 400kHz



  if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port

  {

    //Serial.println("GNSS missing.");

    while (1);

  }



  //---------------------------------Configure Base Station-----------------------

  myGNSS.setI2COutput(COM_TYPE_UBX); //Set the gnss I2C port to output UBX for setup

  myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save the communications port settings to flash and BBR



  bool response = true;

  response &= myGNSS.enableRTCMmessage(UBX_RTCM_1005, COM_PORT_I2C, 1); //Enable message 1005 to output through I2C port, message every "1" seconds

  response &= myGNSS.enableRTCMmessage(UBX_RTCM_1074, COM_PORT_I2C, 1);

  response &= myGNSS.enableRTCMmessage(UBX_RTCM_1077, COM_PORT_I2C, 1);

  response &= myGNSS.enableRTCMmessage(UBX_RTCM_1084, COM_PORT_I2C, 1);

  response &= myGNSS.enableRTCMmessage(UBX_RTCM_1087, COM_PORT_I2C, 1);

  response &= myGNSS.enableRTCMmessage(UBX_RTCM_1094, COM_PORT_I2C, 1);

  response &= myGNSS.enableRTCMmessage(UBX_RTCM_1097, COM_PORT_I2C, 1);

  response &= myGNSS.enableRTCMmessage(UBX_RTCM_1124, COM_PORT_I2C, 1);

  response &= myGNSS.enableRTCMmessage(UBX_RTCM_1127, COM_PORT_I2C, 1);

  response &= myGNSS.enableRTCMmessage(UBX_RTCM_1230, COM_PORT_I2C, 10); //Enable message every 10 seconds

  //Use COM_PORT_UART1 for the above six messages to direct RTCM messages out UART1

  //COM_PORT_UART2, COM_PORT_USB, COM_PORT_SPI are also available. Use I2C to send back to Arduino

  //For example: response &= myGNSS.enableRTCMmessage(UBX_RTCM_1005, COM_PORT_UART1, 10);



  if (response == false) {

    //Serial.println("RTCM failed to enable. Frozen");

    while (1); //Freeze

  }



  //---------------------------------Start new survey-----------------------

  response = myGNSS.enableSurveyMode(90, 50); //Enable Survey in, 90 seconds, 50.0m

  //response = myGNSS.enableSurveyModeFull(86400, 2.000); //Enable Survey in, 24 hours, 2.0m

  if (response == false) {

    //Serial.println("Survey start failed. Frozen.");

    while (1);

  }

  else {

    //Serial.println("Survey started.");

  }

  

  

  //---------------------------------Wait for survey-----------------------



  while (myGNSS.getSurveyInValid() == false) // While the survey in is taking place

            //while (myGNSS.packetUBXNAVSVIN->data.valid == 0) // Or we could read valid directly

  {

    response = myGNSS.getSurveyStatus(2000); ///////Query module for SVIN status with 2000ms timeout (req can take a long time)

    if (response == true) { ////// Check if fresh data was received

      //Serial.print("Runtime:");

      //Serial.print((String)myGNSS.getSurveyInObservationTimeFull()); // Call the helper function

      

      //Serial.print(" Accuracy: ");

      //Serial.print((String)myGNSS.getSurveyInMeanAccuracy()); // Call the helper function

      ///// Read the mean accuracy directly from packetUBXNAVSVIN and manually convert from mm*0.1 to m

    }

    else

    {

      //Serial.println("SVIN request failed");

    }

  }

  //Serial.println("Base survey complete!");

  myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_RTCM3); //Set the I2C port to output UBX and RTCM sentences (not really an option, turns on NMEA as well)

}

//-------------------------------------------------------------------

void loop() 

{

  myGNSS.checkUblox(); //See if new data is available. Process bytes as they come in.

  delay(25); //Don't pound too hard on the I2C bus

}



void SFE_UBLOX_GNSS::processRTCM(uint8_t incoming) //when RTCM message is ready from ZEDF9P broadcast it with XBee

{

  myXBee.write(incoming);

  //Pretty-print the HEX values to Serial

  if (myGNSS.rtcmFrameCounter % 16 == 0) Serial.println();

  Serial.print(F(" "));

  if (incoming < 0x10) Serial.print(F("0"));

  Serial.print(incoming, HEX);

}

I’m fine from a memory standpoint on this end, thanks in part to reducing the printouts that I have. Data is being transmitted byte by byte. On the other end, I have an XBee attached to an explorer module, just to confirm that messages are not corrupted/not being fully sent. I know that is not the issue as I can see the exact same messages from u-center on the base side, as I do in XTCU on the explorer module side. As an example:

From the u-center packet console:

00:28:55 0000 D3 00 13 3E D0 00 03 83 45 2B B2 3D B5 C1 9E DA Ó…>Ð…E+²=µÁ.Ú

0010 EB 0A 35 56 60 B1 7A 3C 24 ë.5V`±z<$.

From the XBee explorer module side:

23:48:36 0000 D3 00 13 3E D0 00 03 83 45 2B B2 3D B5 C1 9E DA Ó…>Ð…E+²=µÁ.Ú

0010 EB 0A 35 56 60 B1 7A 3C 24 ë.5V`±z<$.

I believe this corresponds to RTCM 1005, so I know for certain that all of the information I need to transmit between the XBee modules is coming through. The incoming byte rate is around ~1200-1500 bytes per second, suggesting that I am also sending and receiving about as many bytes as we would expect from what is listed in the Sparkfun tutorials. I have a second version of the same code which is identical, except instead of outputting info to Serial, I have very very basic debug messages sent over Wire to an LCD. Checking that second version, I get the same info on the XBee Explorer module side, so I know that there aren’t any problems being caused by both the LCD and RTK2 communicating over I2C. In short I am almost entirely confident that my base setup is fine and my radio setup is fine. I can plug my headless version into a power source, the XBee into my computer, and the data is sent no problemo.

Adding in the second Arduino, attaching the XBee with an XBee shield, and running the following code:

int count=0;

void setup()

{

Serial.begin(38400);

while (!Serial); //Wait for user to open terminal

myXBeeRover.begin(38400);

Wire.begin();

}

void loop()

{

if (myXBeeRover.available()) {

Serial.print(myXBeeRover.read(), HEX);

Serial.print(" ");

count++;

if (count%16==0) Serial.println();

}

delay(25);

}[/code]

gives me something like

D3 0 14 FE 80 1 0 0 0 65 3E BF 29 C0 0 0 1 1 0 0 0 0 0 29 79 31

. Looks a lot like an RTCM message (not sure which one). So at this point I should be able to connect the RTK2 to the Blackboard by I2C or serial. No? Looking closer at the Artemis Redboard - looks like my Redboard is an older version. This new version has two serial lines? If that is really what will make the difference I will purchase it, but I want to be confident that is going to resolve my problem.

Last update for the evening, otherwise I will go mad with this thing. I have an Arduino Mega, which I tried. Still sending data from the XBee to the Arduino using SoftwareSerial, since the Sparkfun XBee breakout only allows me to communicate on pins 0, 1 or 2, 3. Then from the Arduino, I use the Serial1 pins to write the data to UART2 on the RTK2. No luck.

Hi Adam,

Thanks for the private message. Let’s continue our discussion here then everyone can benefit. Also, I’m in the UK, which doesn’t help.

First a note about boards and voltages:

You need to be careful about the voltage of the boards you are using. The BlackBoard C (SPX-16282) is a good choice as you can switch between 3.3V I/O and 5V I/O. Always use 3.3V. The Qwiic connector has a separate voltage level shift circuit which means Qwiic is always 3.3V even when you have 5V I/O selected. But, again, always use 3.3V. The UART, I2C and Qwiic connections on our ZED-F9P boards are all 3.3V. They have protection resistors which will prevent most badness, but, again, always use 3.3V.

The XBee Shield (WRL-12847) also has a level shifter circuit on its TX and RX signals, so that can work with 5V I/O too. Again, 3.3V is preferred.

The ATmega board you have is probably 5V only. Do be careful there. If you try to connect its I2C or extra UART pins directly to the ZED-F9P board, you may be putting a 5V signal onto a 3.3V pin…

SoftwareSerial is not completely reliable, especially at higher baud rates. But, I agree, your data does look clean. Hardware serial ports are always preferable. The Artemis RedBoard has separate hardware UART for the USB connection and for the TX and RX pins. And it is all 3.3V. But don’t rush out and buy new boards just yet. We’re not there yet. We need to figure out why you are having RTCM issues.

OK. Trying to replicate your issue:

I’m struggling a bit because I only have one 3.3V RedBoard (ATmega328), one ZED-F9P and one ZED-F9R. I will run Example3 on the RedBoard with the ZED-F9P connected via Qwiic. I will create a SoftwareSerial port and output the RTCM data on that. The example uses Serial1, I’m replacing this with SoftwareSerial. This is the same thing you do with your XBee. I will then connect the SoftwareSerial TX pin on the RedBoard directly to the UART2 RX pin on the ZED-F9R. I will not hook up the SoftwareSerial RX pin to minimize the work the ATmega needs to do. I will also connect GND to GND. If the RTCM data is generated correctly, I should see the F9R go into RTK Floating mode, maybe even Fixed. I will use u-center so I can watch first the NAV-SVIN on the F9P, then MON-COMMS on the F9R.

Success! I had to cut the example code to the bone to make it fit. I actually deleted all Serial code to save memory. It’s a bit unnerving working blind, but needs must. I did a 60s, 5.0m survey-in. I watched NAV-SVIN with u-center and watched the survey complete. The RTK LED on the F9R went off almost immediately. I then switched u-center over to the F9R and NAV-PVT shows I have a Floating solution. MON-COMMS shows lots of RTCM3 messages arriving on UART2.

OK. This is all good. We need to get you to the same place. After that, the next steps will be to: add in a second BlackBoard so you are receiving RTCM with SoftwareSerial; then, finally, put the XBees back into the system.

I will attach the cut-down Example3 code here in case it is useful.

I have dual-band antennas connected to both ZEDs. Both antennas are outside with a good (not perfect) view of the sky.

I need to pop out for a while. When I get back I will see if I can get SoftwareSerial RX working. I will configure the ZED-F9P to output RTCM on UART2. Then I will connect the RedBoard to the ZED-F9R and modify Example5 for SoftwareSerial. If I can receive RTCM from the F9P UART2 with SoftwareSerial and push it to the F9R via I2C, then I’m replicating what you are trying to do - just without the XBees.

Until later,

Paul

Example3_StartRTCMBase_SoftwareSerial.zip (2.28 KB)

OK. I’ll document this in real time as I go.

I have the RedBoard connected to the ZED-F9P. The RB is still running the modified Example3. It is outputting RTCM on SoftwareSerial. The ZED-F9R is stand-alone. It is receiving the RTCM on UART2 RX. It has a fixed solution.

I’m connecting u-center to the F9P. I’m going to manually configure it to output RTCM on its UART2. Then I can disconnect the RB. Opening u-center:

Using View \ Message View

Open UBX-CFG-PORT

Set the Target to UART2

I see that Protocol Out is 5-RTCM3

That’s OK.

I need to manually enable RTCM 1005, 1074, 1084, 1094, 1124 and 1230

I select UBX-CFG-MSG

I select F5-05 RTCM3.3 1005, I tick UART2 and leave the rate box set to 1. I click Send at the bottom of the window.

I repeat for 1074, 1084, 1094 and 1124. All using a rate of 1.

They’re all enabled on I2C too. I do not disable those.

I repeat for 1230 but set the rate to 10.

I check UBX-MON-COMMS. I see the UART2 Tx Total increasing each time I click Poll. That shows something is being transmitted.

I move my jumper wire from the RB SS TX (Pin 3) over to the F9P UART2 TX pin. F9P UART2 TX is now connected to F9R UART2 RX. I connect GND on the F9P to GND on the F9R.

The F9R RTK LED is still off. That’s good.

I close the u-center port for the F9P and open the port for the F9R. I check UBX-MON-COMMS and I can see RTCM3 messages being received on UART2. The count increases each time I click Poll. UBX-NAV-PVT shows a Fixed Carrier Range. Even better.

OK. All. good. Time to disconnect the RedBoard. I disconnect the Qwiic cable. The RB and both ZEDs are still powered on via USB.

I hastily modify Example5, stripping out all Serial code and replacing the Serial1 code with SoftwareSerial. I will attach the code here.

I upload the new code onto the RedBoard. I let it run. Now I connect the RB to the ZED-F9R via Qwiic. I reset the RB to restart the code. It won’t do anything as I have not yet connected anything to pin 2.

Check the F9R via u-center. I still have a fixed solution. The MON-COMMS UART2 RTCM3 count is still increasing.

OK. I now move the serial jumper wire. I connect F9P UART2 TX to the RB pin 2 (RX). I have RB GND connected to F9R GND via the Qwiic cable. I have F9P GND connected to RB GND via a jumper wire.

The RB should now be receiving RTCM from the F9P via SoftwareSerial on pin 2, and pushing it to the F9R via I2C. Is that happening?

The RTK LED on the F9R has come back on. That’s not good.

I check the F9R with u-center. The F9R is not talking… Have I done something silly?

I turn off the F9R and the RedBoard. I restart the RedBoard. It provides power to the F9R via the Qwiic cable.

I reconnect to the F9R via u-center and USB. It’s still not happy.

I forgot to include myGNSS.checkUblox(); in the modified Example5 loop. I add that.

OK. The F9R is talking to u-center. I check UBX-MON-COMMS. I see the SKIPPED count on I2C RX increasing quickly. The I2C RTCM RX count is increasing, but only very slowly and mostly not at all.

Not good.

I’m trying to push the RTCM data 32 bytes at a time. store is char[32]. Is that too much? I change to 16 bytes.

Same thing. I see mostly SKIPPED. Very few RTCM3 RX counts…

This makes me think that SoftwareSerial RX cannot cope…

How do I prove this?

The RedBoard I’m using is this one: https://www.sparkfun.com/products/15123 . It can do 3.3V or 5V via a solder jumper.

It’s a bit extreme but we’re trying to get to the bottom of this. I cut the track which links the D0 RX header pin to the TXO Pin2 on the CH340. I add a single header pin onto the RX LED Cathode. I can then use a jumper wire to connect CH340 TXO from the RX LED to the ATmega328 D0 RX Pin30 when I want to upload new code. When I disconnect the jumper, I can use the ATmega328 RX for hardware Serial. I don’t care or worry about the ATmega328 TX to CH340 RXI connection.

OK. Hacking done. Code modified for Serial instead of SoftwareSerial and uploaded. Jumper disconnected. Reconnect the F9R via Qwiic. Reset the RB. Connect the F9P UART2 TX to RedBoard D0 RX - which I can now thanks to my hardware hackery.

F9R RTK LED went out almost immediately.

I check the F9R MON-COMMS with u-center. Success. I see zero SKIPPED I2C RX messages. And about 10 RTCM3 RX messages per second. NAV-PVT shows the F9R has a Fixed carrier solution.

Ta da!!

From all of this, we can conclude that: SoftwareSerial TX is OK for RTCM. But SoftwareSerial RX fails for RTCM - if you’re trying to push to I2C at the same time… On an ATmega328(P). At 38400 baud.

Buy yourself a pair of Artemis RedBoards and you should be good to go:

https://www.sparkfun.com/products/15444

Interesting challenge. I enjoyed that. And I hope this helps you sleep easy…!

Best wishes,

Paul

Example5_RelativePositioningInformation_SoftwareSerial.zip (1.86 KB)

I appreciate you being so patient with me. Honestly didn’t expect to get this much assistance from the forum, so at the very least it doesn’t feel like my $600+ purchase is going to waste. I was pretty worried on Monday evening!! You’re the best Paul.

Ok - I am going to try following along to what you did almost exactly so that I am checking the same things you have. Starting with your first message. On the base side, I simply keep the Blackboard, ZED-F9P configured as a base, the XBee shield on SoftwareSerial, and I run the same code that you sent as a zip. I then connect the rover ZED-F9P UART2 RX pin to the base SoftwareSerial TX pin. The RTK LED on the receiver side does not change at all. For the same module, in u-center. I see the following under MON-COMM:


Promising at the very least!

And under RXM-RTCM I see the following:


It looks like it is receiving all the messages it should, but it is passing over all messages other than 1005 and 1230. Maybe this is why a fix is not being achieved. And just to confirm, under NAV-PVT my position fix type is “No Fix”.

For both modules I am using dual band antennas from Trimble. Pretty high end antennas.

Continuing in another message…

Few hours later…

I brought the system out to have a better view of the sky. I am now receiving the RTCM messages over UART2 and they are now being used. NAV-PVT fix says “3D Fix”. So the next step is for me to reincorporate the radio modules and second Blackboard. The RTK LED is slowly blinking on and off. Carrier Range status is “Float”.

Ok. So I’ve reincorporated the second Blackboard with its XBee. I tried to follow along with what you are doing to finally get the data back to the RTK2 over I2C, but still no success. Connecting the receiver UART2 RX pin to the SoftwareSerial RX pin gives me what I need, so I think I will be able to avoid purchasing a RedBoard. Basically the XBee is just bypassing the Blackboard and the RTK2 is listening in on the line it would use to send data back to the Blackboard.

Paul - thank you so much!! and Sparkfun - give this man a raise! This was beginning to look nightmarish a few days ago, but I finally have corrections on my receiver, even if it wasn’t in the way I originally intended.

I am going to add some images and files of my final setup for anyone who may stumble upon the thread (and for me to look back at) even though most of it is the same as what you have Paul.

For the base:

Survey-In (BASE) Config.txt (25 KB)

RTK_Base.zip (4.92 KB)

And for the rover:

Rover Config.txt (25 KB)

RTK_Rover.zip (4.13 KB)

Thanks again Paul!

Hi Adam,

Yay! Success! Nice job. The way you’ve bent those jumper wires clearly indicates an engineer with high standards… :wink:

Taking SoftwareSerial out of the loop is a good solution. Just to be clear - for anyone else reading this - you have connected the XBee Out directly to the ZED-F9P UART2 RX (RX2 Input). You have the XBee set to 38400 baud so you can ‘pipe’ the RTCM data directly to the ZED. On the XBee Shield, you have the switch set to “DLINE”. XBee Out is then connected to D2, and that’s where you’ve attached your jumper wire. The second jumper wire is GND - GND.

D2 would normally be your SoftwareSerial RX pin, but, for the reasons discussed above, SoftwareSerial RX is not reliable / useable for this project. The ATmega328 cannot run SoftwareSerial RX and I2C transfers reliably for RTCM at the same time.

A small word of caution though. Looking closely at the schematic for the XBee Shield, the 3.3V XBee serial signals are level-shifted up to 5V by Q1 and Q2. The signal on your jumper wire is actually 5V, not 3.3V as needed by the ZED-F9P. You are saved by the fact that the signal is ‘driven’ by a 1K resistor. It would be better if you connected your jumper wire to the DOUT breakout pad under the XBee module. That is true 3.3V.

https://cdn.sparkfun.com/datasheets/Wir … ld_v15.pdf

Taking the antennas outdoors was the right thing to do. I’ve just repeated the test here and I see all RTCM messages being used. I did a 60 second, 5m survey-in on the ZED-F9P. The ZED-F9R is using all messages (see images below) and now has a fixed carrier solution. If your antennas have a poor view of the sky and/or your survey-in is not accurate enough, the Rover may not be able to use the corrections as they are too inaccurate. I think that explains what you were seeing in RXM-RTCM earlier.

Another note for anyone else reading this, you need to enable UBX-RXM-RTCM in u-center. You cannot Poll it. Open View \ Messages View, select UBX-CFG-MSG. Select 02-32 RXM-RTCM and tick which port(s) you want to enable it on. Click Send at the bottom of the screen to enable the message. Then when you go to UBX-RXM-RTCM, you will see the data in the attached screenshot.

Good luck with your project Adam - I’ve enjoyed our problem-solving. I know others will find it useful too.

Best wishes,

Paul

Screenshot 2022-05-20 085300.jpg

PS: Here’s my “aide memoire” for the RTK LED:

oN is No RTK fix

FLashing is FLoat RTK fix

ofF is Fixed RTK fix