SCK-PBL-1 · Documentation · Developer Notes

SCK-PBL-1 Developer Notes

SCK-PBL-1 Payload Board — Developer Notes

SpaceCommsKit — https://spacecommskit.com
Version 1.0

This is a companion to the SCK-PBL-1 User Guide. The User Guide tells you what's on the board and how to talk to it. This page is different: it's a record of real problems found during bring-up of this board, exactly how each one was tracked down, and what the actual fix turned out to be — including a couple of cases where the obvious suspect was wrong and the real bug was hiding somewhere nobody was looking.

If you're building on this board and hit a symptom that sounds like anything below, start here. It'll likely save you the time it took us to find it the first time.


1. The MS5611 Pressure Bug

The board's altimeter is an MS5611-01BA03 barometric pressure sensor. It measures air pressure and reports it over I2C along with a set of factory calibration numbers; the firmware combines the two using a formula from the sensor's datasheet to produce a pressure reading in hPa (hectopascals — the standard unit for atmospheric pressure; sea-level pressure is typically around 1013 hPa) and a derived altitude.

On a brand-new, fully assembled board, the very first pressure readings out of this sensor were consistently around 1970–1973 hPa — roughly double normal atmospheric pressure at ground level. Temperature readings from the same sensor looked completely normal throughout. The mismatch was stable and repeatable, not noisy or occasional.

Why this took a while Every individual step below was a reasonable thing to check given what was known at the time, and each one came back clean. That's actually the useful part of this story: a long list of "not the problem" is often what it takes to find something that's genuinely unusual, and it's worth reading through even though the real answer turns out to be short.

What was ruled out, and how

Suspected causeHow it was testedResult
Corrupted calibration dataReverse-derived all six calibration coefficients by hand from the sensor's own printed output and checked them against normal MS5611 factory rangesAll six were realistic, genuine values — not corrupted
Formula implemented wrongRe-ran the datasheet's compensation formula by hand using the sensor's own logged numbersThe arithmetic matched exactly, given those inputs
Sealed pressure portPhysically inspected the sensor package for shipping tape/film over the two pressure portsBoth ports open, no seal present
Power pins wired wrongMeasured supply (VDD), protocol-select (PS), and ground (GND) pins directly with a multimeterAll three measured exactly correct
I2C wiring wrongTraced SDA/SCL connections against the schematic and confirmed pull-up resistor valuesCorrectly wired, standard pull-ups
ADC conversion read too earlyWidened the conversion wait time well past the datasheet's stated minimumReduced reading-to-reading noise, but did not move the actual offset
Sensor hadn't finished settling after reflow solderingChecked the manufacturer's own soldering guidance, which recommends 48 hours of rest after the last solder step before trusting readingsBoard was already well past that window
A specific "reserved" pin wired to the wrong railPhysically reworked the board to tie the pin to ground per the datasheet's reference circuit, retestedNo change in the reading — directly disproven
One defective sensorSwapped in a second, then a third physically different sensor (different manufacturing date, opposite end of the same reel), retested eachAll three produced the same wrong reading — rules out a single bad part

The actual bug

The detail that cracked it: the wrong reading wasn't random or vague, it was landing at almost exactly double the correct pressure — 2.00×, to four significant figures, confirmed against an independently measured reference reading and reproduced across three different physical sensors. A clean, precise ratio like that is the signature of a units or scaling error, not a hardware fault — random defects don't converge on an exact multiplier.

Cross-checking the firmware's compensation math against a trusted, independent open-source MS5611 library turned up the real issue: the MS5611 sensor family has two different sets of internal math constants depending on the exact chip variant, and this firmware had been using the wrong set — every one of four constants was set to a value meant for a closely related sensor, not this one. Using the wrong constants doesn't cause an error or a crash; it just silently computes a pressure that's exactly double what it should be, for any sensor, every time.

Root cause Four shift constants in the pressure compensation formula were using values from a related sensor variant instead of the genuine MS5611 datasheet values. This inflated the computed pressure by exactly 2× on every reading, regardless of which physical sensor was attached — which is exactly why swapping sensors never changed anything.
# Wrong (silently doubled every pressure reading):
OFF  = C2 * (1 << 17) + (C4 * dT) // (1 << 6)
SENS = C1 * (1 << 16) + (C3 * dT) // (1 << 7)

