Dual GPS PCB v1.4

Hello everybody,
we worked on a new Version of the Dual GPS PCB. I ordered some Testboards and hope to receive them in 1 or 2 weeks.

Differences to V1.3:

  • Second ESP to postprocess the corrected GPS Position data for example an external Terminal (different baudrate then 115k…)
  • 2 Outputs with RS232 from the second ESP32
  • The modules should be aligned so it is easier to connect everything.
  • It is possible to input external Correction Data (from a modem)
  • It is compatible with the node mcu 32 from az-delivery (ESP32 Dev Board) and some chinese ones Amazon. I tried to make a double footprint :see_no_evil:

If someone from Germany/Austria is interested in a bulk order please contact me via telegram.

The PCB can be found here.
After we tested it, i can upload a zip package with the production data.


I made a short test of the PCB.
With Franz Dual Code the PCB with one ESP32 and the W5500 module sent the corrected GPS Position to AGO. So the normal function is given.
I haven’t tested the function of the second ESP yet (corrected GPS Positon to external Terminal).

And again:
If someone from Germany/Austria is interested in a bulk order please contact me via telegram. The procedure is described in the “AOG Dual Antenna Users” group.

1 Like

Hey Ben,

Has there been any more updates on this?

I made a bulk order of 30+ boards and they have been shipped mid june to all the people. So I think it is alright.
Maybe someone with a system running on the field can give a comment. I only have old versions in the field.


Unfortunately, I overlooked this topic.
Do you have a pcb left?

I’ve got 5 board on the way from China. Looking forward to test this out. I’ve got a couple of newbie questions though…

My tablet does not have ethernet-connection so can I just skip the W5500 and connect it via USB?

Do I need an XBee reciever? I’m using Network RTK, with an existing network set up by the government. (https://www.lantmateriet.se/en/maps-and-geographic-information/gps-geodesi-och-swepos/swepos/swepos-tjanster/natverks-rtk/)

The second ESP, what is i good for and is it mandatory?

Where do I find the ESP software?
Thanks @Benjamin for making life easier. :slight_smile:

I have set up two sets of Benjamin’s board using both C099-F9p and Ardusimple F9p’s.
I used the code from mtz8302 and read the contributions by Franz Husch and Valentin Ernst. The Ardusimple boards plug straight in. The C099-F9p require RX TX changes in Mathius Code and some extra wires added to his boards.

see here for mtz8302 ESP32 code:

I only used USB for setup then ran testing with WIFI and both setups worked good.

Thanks for a quick reply!
Are you using an XBee reciever with your Ardusimple F9P?

If you are using a Government CORS site you only need internet access to get the corrections for RTK.

1 Like

And Franz code can be found on GitHub:


Hello , I m in tests with dual antenna , MTZ8302 mount , but no response in AOG ! can you help me for debug the syem and help to see where is the problem . Photos , tuto … Thanks JLPIC

My gathered notes from this site and Ublox:

Wired connection between moving base (for heading) and rover/tractor absolute position) – using code by Matthias Hammer (MTZ8302) and Benjamin’s Dual GPS PCB v1.4 for Ardusimple and C099-F9P.

The UART2 interface is recommended as the default RTCM interface for correction data. The UART2 interface a speed of 460800 baud is required. The Rover F9P(PVT) sends rtcm correction data from TX2pin to the Heading F9P(RelPosNed) RX2pin. As stated by Matthias Hammer the Ardusimple TX2 and RX2 pin labels are reversed!!.

Only the RTCM correction data is used between the heading and rover F9P’s.
No other protocols other than RTCM are to be enabled on UART2. This allows the UART2-TX on the Rover to transmit to the UART2-RX on the moving base without issues such as buffer overflowing or the wrong messages being sent into the heading ZED-F9P unit. For example, do not allow NMEA output messages to be fed back into UART2. Only enable the required RTCM messages to be output on the Rover(PVT) ZED-F9P UART2.

Required corrections transmitted from Rover(PVT) (connected to the right position antenna) to heading(RelPosNed) (connected to the heading left antenna)
The moving base algorithm was optimized for HPG 1.13.
The recommended list of RTCM messages for the Rover(PVT) is:

