RoverLink Released Open Source


I developed a program to utilize a pair of ESP32 dev boards for a short to medium range telemetry solution to connect ArduRover Mission Control to Pixhawk. If anyone else needs this I have created a public repository and will update it if I find issues but seems to work well now in my basement (range 10 feet!).

Will test it outdoors later this week but the idea is that you can take a pair of ESP32 boards and use them as a lightweight telemetry solution over the lightweight ESP-NOW protocol meaning you don´t need any WIFI networks or routers. It is very fast and simplistic as it doesn´t use IP, DNS, etc.

I am running it at 115,200 full duplex and it seems more responsive than my 915 Mhz store bought telemetry which I let the smoke out of last week.

Thanks for any feedback.


This is very similar to my own ESP-Now projects. I was very impressed with the range one can achieve with simple external antennas.

I’ve been using the “ESP-Now-Burst-Serial-Bridge” linked below as the RTCM3 relay for my Rover mower for the past 2 months with no issues at all. I see ranges over 200’ on a regular basis with no packet loss, even through some significant physical obstacles.

ArduPilot blog entry
ESP-Now-Serial-Bridge (
ESP-Now-Burst-Serial-Bridge (

Wow, I started mine about the time you published your program when I was overseas. I wish I noticed yours before I developed my solution. I may switch over to yours if I have problems with RTK corrections.

I have an Ardusimple RTK gps in the rover and send corrections over telemetry but haven´t tried it yet with the ESPNOW based code. I researched Mavlink and saw that the packets are sub 250 but forgot to check out the RTK correction packets I receive from NYSNET correction network in New York state.

Thanks for responding.

1 Like

Update: this did seem to work with GPS correction data without problems. I ran it outdoors today in poor conditions (downpour) and did have an RTK float solution at times.

If anyone else plays with this please let me know how it works for you.


1 Like

It should send most MAVLink messages no problem. Technically the max packet size is 263 bytes for MAVLink, but I’ve yet to see one over the 250 limit for ESP-Now.

If you are sending raw RTCM3 (not the MAVLink encoded correction data), you will almost certainly need to alter the code (see my burst messaging code).

1 Like

Yuri, thanks for getting back to me so quickly!

I would like to test mine out to see if it handles the larger packets because I am somewhat packet agnostic. I am sending out packets whenever I see characters available in the serial buffer so I may be a little less efficient than your “store and forward” method because I am probably sending out several ESP-NOW messages for each Mavlink packet. I am going to put in some debug code to see what I am actually doing and will make another post then.

I saw your video of your mower tracking in perfectly straight lines. Strong work!

A couple of questions on the direct sending of raw RTCM3:

  1. Are you connecting from some caster software directly to your f9p board(s)?
  2. Did you find advantages in performance by sending raw RTCM3 to your rover instead of going through Mission Planner?

I tried some packet-agnostic code like yours and found that packet loss increased dramatically. In fact, one version of that was actually rapidly sending single bytes at a time because the loop happens faster than serial output. That’s what drove me to store/send full packets the way I do. It’s a far more reliable method, and there is really no reason not to implement it for a protocol like MAVLink.

I thought that I found a significant advantage to sending raw RTCM3 over MAVLink injection, but a firmware update on the F9P boards solved that almost entirely. There is still probably a slight reliability advantage in sending raw RTCM3 rather than relying on MAVLink injection, but it’s not a very measurable one.

I do, however, prefer direct RTCM3 messaging, because I don’t have to run (or rely on) Mission Planner to get RTK solutions on the Rover.

I use an F9P as a fixed base. It is directly connected to an ESP32 running the serial bridge software. I don’t use any NTRIP casting for my setup.

Thanks for those responses. I am not going to test this much now that I know you already tried this method. How do you do your Mission Planner telemetry if you are using your esp32 for dedicated GPS corrections?

Actually, I have 3 vehicles, and I use slightly differing methods for each. I’ve mostly been referring to my mower, which is the most complex of the 3. Here’s a rundown:

I have a small testbed Rover where I use an ESP32 with my serial bridge software for a MAVLink connection. It does not have an RTK capable GPS, so that’s of no concern.

I have a 550mm quadcopter that uses an M8P GPS module. I use a 915MHz SIK telemetry radio on it with the ground radio connected directly to the USB port of the GCS computer. I only use MAVLink injection via Mission Planner when I want it to have an RTK fix (RTCM3 comes from my fixed base via a Raspberry Pi ser2net connection).

Lastly, I have a zero turn lawnmower Rover with F9Ps in a moving base configuration. It has a 915MHz SIK telemetry radio as well, which transmits to the “ground” radio that’s connected to a Raspberry Pi, which, in turn, transmits telemetry via ser2net over WiFi. An ESP32 connected to the fixed base F9P handles direct RTCM3 messaging to an ESP32 connected to the moving base UART2 port on the Rover.

That sounds complicated. It’s not as bad as it sounds :smiley:

I shot a video about the fixed base a couple of months ago. I have since added ESP-Now capability to it (but also kept the RPi).

ArduPilot WiFi Enabled Fixed Base + Telemetry for RTK GPS - YouTube

Thanks a lot for your help.

1 Like

Hi Yuri,
i’ve watched your video and setup ser2net accordingly. Telemetry works fine, but no correction messages are coming in (works fine if Base is connected directly to the PC).

Using simpleRTK2B-F9P V3 connected via USB. It shows up as /dev/gps0 and /dev/ACM0, but not as ttyUSB. Could this be making a difference?

ipv4,udp,4001:raw:0:/dev/gps0:460800 NONE 1STOPBIT 8DATABITS LOCAL -RTSCTS max-connections=10
ipv4,udp,4002:raw:0:/dev/ttyACM0:115200 NONE 1STOPBIT 8DATABITS LOCAL -RTSCTS max-connections=10

2000:raw:601:/dev/ttyUSB0:57600 NONE 1STOPBIT 8DATABITS LOCAL -RTSCTS max-connections=10

Reading directly from with SCREEN gps0 and ACM0 (antenna disconnected) gives these results:

Interesting observation when FixedBase is mounted on top of RPI GPIO: stops outputting all $G… messages and switches to these as soon as MP is connected via the UDP:

Yet, MP is not showing any Messages Seen, only shows Input Rate of ~30bps.

It reverts back to $G messages only after RPI shutdown.

You have conflicting lines in your configuration file. gps0 is probably a symlink to ttyACM0. Use only one line or the other. I’m fairly certain that Mission Planner’s expected/autoconfigured baud rate is 115200.

1 Like

Yuri, thanks for the hint, problem was baud rate indeed. It eventually started working via RPI GPIO and UDP with baud rate set to 460800 in ser2net.conf. MP is autoconfiguring to this baud rate for some reason. Even though by default Base is set to 115200.

P.S. ser2net is switching from conf to yaml-based format config, have you tried it yet?

I haven’t touched the config file in a long time! Glad you got it working.

I am having a similar issue and have tried numerous combinations as well still without any luck. Just like Muse, the Telemetry is working just fine but the GPS through TCP or UDP is still not working. Based on LSUSB I am still racking my head on the config have below.

SUBSYSTEM==“tty”, KERNELS==“1-1.2”, ATTRS{product}==“U-Block AG u-blox GNSS receiver” SYMLINK+=“ttyGPS0”
SUBSYSTEM==“tty”, KERNELS==“1-1.3”, ATTRS{product}==“U-Block AG u-blox GNSS receiver” SYMLINK+=“ttyGPS1”
SUBSYSTEM==“tty”, KERNELS==“1-1.4”, ATTRS{product}==“U-Block AG u-blox GNSS receiver” SYMLINK+=“ttyGPS2”
SUBSYSTEM==“tty”, KERNELS==“1-1.5”, ATTRS{product}==“U-Block AG u-blox GNSS receiver” SYMLINK+=“ttyGPS3”


ipv4,udp,4000:raw:0:/dev/ttyGPS0:460800 NONE 1STOPBIT 8DATABITS LOCAL -RTSCTS max-connections=10
ipv4,udp,4001:raw:0:/dev/ttyGPS1:460800 NONE 1STOPBIT 8DATABITS LOCAL -RTSCTS max-connections=10
ipv4,udp,4002:raw:0:/dev/ttyGPS2:460800 NONE 1STOPBIT 8DATABITS LOCAL -RTSCTS max-connections=10
ipv4,udp,4003:raw:0:/dev/ttyGPS3:460800 NONE 1STOPBIT 8DATABITS LOCAL -RTSCTS max-connections=10

#for connecting with u-center - comment out the udp connection above to use
#2001:raw:600:/dev/ttyGPS0:460800 NONE 1STOPBIT 8DATABITS LOCAL -RTSCTS max-connections=10

#telemetry only seems to work reliably with TCP
2000:raw:601:/dev/ttyTelemetry0:57600 NONE 1STOPBIT 8DATABITS LOCAL -RTSCTS max-connections=10