# Correct:
OFF  = C2 * (1 << 16) + (C4 * dT) // (1 << 7)
SENS = C1 * (1 << 15) + (C3 * dT) // (1 << 8)

After the fix, pressure readings matched an independently measured reference value to within normal sensor accuracy, and computed altitude finally agreed with GPS altitude for the first time in the investigation.

Lessons

  • A precise, repeatable ratio in a bad reading (like an exact 2×) is a strong clue on its own — it usually means a units, scaling, or constant error, not a flaky connection or a bad part.
  • If the same wrong answer shows up on multiple physically different units of the same part, stop suspecting the hardware and start suspecting the code or the math.
  • Confirming that a formula's arithmetic is internally consistent proves you haven't mistyped an operator. It does not prove the constants going into that formula are the right ones for your specific part — check those against an independent reference too.

2. GPS Airborne Mode Not Actually Taking

The onboard GPS module needs to be switched from its default "Portable" navigation mode into "Airborne" mode to track altitude reliably above roughly 12km — necessary for high-altitude balloon flights. This is done by sending the module a specific configuration command at startup (a UBX-CFG-NAV5 message, in u-blox's binary protocol).

The original firmware sent this command but never actually confirmed the module accepted it — it just printed a success message regardless. On inspection, the command being sent was malformed: it was missing its checksum bytes, meaning the GPS module had no valid way to accept it and was silently ignoring it every time. The board would have flown with the GPS still in default mode without anyone knowing.

The fix, in three parts

  1. Corrected the command itself so it's a complete, properly checksummed message the module can actually parse.
  2. Narrowed what the command changes. The original command tried to set every navigation parameter at once. Some GPS module variants will silently reject a request like that if they don't like any single parameter in the batch. Limiting the command to change only the one setting that actually matters (the navigation dynamic model) fixed this on a module that had been rejecting the broader request.
  3. Added real verification. Some GPS modules acknowledge configuration commands directly; others don't, even though they're otherwise working normally. The firmware now checks for an acknowledgment first, and if none arrives, falls back to asking the module directly what mode it's currently in — a stronger check either way, since it confirms the setting actually stuck rather than just that a command was sent.

The firmware now reports this status as part of every GPS reading — the ground station or any downstream tooling can see whether airborne mode is confirmed active, failed, or unconfirmed, instead of trusting a print statement that never checked anything.

Lesson

Sending a configuration command successfully is not the same as the receiving device actually applying it. If a setting matters for how your mission behaves, verify it took effect — with an acknowledgment if the device supports one, with a direct read-back if it doesn't — and report the real, confirmed state, not just "we sent the command."

3. SD Card Mounting Intermittently

During bench testing, the SD card sometimes failed to mount at boot and sometimes mounted fine, with no consistent pattern. The first explanation — that the board had been physically bumped and the card had worked loose — turned out to be a real, confirmed cause on at least one occasion. But a later, controlled test showed the same on/off pattern happening across power cycles with the board sitting completely untouched, which ruled out physical handling as the explanation for that pattern.

This points at a marginal timing issue rather than a mechanical one: SD cards need their supply voltage and a short settle period before their initialization sequence will reliably succeed, and that margin can vary slightly from one power-up to the next for reasons that have nothing to do with how the card is seated.

The fix

A short retry loop at boot — if the first mount attempt fails, wait briefly and try again, up to a few times, before giving up:

SD_MOUNT_RETRIES = 3
for attempt in range(1, SD_MOUNT_RETRIES + 1):
    if mount_sd():
        break
    print(f"SD mount attempt {attempt}/{SD_MOUNT_RETRIES} failed, retrying...")
    time.sleep_ms(300)
else:
    print("SD mount failed after all retries -- flight log will not record")

This resolved the issue cleanly across repeated testing.

For actual flight use

A reliable boot-time mount doesn't guarantee the card stays seated through real flight conditions — vibration during ascent and temperature extremes at altitude can still work a friction-fit card loose even when bench testing looks perfect. Worth considering before flight, roughly in order of how much protection each gives:

  • A small printed or fabricated bracket that physically prevents the card from backing out of its socket
  • A strip of Kapton (or similar high-temperature-rated) tape anchoring the card in place — simple, common in amateur high-altitude ballooning, and tolerant of the temperature range involved
  • A small dab of glue at the card's edge, away from the electrical contacts, for a more permanent hold at the cost of easy removal
  • Specifying a socket with a push-push latching mechanism on a future board revision, rather than a plain friction-fit slot

Lesson

An intermittent failure that happens with no physical handling involved is a different kind of problem than one that happens after the board gets bumped. Both are real and worth fixing, but they point in different directions — check which one you're actually looking at before deciding on a fix.

4. Known Issue: Command Replies Aren't Verified

Open issue — not yet fixed This is a structural gap in the current firmware, not a bug that's been resolved. It's included here as a known risk for anyone building on this board today.

Both the SCK-915 and SCK-2400 radio boards bridge commands to this payload board over a simple UART link. When the radio board sends a command to the payload processor and waits for a reply, it currently accepts whatever response arrives next as the answer — it doesn't check that the reply actually corresponds to the command it sent.

Normally this isn't a problem. But the payload board also sends autonomous GPS telemetry (a "beacon") on its own independent timer, completely decoupled from command/response timing. If that beacon happens to transmit at the same moment an unrelated command is waiting for a reply, the radio board can mistake the beacon data for the answer to a completely different command — this was directly observed: a request for onboard temperature came back holding GPS coordinates instead.

Compounding this, the radio board's command-handling loop blocks — it can't process anything else — for up to several seconds while waiting for a reply that may never come. With a beacon interval on the same order as typical command round-trip time, the odds of this kind of collision on any given command turn out to be uncomfortably high, not a rare edge case.

Current mitigation

None built into the firmware yet. During development, the autonomous beacon can be temporarily disabled to get reliable command testing done — but the beacon is the actual telemetry downlink in flight, so this is a testing convenience only, not something to rely on for a real mission.

What actually needs to happen

The command protocol between the radio board and the payload processor needs real request/response matching — a sequence number or command echo that lets the radio board confirm a reply actually corresponds to what it asked for, so beacon traffic arriving at an inconvenient moment gets correctly ignored instead of mistaken for an answer. Until this lands, any use case involving frequent on-demand commands running at the same time as the autonomous beacon should be treated as carrying real risk of this kind of mismatch.


5. MS5611 Manufacturing Notes

From the sensor manufacturer's own soldering guidance (application note AN808), for anyone assembling boards with this part:

  • No special moisture bake-out step is required before reflow — standard industry-standard reflow profiles apply.
  • Hand soldering this part is not recommended; it's designed for machine reflow.
  • Use "no-clean" solder flux, and don't wash the board afterward — cleaning fluid can get into the sensor's exposed pressure port and damage it.
  • Let a freshly soldered board rest at room temperature for at least 48 hours before trusting sensor accuracy. Thermal stress from soldering affects readings until it has time to settle. Worth checking explicitly if you're seeing an unexplained pressure offset on a board assembled within the last two days.

6. Patterns Worth Reusing

A few practices from this bring-up that are worth carrying into future work on this firmware:

  • Retry loops for anything with a startup timing margin. Both the GPS mode configuration and the SD card mount needed the same shape of fix: try a few times with a short pause in between, rather than a single fixed-length delay and a hard failure.
  • Verify configuration commands, don't just send them. Anything that configures external hardware should report a real, checked outcome that the rest of the system — and ground telemetry — can act on.
  • Leave useful debug instrumentation in place, disabled, with a note. The diagnostic output that eventually found the pressure bug above is still in the firmware today, commented out, with an explanation of exactly what it caught. The next person chasing a strange sensor reading gets a head start instead of starting over.
  • When a bug seems to follow the code rather than the hardware, prove it by swapping the hardware. Reasoning about it is a good start; actually testing a second and third physical unit is what turned "probably a bad sensor" into "definitely not a bad sensor" here.

Found something that isn't covered here, or have your own hard-won lesson to add? Open an issue or PR against the firmware repo — this document is meant to grow with the project.