Building an FPV drone telemetry system means getting down to business with microcontrollers and GPS. Come along as I share how I untethered my dev board with a Raspberry Pi and then wrestled with getting those first satellite coordinates.

Build, Create & Learn — A Maker’s Journey Episode 3. I’m happy to share the latest updates of my projects in my new podcast episode.



Today, we’re diving into the exciting world of GPS data for our custom FPV drone telemetry system. But before we get there, I want to share a recent breakthrough that’s truly been a game-changer for my entire embedded development workflow: breaking free from the USB cable.

Breaking Free – My Wireless Embedded Lab

So, as an embedded system enthusiast, I’m always messing around with microcontrollers – like the one for my drone telemetry system. But there’s this one thing that always gets you: you always need a physical USB cable! It’s what hooks your powerful computer right up to your embedded hardware, letting you flash new software or debug some tricky sensor problem.

And honestly, that physical connection really annoyed me! I love working from all sorts of places – sometimes it’s my desk, sometimes I’m comfy in bed with my MacBook, sometimes even chilling in the garden. Can you imagine needing to flash new software or debug a sensor, but your dev board is stuck in the workshop? Ugh! Or maybe you’re like me, always on the go with a laptop, constantly plugging and unplugging, totally breaking your flow. It felt like I was always on a leash, kind of like that old headache I had with the SSD mount.

This annoying problem just kept bugging me: how could I finally break free?! I really wanted to work remotely, no matter where the hardware actually sat. Of course, if I’m pushing buttons or hooking up wires, I still need to be right there with the board. But for so much of what I do – grabbing sensor data, tweaking internal algorithms, or fine-tuning low-level drivers – the board could seriously be anywhere! That’s when I decided to jump headfirst into making “embedded programming over network” a real thing for my setup.

And the absolute star of that whole solution? A trusty Raspberry Pi!

This wireless setup just makes development so much more comfortable, it’s amazing. It means no more tangled cables, I can totally work from the couch, and I can do quick re-flashes without even touching the board! It’s seriously a game-changer for how I get things done. I’ve actually written down this whole adventure, including all the dead ends, in a detailed article hitting the blog really soon. That article will spill all the beans on the exact setup and configuration for the Raspberry Pi solution, with all the commands and troubleshooting tips you’ll need. For now, think of this as a quick peek, giving you a sneak preview into how I finally cut the cord from my development board!

Diving into GPS: The MTK3339 Sensor

Let’s get back to our drone telemetry system and the main component for this episode—the GPS sensor: the MTK3339.

I kicked things off by doing what any good maker does: hitting the docs! I grabbed the Adafruit breakout board documentation for the MTK3339. It was a super nice intro to the component and what it could do, and it really helped me get my head around GPS data. I learned all about the MTK3339 chipset, its awesome -165 dBm sensitivity, and how it can update 10 times a second. Plus, I found out it spits out data in the standard NMEA 0183 format, and its default speed is 9600 baud.

What really surprised me were these cool features I didn’t even know about when I bought it: built-in datalogging and the option for an external active antenna! That was a sweet bonus, especially thinking about future drone flights. Getting that first intro to NMEA strings was very helpful – figuring out those cryptic lines of text are totally key to getting useful data.

My first thought for talking to the sensor was to just use the big Adafruit library. I mean, why build from scratch, right? But all the examples were for Arduino IDE. I tried adding the library to my STM32 project, and hit a wall. Turns out, that library was written in C++, and my project uses plain old C.

Man thinking with flying equations and numbers

This was a bit of a head-scratcher. C++ uses classes and structures files differently, which is a big jump from C’s more step-by-step style. Sure, they’re similar, but I quickly realized I just wasn’t fluent enough in both to easily switch back and forth. It was a humbling moment, for sure. I know the basics, but I definitely need to brush up on the details of each language. I’m hoping to master them as I go, but this particular task needed more brainpower and time than I had right then.

So, I started looking online for ways to tackle the MTK3339 with an STM32. I actually found an example built with the mbed library. The code looked somewhat understandable, and I thought, “Yes! This should be an easy fit for my project!” But nope, I was wrong again. This library was also in C++, and trying to convert it was just as much of a headache. I even thought about converting my entire project to C++ just to use this library. However, after hours of trying to get the files to build, hitting all sorts of linker errors and confusing class structures, I stopped on that approach. It was a classic maker pivot – sometimes, the path you think is the easy one turns into a dead end, and you just gotta take a step back and try something totally different.

The UART Detective Work & First NMEA String

My new approach was to start from scratch, aiming for the absolute minimal working setup: just establishing a simple serial connection to the sensor. In my STM32 pinout configuration, I noticed that USART2 was already pre-configured by my development board. My first thought was, “Perfect, I’ll just use that!” But then a bit of skepticism crept in. Why was it pre-configured? Was it already being used for something else?

Can I use this UART port?

This led me down a rabbit hole of detective work. I started reading about some people discussing issues with the UART1 port, which led me to dig deeper into the user manual for my specific Nucleo development board. There, it was described nicely and explained exactly how the ST-Link debugger on my board was connected to the STM32 chip. And sure enough, my concern was correct: USART2 was indeed being used as the serial COM port for the ST-Link debugger, which is how my laptop communicates with the board. With that information, it was crystal clear that I had to switch to another available UART port. So, I activated the USART1 port on pins 9 and 10, which meant I had to slightly adjust the physical wiring of the GPS breakout board to my dev board pins.

