- Published on
A long running project - Giraffe: A Unified, Semi-Autonomous, High Altitude Balloon Flight Control Framework.
- Authors
- Name
- Joshua Jerred
There is one project that I've actually been able to stick to for more than a few weeks, and that is my continuous work on weather balloon flight hardware and software. This project is what I can thank for my self-taught knowledge of electronics.
The Very First Versions (2013-2014)
My very first version of this project was in 2013 when I was 12, and the best part of this is the fact that I've never launched a single balloon (mainly due to financial constraints).

It was just a foam spigot cover with a Raspberry Pi B model stuffed inside of a block of foam. That Pi still surprisingly works to this day even after being pushed into a anti-anti-static block and accidentally ripping off a power supply capacitor.
I didn't know how to use any sensors at the time and I was only programming with scratch, so I really have no idea what my goal was. It was going to include a cellular GPS receiver but, due to the fact that I was a jobless 13 year old, I couldn't afford to do much more than torture that poor Pi.
This project, just like many others, got pushed to the side but I didn't forget about this one.
The First Real Version (2017-2019)
There was casual work on other versions of the project but the first time that I actually did anything with it was in 2017. I was 16 at the time, had my ham radio license, and had taken an interest in SSTV. I also finally had a job so I could afford to buy a few parts.

This one was a bit more interesting and it was my first dive into the software side of things. This one was based on the same Pi, eventually replaced with a Pi Zero. It included a pressure sensor (BMP180), a temperature sensor (DS18B20), a GPS receiver (Knock off uBlox on a breakout board), and a Pi camera.
The software was a simple bash script that used various Python scripts - found on the internet - to read the sensor. It would then use raspistill to take a picture.
After the picture was taken it would use 'convert' to add the sensor data to the image, then passing it to a public SSTV modulation program made by KI4MCW. After this it would play the audio with aplay. This was done with a cronjob that ran every few minutes. The radio was a UV-5R with VOX turned on.
It was a gross way of doing things but it worked. I wasn't confident to launch it as the communication wasn't done in a way that was reliable or even necessarily legal.
The code for it can be found here.
AOS - Atmospheric Observation System - (2019-2022)
This was after I started to learn Python. The entire thing was written in Python with a lot of the sensor code being taken from the web and modified to fit my class based structure. I don't want to go into too much detail on the software, but it can be found here.
This one used the same sensors as the previous version with the addition of a DRA818V radio module. This module required a UART, which was already being used by the GPS receiver, so I created a arduino based I2C to UART bridge.
This one worked, but it was still a bit of a mess. The biggest issue that I was having was with my limited knowledge of electronics. Every time I would use the radio it would crash the Pi along with other issues. This one had functionality to change frequencies so I could transmit SSTV images and then switch to the common APRS frequency to transmit location data.

