Project
BeliefSat
Firmware and systems programming for BeliefSat, a student-built PocketQube satellite, with a focus on constrained embedded systems, telemetry, communication, and fault tolerance.
August 2020 — May 2022
What does it take to write software that has to keep running on a tiny computer, communicate over radio, and recover when something goes wrong?
BeliefSat was a student satellite project where I worked on the firmware and programming side of a 2P PocketQube. I was the Head of Programming for the team.
The software had to sit close to the hardware: reading sensors directly, managing the radio, collecting telemetry, handling commands, transmitting images, and making sure the spacecraft could recover from faults without someone physically touching it.
The project was a particularly good introduction to embedded systems because memory, power, communication bandwidth, and failure recovery were all real constraints rather than theoretical ones.
The Firmware
The main responsibility of the programming team was the spacecraft firmware.
Unlike application software, we couldn't simply add another library when we needed functionality. The microcontroller had limited memory, and the final firmware had to fit within those constraints.
For several sensors, I worked from the underlying implementations and extracted the parts we actually needed. Instead of carrying entire libraries and their header dependencies into the firmware, the required functions were pulled out and adapted to the spacecraft code.
This made the firmware smaller while still giving us control over the hardware we were interfacing with.
The result was firmware that directly handled interfaces such as I2C and SPI, rather than treating the sensors as black boxes.
Working Under Memory Constraints
One of the most interesting parts of the project was that code size actually affected engineering decisions.
For each peripheral, we had to ask:
What functionality do we actually need?
A general-purpose library might support dozens of features that are useful on a normal Arduino project but unnecessary on a spacecraft controller.
We therefore stripped implementations down to the functionality required by the mission. This meant working closer to the sensor datasheets and registers and writing smaller, purpose-built pieces of firmware.
That experience changed the way I think about abstraction: sometimes the best embedded abstraction is the smallest one that does exactly what the hardware needs.
Telemetry
The spacecraft continuously collected information about its own state.
The firmware gathered measurements from:
- Temperature sensors
- Ambient light sensors
- Gyroscope
- Magnetometer
- Solar power sensors
- Battery voltage
- Battery state of charge
These values were packed into a fixed telemetry structure and transmitted to the ground station.
The telemetry also included things such as reset counts and the current operating mode, which made the packet useful not only for observing the spacecraft but also for diagnosing problems.
Communication
The spacecraft communicated with the ground through a radio link, and the firmware handled both transmission and reception.
The communication layer included:
- Telemetry downlinks
- Command uplinks
- Digipeater functionality
- Radio mode changes
- Packet validation
- Interrupt-driven reception
- CRC validation
- Reed–Solomon error correction
For telemetry packets, the firmware calculated a CRC and added Reed–Solomon parity before transmission.
On reception, packets were checked and error-corrected before commands were processed. Commands were also checked against the spacecraft callsign so that packets intended for another system would be discarded.
Fault Tolerance
A spacecraft can't rely on someone restarting the computer when it gets stuck.
The firmware therefore used a watchdog timer as one of its main recovery mechanisms.
The software regularly reset the watchdog while long-running operations were in progress. If the controller stopped responding for too long, the watchdog would reset it automatically.
We also kept persistent reset information so that the firmware could distinguish between different types of resets and retain useful state across restarts.
The spacecraft also had different operating modes, including normal, safe, automatic image transmission, and silent modes.
Battery state affected the operating mode automatically. When battery levels dropped, the firmware could move into a safer mode rather than continuing to operate as if power were unlimited.
The Camera Problem
One of the more interesting problems we worked on involved the spacecraft's camera.
The camera was mounted on one face of the satellite while light sensors were distributed across the spacecraft. By comparing the amount of light detected on different faces, we could estimate where the Sun was relative to the spacecraft.
That created another problem:
The camera should not point directly at the Sun when taking an image.
So image capture could not simply be treated as:
timer → take picture
The spacecraft first had to reason about its orientation relative to the incoming light and determine whether taking the image was safe.
The camera system itself also had to work within the same resource constraints as everything else. The firmware controlled the camera over SPI, captured JPEG data into its FIFO, converted it into SSDV packets, and transmitted those packets over the radio.
The payload was later removed from the mission, so this particular camera implementation did not ultimately fly. The engineering problem was still a useful exercise in combining sensors, hardware constraints, and decision-making in firmware.
Sending Images From Space
Sending an image is very different from sending a small telemetry packet.
The firmware captured a JPEG image from the camera, processed it using SSDV, split it into radio-sized packets, and transmitted the resulting stream.
The radio was reconfigured for the image transmission mode, including a higher data rate and larger packet size than normal telemetry.
This required coordinating several pieces of software and hardware at once:
Camera → SPI → JPEG data → SSDV → radio packets → ground station
It was one of the places where the project stopped feeling like isolated sensor programming and started looking like a complete embedded system.
Radio and Protocol Work
The firmware also contained our own integration layer around the radio hardware.
I worked with the radio interface at the register and SPI level and adapted the radio library to the hardware we were using.
The communication system supported both normal telemetry and command-driven operations such as changing modes, enabling transmission, triggering image capture, and resetting the spacecraft.
The project also included an APRS-based firmware implementation for telemetry and amateur-radio functionality.
Programming Lead
As Head of Programming, my role wasn't limited to writing firmware.
I was responsible for the programming side of the project and for coordinating the software work with the hardware and other subsystems.
A satellite forces these boundaries to disappear quickly. A change in the electrical design can affect firmware. A change in the radio protocol can affect telemetry. A memory problem can force a different implementation of a sensor driver.
That made the project a good lesson in designing software around a physical system rather than designing software in isolation.
What I Learned
BeliefSat was one of my earliest experiences where software had hard physical consequences.
There was no server to scale up, no extra memory to allocate, and no opportunity to manually fix a machine once it was operating remotely.
The biggest lesson was learning to treat constraints as part of the design.
Memory affected how we wrote drivers. Power affected operating modes. Radio bandwidth affected packet formats. Fault tolerance affected control flow.
It was also the project that made me appreciate how much software engineering exists below the level of operating systems and frameworks.
Sometimes you're just talking to a sensor register over I2C, keeping a watchdog alive, and trying to make sure the satellite doesn't take a picture of the Sun.
Tech
C · C++ · Arduino · Embedded Systems · I2C · SPI · APRS · FSK · Reed–Solomon · SSDV
Role
Head of Programming
Worked on spacecraft firmware, sensor integration, communication, telemetry, fault handling, and embedded systems design.