Pins diagram from the STMCubeIDE

With this new UART port configured, I had compiled code, and it ran on the board. But I still didn’t get any output on my laptop. My immediate thought was, “Is the board still not working? Is my code wrong?” But then I remembered: I needed a serial terminal to actually see the communication coming from the debugger’s COM port. After some quick research, I figured out how to set up a terminal directly within the STM32CubeIDE. And wouldn’t you know it. When I connected, there was some output! But it was cryptic, scrambled, and definitely not what I was expecting.

Wrong scrambled data from the serial port of the gPS module

Finally, a response in the terminal!

First, I was just happy to see any response in the terminal at all. But after that initial excitement, I realized these looked off. They were fragmented and didn’t look correct at all. My first idea was to ask ChatGPT if it could identify the issue. I checked all the recommendations: baud rate of the GPS module, baud rate of my serial communication, the wiring – everything looked fine. But the output was still garbage. So, I tried two more things, and one of them, or perhaps both, solved the issue. First, I double-checked the pinout configuration again and fixed the connection for pins 9 and 10, then recompiled. I also changed the main loop function where I was forwarding the serial response from UART1 (the GPS module) to UART2 (the debugger/my laptop). I switched to a simpler HAL_UART_Receive and HAL_UART_Transmit approach. This resulted in a proper, readable response in the terminal. And there it was: my first NMEA string!

Here’s a simplified look at the core idea of how you’d forward data from one UART (connected to the GPS) to another (connected to your debugger/laptop) in a bare-bones C setup using STM32 HAL:

int main(void)
{
	HAL_Init();
	SystemClock_Config();

	MX_GPIO_Init();
	MX_USART2_UART_Init();
	MX_I2C1_Init();
	MX_USART1_UART_Init();

	// Optionally print welcome message
	const char *msg = "GPS pass through ready\r\n";
	HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);

	while (1)
	{
		if (HAL_UART_Receive(&huart1, rx_buffer_pc, 1, HAL_MAX_DELAY) == HAL_OK)
		{
			HAL_UART_Transmit(&huart2, rx_buffer_pc, 1, HAL_MAX_DELAY);
		}
	}
}

This snippet illustrates the very basic loop. In a real application, you’d likely use DMA or interrupts for more efficient data handling, especially with high data rates. But for getting that initial raw NMEA output, this kind of direct forwarding can be a lifesaver.

The Satellite Fix & Verification

Seeing those NMEA strings was a huge step, but the crucial part for GPS is getting a “fix” on satellites. I quickly learned to look for specific indicators in the NMEA strings. For example, in the $GPRMC (Recommended Minimum) sentence, a status field will show ‘A’ for an active (valid) fix or ‘V’ for void (invalid). In the $GPGGA (Global Positioning System Fix Data) sentence, a ‘fix quality’ field will show ‘1’ for a GPS fix or ‘2’ for a DGPS fix. My initial strings, despite being readable, showed no fix.

Proper data from the GPS module

See, I was stuck indoors, using the GPS board’s tiny internal antenna. To get a satellite connection, I had to go outside. And wow, did my new wireless Raspberry Pi setup shine here! I just grabbed the board and the Pi, plugged the Pi into a socket on my terrace, and let it do its thing. Connected to it over the network from inside, and after just a few minutes in the debugger, boom! There it was: the right NMEA string, showing $GPGSA,A,3,… – a solid 3D fix!

It was so exciting to finally see real satellite data hitting my little board. Just amazing! To check the coordinates, I fed a chunk of the serial response into ChatGPT, asking it to turn it into a Google Maps address. Then, using Google Maps’ built-in tool, I measured the distance between the GPS’s spot and my actual location. The result? Only about 160 meters off! Which, for a first try with a tiny antenna, I think is totally fine. It was super cool to get not just the GPS coordinates, but also the actual Greenwich Mean Time directly from a satellite!

Conclusion & What’s Next

So, what a ride this article’s been! We kicked off by untethering our embedded dev with that awesome new wireless setup – seriously, a total game-changer for flexibility. Then, it was full-on GPS mode: fighting C++ libraries, figuring out UART mix-ups, and finally, getting those first proper NMEA strings after some intense debugging. And the best part? Getting a solid satellite fix outside and actually checking our location data!

It’s a huge reminder that being a maker is all about those little ‘aha!’ moments, those tiny frustrations that teach you big lessons, and the simple wins that keep you going. It’s about learning, adapting, and most importantly, not being scared to mess up and just figure stuff out. That’s where you really grow!

So, what’s next? My immediate goal is to turn those raw NMEA strings into actual, usable coordinates in my code. Plus, I just ordered an active external GPS antenna. That should give me way better range and accuracy for future drone flights, especially on a fast FPV drone. The breakout board does have some built-in storage, but I’m planning to use an SD card next time. That’ll give me way more space, let me log tons of different data (not just GPS, but also from the BME280). And crucially, let me play with how often I log, ‘cause I’m not sure that 15-second internal logging will cut it for a speedy drone.

If you liked this honest peek into starting an embedded project, please subscribe to ‘Build, Create & Learn - A Maker’s Journey’ wherever you listen to podcasts. Oh, and that super detailed article on my wireless-embedded setup? Keep an eye on my blog for that deep dive! Hit me up, connect on social media, or drop a comment on this post – I’d love to hear about your own debugging nightmares or big wins! Your stories really make this community awesome.




Let’s keep building, creating, and learning — together.