I had started to learn C++ and became interested in lower level programming, so around August of 2020 I decided to start from scratch... again.
Giraffe - The Current Version (2020-2022)
This is the current version of the project. It's more of a mess than ever before! The goal for this version was not to make the best flight computer hardware or software, but to use it as a learning lab for myself. I want to learn as much as I can about electronics, programming, the development and design process, and a whole lot more. It's grown to be much more than I originally intended and I really don't mind. There is no end in sight. It's grown enough to deserve a nonsensical name, so I've named it Giraffe.
A list of the things that I've learned/exposed myself to so far:
- C++ in a Linux Embedded environment
- Basic Socket Programming
- I2C both hardware and software (linux)
- Unit Testing with Google Test
- GitHub Actions
- Writing Device Drivers
- 'Proper' PCB Design
- Dealing with RFI/EMI
- Hardware level debugging
- Interrupt handling
- Multi-threaded programming in C++ (std::thread and mutexes)
- The joy of reading datasheets
- Making Schematics in KiCad (and everything that comes with that, goodbye Fritzing!)
- SMD soldering with hot air
- Doxygen Documentation
- Planning and project management with Trello, Git, and GitHub projects (The most difficult part of the project)
- Learning when to restart instead of approaching my problems with brute force attempts
- Why decoupling capacitors are important
- Python HTTP servers (for the simple debugging web server)
- WAV file generation
- PSK/ASFK modulation from scratch
- UML with PlantUML
- JSON parsing with nlohmann::json
- CMake
- Understanding why the linker is yelling at me
- Patience
There is a whole lot more to add to this list but I honestly can't keep track at this point.
I've also attempted to make this project much more modular than the previous versions both in hardware and software. It's really a combination of all of my projects put into one.
Software
The flight computer software is written in C++ and is fairly modular and threaded.
The software falls under the name of 'GFS' or Giraffe Flight Software.
This software includes (or soon will include):
- SSTV images (with sensor data)
- Data Packets
- APRS Tracking
- Easy Expansion/Configuration
- Two Way Communication for real time configuration and limited control
- A whole lot more
I've decided to call each major functional block a 'module' and each sensor/data source an 'extension'. There are a few 'utility' scripts that are used across multiple modules/extensions.
Everything is pulled together with the 'flight runner'.
Modules
The currently implemented modules are:
- Configuration
- Used to load the configuration JSON file which contains all of the settings for the flight computer
- Determines which extensions are installed
- Validates the configuration options
- JSON Configuration includes:
- Project details (name, main-board ex: pi zero, starting procedure)
- Extensions (list of extensions to load with unique IDs, names, and interface settings, indicator of it an extension is flight critical)
- Debugging options (Enable/Disable the console and web server)
- Telemetry options (Call Sign, APRS, PSK, SSTV, frequency for each, modulation type)
- Data that should be included in the data logs and telemetry
- The flight procedures
- The flight procedures are a set of intervals that the flight computer will use to determine the frequency of telemetry transmission and data logging based on the current flight phase (launch, ascent, descent, failsafe, debug, etc.)
- Console
- Used to display debugging information about the flight computer
- Example image:
- Data
- The data module is the glue that helps everything communicate data, errors, and events
- Has a 'datastream' which is a shared data structure that all of the modules and extensions can access in a thread safe manner to get and set data
- Logs the data to a file
- Extensions
- The extension module is what loads all of the extensions and keeps them running
- It will (currently does not) handle extension errors depending on the configuration by either restarting them or keeping them disabled
- Server
- The debugging web server simple hosts a socket server that will send JSON data to clients that request it (the python web server takes care of this)
- Example image:
- Telemetry
- Used my MWAV library to generate WAV files for PSK, AFSK, and (eventually) SSTV along with APRS.
- Handles the radio interface (still a DRA818V sadly, other options are cost prohibitive :( )
- Keeps a 'queue' of radio transmissions that it will send in order as long as the configured frequency is clear
- MWAV is a fully separate project that I'm working on that also uses my WAV generation 'library'. I've created my own dependency nightmare.
- It currently does not control a radio but the TX queue is implemented and it just plays WAV files as they're generated.
Each module uses a common parent class to allow them to be easily started and stopped (depending on JSON configuration!)
For example, if you are about to start a flight and do not want the console to be displayed, disable it in the JSON configuration and its thread will not be started.
The server module works in a similar way. If you configure it to start you can stop the module through the web server by clicking the 'stop' button in your web browser. This stops the web server thread all together saving a bit of CPU time.
Extensions
Each extension runs in it's own thread as some of them require a lot of real time but not CPU time. This also allows for extensions to fail in not so graceful ways without pausing the entire flight computer. This is especially important as I've written all of my own drivers for the sensors (except for the DS18B20 as the kernel driver works fine) which guarantees instability. They all use the 'data stream' to communicate data and errors to the data module. This is a simple queue based system that is thread safe.
So far extensions/drivers have been written for:
- BMP180 - I2C driver - (Barometric Pressure/Temperature Sensor)
- BME280 - I2C driver - (Barometric Pressure/Temperature/Humidity Sensor)
- DS18B20 - Uses the linux 1-wire driver - (Temperature Sensor)
- SAM-M8Q - I2C/DDC/UBX driver - (GPS)
- System sensors - statfs/sysinfo kernel headers - (CPU, Memory, Disk, Uptime info)
- MAX17049[in progress] - I2C driver - (Battery Fuel Gauge)
Extensions also all use a common parent class with 'start' and 'stop' functions. This allows for for these drivers to be written with just a single function, the 'runner' function. The runner includes a while loop that will run as often as the defined interval (configured in the JSON configuration).
Eventually I plan on writing a slightly different extension class that will require extensions to be written with a 'setup' and 'loop' function similar to Arduino programming.
Planned extensions:
- TSL25911FN, LTR390, or other IR/UV sensors
- BMI055 IMU
As you can probably tell, I'm a big fan of this whole 'I2C' thing. I'm starting to explore SPI as well but I'm reserving the UART for the DRA818V radio.
Also, thanks to learning all of this on my own time I've been pronouncing I2C as 'eye-two-see' instead of 'eye-squared-see' like I'm apparently supposed to. No one ever corrected me.
There are a few 'simulated' extensions that are used for testing and debugging.
Utilities
Utilities are scripts that are used across multiple modules/extensions. These include:
- The datastream - The data link between all threads, created in the data module and passed to everything else
- UBX - A I2C UBX driver that is used for u-blox GPS modules
- configurables - A set of macros (I know... I just don't know how to do this better yet) for items that only need to be configured at compile time
- Config Types - The structures and enums used by the configuration module to pass configuration data to other parts of the flight computer
- Socket - A simple socket class used by the web server (Largely followed a tutorial on this one, but I hammered it into a class that I designed)
- A simple timer class
Flight Runner
Everything is pulled together by the flight runner. It's the main thread. It first uses the configuration module to load the user configuration. From here it starts the other modules depending on the configuration. It then starts the 'flight procedure'. This may change in the future but for now that's about it. Eventually it will be responsible for doing the 'health check' which will determine the overall health of the flight computer along with checking it's flight phase based on data relating to the location, altitude, battery state, etc. It will have the ability to fall into a configured failsafe mode if it detects and large issues.
Unit Tests
There are currently 12 unit tests that have helped a lot with debugging issue, especially with regular large changes to the code base. Tests include things like:
- Module Tests
- Driver Tests
- Extension Tests
- Hardware Tests
Future Plans
There are a few things that need to be implemented before it's ready for flight.
- Full Telemetry
- APRS/AX.25
- SSTV (Robot)
- Two way communication
- A data packet log so that things can be retransmitted upon request from the ground station
- Stability
- It's currently very stable, without any crashes or memory leaks, but it can't be fully tested until more is implemented.
Overall, the software is far from perfect. I've learned a lot about C++ and Linux programming since I started this project a few months ago. If I really wanted to do it 'right' I'd have to restart, and with it being over 5,000 lines of bloat, and a hobby project, I'm not going to do that again.
If I could do it again I probably wouldn't make it so threaded, but it's been a fun challenge. The main problem that I'm having with this is large errors when building for the original Pi Zero. Something about older ARM version of this SBC is making it an absolute pain to get compiled. For now I'm testing on a Pi 4 with plans to switch to a Pi Zero 2 W when I can find one.
There have already been so many lessons learned and I'm only fixing non-critical issues as I need to.
Performance wise, the Pi Zero has had no issues running it but we'll see how it does as this project grows.
Hardware

This is what I'm most proud of, even though this is where I have the least experience. I have zero formal education when it comes to electronics, so it's a bit of a disaster, but it's far better than the AOS PCB that I designed a while back.
I started by building a few prototype boards for my individual sensor, specifically the BME280 and the SAM-M8Q. I've probably spent more money than I would have just buying the breakout board but it has taught me a lot.
Below is a picture of the BME280 board that I designed, without two BME280 sensors in their package next to it. I've was worried about this being my first attempt at doing hot air reflow soldering, but it worked after a few tries!
The pull up resistors were not needed as the Pi has internal pull ups, but I put them on the board just incase they were. There are also two 0.1uF decoupling capacitors on the board.

The SAM-M8Q board is just the footprint for the module and a large ground plane (as recommended by the datasheet). I forgot the capacitors on this one, but it still works fine, it's a prototype board after all.

The main flight computer is now called 'GFC' or Giraffe Flight Computer, because why not.
It is also modular by design. The Hat includes a the BME280, MAX17049, the IMU in future versions, an EEPROM for GPIO configuration at boot time, and power supply circuitry for semi-reliable 5V power. It also includes connectors for expanding on the SPI, I2C, and 1-wire buses.
This is the first prototype that I've had fabricated and it works but needs some major revisions.

The SAM-M8Q is not included on the hat as I wanted to keep the form factor of a Pi Zero and it requires a large ground plane, it'll be on a separate board.
The radio is also not included on the hat, as it will be on a hat sized board but placed beneath the Pi Zero, which is why I lovingly call it the 'Shoe'.
I plan on doing this to mitigate problems with RFI/EMI by keeping the radio away from everything else. This one will ideally be a 4 layer board to help with this as well, but it's a work in progress.
So far I'm really happy with this design, especially compared to the AOS PCB. Turns out decoupling capacitors exist for a reason, and they've already solved problems with noise.
My biggest issue with hardware debugging is that I did do not have all of the equipment that I would like to have, but I've made things work. Overall my 'lab' is a small desk with various cheap tools. I'm very happy with what I've been able to do with as little as I've spent.
My tools include:
- Hantek 6022BE Oscilloscope - As good as you'll get for $50
- $8 logic analyzer - Great when paired with Saleae Logic software
- Weller WES51 Soldering Station - Well worth the 20 soldering irons
- Generic 858D Hot Air Rework Station - For $35 it's not bad, other than the fact that I had to rewire it as soon as I bought it thanks to the commonly known issue with the fuse being on the neutral line and the case not being grounded.
- Fluke 175 Multimeter - This was purchased used for $100 and was also well worth it after going through many walmart multimeters over the years

It's not much, but I'm thankful for the tools that I've been able to get experience with.
Conclusion
This is a continual project that I'm spending all of my spare time on between work and school but it's taught me a lot. I'm going to continue to work on it and hopefully get it to a point where it's ready for flight by the end of 2023.
It's been a lot of fun building this from scratch, including my own modulation and I can't wait to see what I can learn in the future.
If you want to know more about it, check out following links:
- The Doxygen Documentation giraffe.joshuajer.red
- The GitHub Project https://github.com/users/joshua-jerred/projects/3/
- The GitHub Repository Development Branch https://github.com/joshua-jerred/Giraffe/tree/development