I have two SparkFun GPS-RTK2 and two arduino uno board.
Then, I connect each SparkFun GPS-RTK2 to each arduino uno board. I call them base station and rover station.
There is no problem to get RTCM correction data from A and send them to arduino uno of rover station.
https://portal.u-blox.com/sfc/servlet.s … cR4&page=0COM3 data is RTCM correction data and CRC test result of base station RTCM correction data.
COM4 data is RTCM correction data on rover arudino Uno come from base station by using Uart wireless communication and CRC test result of rover station RTCM correction data.
There are no problem.
and I send RTCM correction data from rover arduino Uno to gps module by using I2C communication.
but, rover gps module can’t go into RTK mode.
so, i check which data that rover gps module get by using u-center.
https://portal.u-blox.com/sfc/servlet.s … clm&page=0
https://portal.u-blox.com/sfc/servlet.s … clr&page=0
I check msg 1005, 1230(relatively short data packet) pass crc test , but 1074,1084,1094, 1124 can’t pass CRC test.
How solve this problem??
I attached base arduino code and rover arduino code.
base arduino code
/*
Send UBX binary commands to enable RTCM sentences on Ublox ZED-F9P module
By: Nathan Seidle
SparkFun Electronics
Date: January 9th, 2019
License: MIT. See license file for more information but you can
basically do whatever you want with this code.
This example does all steps to configure and enable a ZED-F9P as a base station:
Begin Survey-In
Once we've achieved 2m accuracy and 300s have passed, survey is complete
Enable six RTCM messages
Begin outputting RTCM bytes
Feel like supporting open source hardware?
Buy a board from SparkFun!
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
NEO-M8P RTK: https://www.sparkfun.com/products/15005
SAM-M8Q: https://www.sparkfun.com/products/15106
Hardware Connections:
Plug a Qwiic cable into the GPS and a BlackBoard
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
Open the serial monitor at 115200 baud to see the output
*/
#include <Wire.h> //Needed for I2C to GPS
#include <SoftwareSerial.h>
#include "SparkFun_Ublox_Arduino_Library.h" //http://librarymanager/All#SparkFun_Ublox_GPS
SoftwareSerial S2(2,3); // 2:RX 3:TX // added to send RTCM3 format data packet to rover arduino by using HC-11 ( wireless uart communication)
SFE_UBLOX_GPS myGPS;
int sum = 0;
int cnt = 1;
int num = 0;
uint8_t test[200]={0,}; // RTCM3 format data packet
void setup()
{
Serial.begin(9600); // 115200 -> 9600
S2.begin(9600); // wireless uart communication baud rate
S2.flush();
while (!Serial); //Wait for user to open terminal
Serial.println("Ublox Base station example");
Wire.begin();
Wire.setClock(400000); //Increase I2C clock speed to 400kHz
if (myGPS.begin() == false) //Connect to the Ublox module using Wire port
{
Serial.println(F("Freezing."));
while (1);
}
myGPS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
//myGPS.saveConfiguration(); //Save the current settings to flash and BBR
while (Serial.available()) Serial.read(); //Clear any latent chars in serial buffer
Serial.println("Press any key");
while (Serial.available() == 0) ; //Wait for user to press a key
boolean response = true;
response &= myGPS.enableRTCMmessage(UBX_RTCM_1005, COM_PORT_I2C, 1); //Enable message 1005 to output through I2C port, message every second
response &= myGPS.enableRTCMmessage(UBX_RTCM_1074, COM_PORT_I2C, 1);
response &= myGPS.enableRTCMmessage(UBX_RTCM_1084, COM_PORT_I2C, 1);
response &= myGPS.enableRTCMmessage(UBX_RTCM_1094, COM_PORT_I2C, 1);
response &= myGPS.enableRTCMmessage(UBX_RTCM_1124, COM_PORT_I2C, 1);
response &= myGPS.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
//For example: response &= myGPS.enableRTCMmessage(UBX_RTCM_1005, COM_PORT_UART1, 10);
if (response == true)
{
Serial.println("RTCM messages enabled");
}
else
{
Serial.println("RTCM failed to enable. Are you sure you have an ZED-F9P?"); //
while (1); //Freeze
}
//Check if Survey is in Progress before initiating one
response = myGPS.getSurveyStatus(2000); //Query module for SVIN status with 2000ms timeout (request can take a long time)
if (response == false)
{
Serial.println("b?"); //Failed to get Survey In status
while (1); //Freeze
}
if (myGPS.svin.active == true)
{
Serial.print("in"); //Survey already in progress.
}
else
{
//Start survey
//The ZED-F9P is slightly different than the NEO-M8P. See the Integration manual 3.5.8 for more info.
//response = myGPS.enableSurveyMode(300, 2.000); //Enable Survey in on NEO-M8P, 300 seconds, 2.0m
response = myGPS.enableSurveyMode(60, 5.000); //Enable Survey in, 60 seconds, 5.0m
if (response == false)
{
Serial.println("fai"); // Survey start failed
while (1);
}
Serial.println("Survey started."); // This will run until 60s has passed and less than 5m accuracy is achieved.
}
while(Serial.available()) Serial.read(); //Clear buffer
//Begin waiting for survey to complete
while (myGPS.svin.valid == false)
{
if(Serial.available())
{
byte incoming = Serial.read();
if(incoming == 'x')
{
//Stop survey mode
response = myGPS.disableSurveyMode(); //Disable survey
Serial.println("Survey stopped");
break;
}
}
response = myGPS.getSurveyStatus(2000); //Query module for SVIN status with 2000ms timeout (req can take a long time)
if (response == true)
{
Serial.print("Press x to end survey - ");
Serial.print("Time elapsed: ");
Serial.print((String)myGPS.svin.observationTime);
Serial.print(" Accuracy: ");
Serial.print((String)myGPS.svin.meanAccuracy);
Serial.println();
}
else
{
Serial.println("SVIN request failed");
}
delay(1000);
}
Serial.println("Survey valid!");
myGPS.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)
// Serial.println(myGPS.getCarrierSolutionType());
}
void loop()
{
myGPS.checkUblox(); //See if new data is available. Process bytes as they come in.
delay(250); //Don't pound too hard on the I2C bus
}
//This function gets called from the SparkFun Ublox Arduino Library.
//As each RTCM byte comes in you can specify what to do with it
//Useful for passing the RTCM correction data to a radio, Ntrip broadcaster, etc.
void SFE_UBLOX_GPS::processRTCM(uint8_t incoming)
{
//Let's just pretty-print the HEX values for now
//if(incoming == 0xD3)
if(myGPS.rtcmFrameCounter == 1)
{
//S2.write("ba"); //hex - b (62), a(61) // added to inform start of packet to rover arduino
test[0] = 'b';
test[1] = 'a';
sum = 0;
}
if(myGPS.rtcmFrameCounter+1 > 180) return;
test[myGPS.rtcmFrameCounter+1] = incoming;
sum += incoming;
if(myGPS.rtcmLen == myGPS.rtcmFrameCounter)
{
// hex - g (67), h(68)
cnt = 1;
test[myGPS.rtcmLen+2] = 'i';
test[myGPS.rtcmLen+3] = 'j';
S2.write(test,myGPS.rtcmLen+4);
for(int i=0;i<myGPS.rtcmLen+4;i++)
{
Serial.print(test[i], HEX);
Serial.print(" ");
}
delay(1);
Serial.println("");
Serial.println(sum);
}
}
rover arduino code
/*
Send UBX binary commands to enable RTCM sentences on Ublox ZED-F9P module
By: Nathan Seidle
SparkFun Electronics
Date: January 9th, 2019
License: MIT. See license file for more information but you can
basically do whatever you want with this code.
This example shows how to query the module for RELPOS information in the NED frame.
It assumes you already have RTCM correction data being fed to the receiver.
Feel like supporting open source hardware?
Buy a board from SparkFun!
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
NEO-M8P RTK: https://www.sparkfun.com/products/15005
SAM-M8Q: https://www.sparkfun.com/products/15106
Hardware Connections:
Plug a Qwiic cable into the GPS and a RedBoard Qwiic or BlackBoard
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
Open the serial monitor at 115200 baud to see the output
*/
#include <Wire.h> //Needed for I2C to GPS
// ㅡㅡㅡㅡㅡㅡadded ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#include <SoftwareSerial.h>
uint8_t ch;
uint8_t cnt = 0;
int flag = 1;
uint8_t test[200] = {0,};
int num;
float lastTime = 0;
int sum = 0;
int sum2 = 0;
// ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#include "SparkFun_Ublox_Arduino_Library.h" //http://librarymanager/All#SparkFun_Ublox_GPS
SFE_UBLOX_GPS myGPS;
SoftwareSerial S2(2,3); // 2:RX 3:TX // added
void setup()
{
Serial.begin(9600); // modified (115200 -> 9600)
S2.begin(9600); // added
S2.flush(); // added
while (!Serial); //Wait for user to open terminal
Serial.println("Ublox Base station example");
Wire.begin();
Wire.setClock(400000); //Increase I2C clock speed to 400kHz
if (myGPS.begin() == false) //Connect to the Ublox module using Wire port
{
Serial.println(F("Ublox GPS not detected at default I2C address. Please check wiring. Freezing."));
while (1);
}
myGPS.setI2COutput(COM_TYPE_UBX|COM_TYPE_NMEA); // get NMEA, UBX format data from gps module
//Configure a given port to input UBX, NMEA, RTCM3 or a combination thereof
//Port 0=I2c, 1=UART1, 2=UART2, 3=USB, 4=SPI
//Bit:0 = UBX, :1=NMEA, :5=RTCM3
myGPS.setPortInput(0, 0x23); // send rtcm3 data to gps module
// 코드 안 넣음 : 값 받음
// 0x01, 0x21, 0x23 : 값 받음
// Serial.println(myGPS.getCarrierSolutionType());
}
bool flag_b_wait = true;
bool flag_a_wait = true;
int cnt_rcv = 0;
int rcvlen = 0;
int loopcnt = 0;
void loop()
{
// in base arduino code, i send "ba" to inform start of data packet.
if(S2.available())
{
ch = S2.read();
// ch = b 체크
if(flag_b_wait == true)
{
if(ch == 'b')
{
flag_b_wait = false;
}
return;
}
// ch = a 체크
if(flag_b_wait == false && flag_a_wait == true)
{
if(ch == 'a')
{
flag_a_wait = false;
cnt_rcv = 0;
}
else
{ // 연속이 아니어서 다시 b wait로 복귀
flag_a_wait = true;
flag_b_wait = true;
}
return;
}
// 정상문자 저장
if(flag_b_wait == false && flag_a_wait == false && cnt_rcv < 200)
{
test[cnt_rcv] = ch;
// 마지막 문자 체크
if(cnt_rcv >= 1 && test[cnt_rcv-1] == 'i' && test[cnt_rcv] == 'j')
{
goto jmp1;
}
cnt_rcv++;
if(cnt_rcv >=200)
{
flag_a_wait = true;
flag_b_wait = true;
}
return;
}
else
{
flag_a_wait = true;
flag_b_wait = true;
return;
}
//flag_a_wait = true;
//flag_b_wait = true;
//return;
} // if(S2.available())
return;
jmp1 :
flag_a_wait = true;
flag_b_wait = true;
rcvlen = cnt_rcv + 1;
Serial.print(rcvlen);
Serial.print(" ");
for(int i =0; i<rcvlen-2; i++)
{
Serial.print(test[i], HEX);
Serial.print(" ");
sum2 += test[i];
}
Serial.println();
Serial.println(sum2);
sum2 = 0;
Wire.beginTransmission(0x42);
Wire.write(0xFF);
Wire.write(test,rcvlen-2);
//delay(1);
Wire.endTransmission();
//delay(10);
/*
while(Wire.available())
{
Serial.print("시작");
ch = Wire.read();
Serial.println(ch);
Serial.print(" ");
}
Serial.println();
*/
/*
if (millis() - lastTime > 5000) // modified 1000 -> 5000
{
lastTime = millis(); //Update the timer
if (myGPS.getRELPOSNED() == true)
{
Serial.print("relPosN: ");
Serial.println(myGPS.relPosInfo.relPosN, 4);
Serial.print("relPosE: ");
Serial.println(myGPS.relPosInfo.relPosE, 4);
Serial.print("relPosD: ");
Serial.println(myGPS.relPosInfo.relPosD, 4);
}
else
Serial.println("RELPOS request failed");
}
*/
}