• RTCM 4072.0 Reference station PVT information
• RTCM 1074 GPS MSM4
• RTCM 1094 Galileo MSM4
• RTCM 1124 BeiDou MSM4
• RTCM 1230 GLONASS code-phase biases

//Set up by Matthias Hammer (MTZ8302) 12.Juli.2020
//ESP32 programm for UBLOX receivers to send NMEA to AgOpenGPS or other program

byte vers_nr = 52;
char VersionTXT[150] = " - 6. June 2021 by MTZ8302
(TX RX pins swapped for C099-F9P-ken), CMPS14 and Ethernet support, NTRIP client for ESP32, multiple WiFi networks)";

//works with 1 or 2 receivers: if you only have one, connect it to right PVT side PINs 27+16

//1 receiver to send position from UBXPVT message to ESP32
//2 receivers to get position, roll and heading from UBXPVT + UBXRelPosNED via UART to ESP32

//ESP sending $PAOGI or $GGA+VTG+HDT sentence via UDP to IP x.x.x.255 at port 9999 or via USB

//AgOpenGPS sending NTRIP via UDP to port 2233(or USB) → ESP sends it to UBLOX via UART

//filters roll, heading and on weak GPS signal, position with filter parameters changing dynamic on GPS signal quality

//by Matthias Hammer (MTZ8302) 2021, supported by Franz Husch (Jeep1945), WEder (coffeetrac), NTRIP client by GLAY-AK2 (GitHub)
//see GitHub mtz8302 · GitHub and Youtube Ma Ha MTZ8302 https://www.youtube.com/channel/UCv44DlUXQJKbQjzaOUssVgw

//change stettings to your need. Afterwards you can change them via webinterface x.x.x.79 (
//if connection to your network fails an accesspoint is opened: webinterface

//use serial monitor at USB port, to get sebug messages and IP for webinterface at ESP start.

//for easier setup:
//use webinterface, turn debugmodeUBX on and change GPIO pin until you get data from the UBlox receivers on USB serial monitor

//the settings below are written as defalt values and can be reloaded.
//So if changing settings set EEPROM_clear = true; (line ~109) - flash - boot - reset to EEPROM_clear = false - flash again to keep them as defaults

struct set {
//connection plan:C099-F9P (must set jumper 40E_N on J4 for moving base!!)
// ESP32— Right antenna -ROVER F9P PVT POS — Left antenna -HEADING F9P RELPOSNED-----Sentences
// RX1(ESPp16)------TX1(J9pin2)--------------------------------UBX-Nav-PVT out (=position+speed)
// TX1(ESPp27)------RX1(J9pin1)--------------------------------RTCM in (NTRIP coming from AOG to get absolute/correct postion
// RX2(ESP-25)-----------------------------TX1(J9pin2)----------UBX-RelPosNED out (=position relative to other Antenna) on PCB connect pin11 to pin12 on RelPosNed
// TX2(ESPp17)-----------------------------RX1---------- not connected on PCBV4
// TX2(J3pin6)-----------------RX2(J3pin5)----------RTCM 1077+1087+1097+1127+1230+4072.0+4072.1 (activate in Rover(PVT) F9P = NTRIP for relative positioning)
// Benjamin’s Dual PCB.
// AgOpenGPS Dual GPS v1.4b adjustments to fit C099-F9P
// Join pins by wire:
// TX2(J3pin6)rover to J8pin1rover
// J9pin3 heading to RX2(J3pin5)heading
// J9pin2 heading to J9pin1 heading
// J2pin1rover to J2pin4rover
// J2pin1heading to J2pin4heading
// Cut 5 header pins connecting to C099-F9P rover J9pin3, rover J2pin4, heading J9pin1, heading J9pin3 and heading J2pin4.
// IO pins ESP32 side C099-f9P ----------------------------------------------------------------------------
byte RX1 = 16; //right F9P TX1 GPS pos-C099-ken (or only one F9P
byte TX1 = 27; //right F9P RX1 GPS pos-C099-ken (or only one F9P

byte RX2 = 25;                    //left F9P TX1
byte TX2 = 17;                    //left F9P RX1

//connection plan:Ardusimple
// ESP32— Right F9P GPS pos — Left F9P Heading-----Sentences
// RX1-27-------TX1--------------------------------UBX-Nav-PVT out (=position+speed)
// TX1-16-------RX1--------------------------------RTCM in (NTRIP coming from AOG to get absolute/correct postion
// RX2-25-----------------------------TX1----------UBX-RelPosNED out (=position relative to other Antenna)
// TX2-17-----------------------------RX1----------
// TX2-------------------RX2----------RTCM 1077+1087+1097+1127+1230+4072.0+4072.1 (activate in right F9P = NTRIP for relative positioning)
// Attention: on Ardusimple boards the print RX2 and TX2 is flipped!!! RX2 print means TX2 function. Workaround: simply connect both RX2 TX2 cross wired
// IO pins ESP32 side ARDUSIMPLE ----------------------------------------------------------------------------
//byte RX1 = 27; //right F9P TX1 GPS pos-C099-ken (or only one F9P
//byte TX1 = 16; //right F9P RX1 GPS pos-C099-ken (or only one F9P

//byte RX2 = 25;                    //left F9P TX1
//byte TX2 = 17;                    //left F9P RX1

byte Eth_CS_PIN = 5;              //CS PIN with SPI Ethernet hardware  SPI config: MOSI 23 / MISO 19 / CLK18 / CS5

uint8_t SDA = 21;			      //I2C Pins for CMPS14
uint8_t SCL = 22;

byte Button_WiFi_rescan_PIN = 4;  //Button to rescan/reconnect WiFi networks / push to GND

byte LEDWiFi_PIN = 2;      // BUILTIN or 2 WiFi Status LED 0 = off
byte LEDWiFi_ON_Level = LOW;    //HIGH = LED on high, LOW = LED off....ken

//tractors WiFi or mobile hotspots
char ssid1[24] = "L1";           // WiFi network Client name
char password1[24] = "xpx8sy8pgh";                 // WiFi network password//Accesspoint name and password
char ssid2[24] = "Repeater";// WiFi network Client name
char password2[24] = "CarolineFarm";                 // WiFi network password//Accesspoint name and password
char ssid3[24] = "";           // WiFi network Client name
char password3[24] = "";                 // WiFi network password//Accesspoint name and password
char ssid4[24] = "";       // WiFi network Client name
char password4[24] = "";                 // WiFi network password//Accesspoint name and password
char ssid5[24] = "";    // WiFi network Client name
char password5[24] = "";                 // WiFi network password//Accesspoint name and password

char ssid_ap[24] = "GPS_unit_F9P_Net";  // name of Access point, if no WiFi found, NO password!!
int timeoutRouter = 120;                //time (s) to search for existing WiFi, than starting Accesspoint 

byte timeoutWebIO = 10;                 //time (min) afterwards webinterface is switched off

// Ntrip Caster Data
char NtripHost[40] = "auscors.ga.gov.au";//;// ntrip.data.gnss.ga.gov.au    // Server IP or URL
int  NtripPort = 2101;                // Server Port
char NtripMountpoint[40] = "PERT00AUS0";   // Mountpoint
char NtripUser[40] = "sh****";     // Username
char NtripPassword[40] = "*****";    // Password

byte NtripSendWhichGGASentence = 0; // 0 = No Sentence will be sended / 1 = send fixed GGA Sentence from belowb/ 2 = GGA from GPS position will be sended

char NtripFixGGASentence[100] = "$GPGGA,051353.171,4751.637,N,01224.003,E,1,12,1.0,0.0,M,0.0,M,,*6B"; //hc create via www.nmeagen.org

byte NtripGGASendRate = 10;         // time in seconds between GGA Packets

//   If the wifi network is x.x.1.x style of IP numbers, you only need to change wifi info and
//   antenna distance in the ESP code and set 2233 as port in the ntrip settings in AOG.
//  When you have for example x.x.0.x wifi network, also change module number x.x.1.x to 
//  x.x.0.x in the UDP settings in AOG. Set UDP On and it should work.

byte WiFi_myip[4] = { 192, 168, 1, 79 };     // Roofcontrol module 
byte WiFi_gwip[4] = { 192, 168, 1, 1 };      // Gateway IP only used if Accesspoint created
byte WiFi_ipDest_ending = 255;//ending of IP address to send UDP data to
byte mask[4] = { 255, 255, 255, 0 };
byte myDNS[4] = { 8, 8, 8, 8 };         //optional

byte Eth_myip[4] = { 192, 168, 1, 80 };     // Roofcontrol module 
byte Eth_ipDest_ending = 255;//ending of IP address to send UDP data to
byte Eth_mac[6] = { 0x90,0xA2,0xDA,0x10,0xB3,0x1C }; //usb autosteer 0x70, 0x69, 0x69, 0x2D, 0x30, 0x31
bool Eth_static_IP = false;	  // false = use DHPC and set last number to 80 (x.x.x.80) / true = use IP as set above

unsigned int PortGPSToAOG = 5544;             //this is port of this module: Autosteer = 5577 IMU = 5566 GPS = 
unsigned int PortFromAOG = 8888;            //port to listen for AOG
unsigned int AOGNtripPort = 2233;       //port NTRIP data from AOG comes in
unsigned int PortDestination = 9999;    //Port of AOG that listens

//Antennas position
double AntDist = 61.00;                //cm distance between Antennas
double AntHight = 254.0;              //cm hight of Antenna
double virtAntLeft = 30.50;           //cm to move virtual Antenna to the left (was renamed, keep your settings, name of direction was wrong)
double virtAntForew = 0.00;            //cm to move virtual Antenna foreward
double headingAngleCorrection = 90.0;

double AntDistDeviationFactor = 1.2;  // factor (>1), of whom length vector from both GPS units can max differ from AntDist before stop heading calc
byte checkUBXFlags = 1;               //UBX sending quality flags, when used with RTK sometimes 
byte filterGPSposOnWeakSignal = 1;    //filter GPS Position on weak GPS signal

byte GPSPosCorrByRoll = 1;            // 0 = off, 1 = correction of position by roll (AntHight must be > 0)
double DualRollAngleCorrection = 0.0;

byte MaxHeadChangPerSec = 30;         // NOT USED at the moment - degrees that heading is allowed to change per second

byte DataTransVia =  7;                //transfer data via 0 = USB / 7 = WiFi UDP / 8 = WiFi UDP 2x / 10 = Ethernet UDP

byte NtripClientBy = 1;               //NTRIP client 0:off /1: listens for AOG NTRIP to UDP (WiFi/Ethernet) or USB serial /2: use ESP32 WiFi NTIRP client

//example: for dual GPS: sendOGI 1, all other 0. For single antenna: VTG,GGA = 1; OGI,HDT = 0, if you have CMPS14 IMUPGN = 1
byte sendOGI = 1;                     //1: send NMEA message 0: off
byte sendVTG = 0;                     //1: send NMEA message 0: off
byte sendGGA = 0;                     //1: send NMEA message 0: off
byte sendHDT = 0;                     //1: send NMEA message 0: off HDT=Trimble heading sentence
byte sendIMUPGN = 0;                  //for CMPS14: 1: send IMU message 0: off

bool CMPS14_present = false;
float CMPS14HeadingCorrection = 0.0;
float CMPS14RollCorrection = 0.0;
int CMPS14_ADDRESS = 0x60;   // Address of CMPS14 shifted right one bit for arduino wire library

bool debugmode = false;
bool debugmodeUBX = false;
bool debugmodeHeading = false;
bool debugmodeVirtAnt = false;
bool debugmodeFilterPos = false;
bool debugmodeNTRIP = false;
bool debugmodeRAW = false;

}; set Set;

bool EEPROM_clear = false; //set to true when changing settings to write them as default values: true → flash → boot → false → flash again


1 Like

Please use triple BACKTICKS when posting code. Google it if you can’t find them or copy these // ``` before and after the code (not the backslash had to put those before the backticks so they didn’t disappear)

Hello, Thank you very much everyone! we managed to use the dual antenna system. Well done ! but … it’s not worth an FP9 in the center of the cabin and the cmps14! Indeed, when I go into reverse AOG does not see it! and to follow the line AB the tractor makes the snake! I’m keeping an eye on it anyway! .

Latest version of AgOpenGPS supports a separate RTCM Arduino. Is that what the second ESP32 on this board is for? What INO should be used on the second ESP and should i configure the primary ESP differently if I use two ESPs?

Haven’t heard of the rtcm Arduino. But no the second esp is for corrected position data to an implement.

Franz got a code for it

This is for the second ESP:

I never used it, so can’t help any further.

1 Like