Embedded telemetry · field notes

What a pressure logger learns when nobody tells it where it is going

A small MicroPython instrument has ridden along in the cabin of twenty sectors — ten on airliners and ten on business jets — sampling pressure every two seconds. It has no GPS, no route, no idea it is on an aircraft at all — only a barometer and a clock. Read back afterwards against the airframe's own ADS-B altitude, it turns out to reconstruct most of the trip on its own. It also failed in three instructive ways, which is the more useful half of the story.

The charts below are the eleven most recent flights, newest first: six legs in three days on a larger business jet — a short out-and-back, then four longer legs out and home again — then a trip home in four legs — two narrowbody sectors, one on a business jet over open water, and a long-haul widebody — and, at the bottom, an earlier out-and-back on the business jet. The longer business-jet legs flew in pairs on a single boot, the logger riding straight through each stop. All eleven carry cabin oxygen and an accelerometer, every leg is logged wheels-up to wheels-down on a network-verified clock, and the airframe is tracked from takeoff to touchdown on each, apart from a few short gaps in coverage. The older traces each lacked at least one of those, so they have been retired from the page; what they taught is kept in the notes further down.

The run

Airframe, cabin, oxygen and turbulence, on one clock

The latest flights

What it found

Six things worth the trip

The altimeter mapped the route without knowing it

Two of the earlier sectors were not point-to-point — each set down at an intermediate airport before continuing. Nothing in the logger knows that. But on both, the cabin trace descends, settles on a plateau roughly 1,100 ft above the departure field for about seventy minutes, then climbs away again. That plateau is the intermediate airport's elevation: with the doors open, cabin pressure is simply local pressure, so the instrument was reading the ground it was parked on. A barometer alone recovered the shape of the itinerary.

isa datumbmp3902 s sampling

Newer airframes really do run lower cabins

Composite airframes are marketed on a lower cabin altitude, and the claim survives contact with a cheap sensor. The 787-8 held its cabin at 5,995 ft — effectively the 6,000 ft figure Boeing advertises. The A330-300 flown the same week ran 7,304 ft, about 1,300 ft higher, for ten hours overnight. Same passenger, same instrument, one week apart. That difference is the entire marketing claim, and it is sitting in a CSV on a microSD card.

The trip home in the charts above makes the same point from the other side. The A350-900 — Airbus's composite answer to the 787 — held 5,671 ft at FL390 for six and a half hours, the lowest cabin of the whole run. Two days later, two A321 sectors ran 7,132 ft and 6,877 ft while flying lower, at FL361 and FL351: roughly 145 ft of cabin per 1,000 ft of aeroplane on the widebody against nearly 200 on the narrowbody.

cabin altitude1013.25 hPacross-check

Power is the constraint, not storage

One sector fragmented across eight reboots. Another lost nearly four hours mid-flight, taking an entire intermediate stop with it. A fifth was never recorded at all, because the battery was flat before boarding. Across sixty-two boots the card had consumed 7.6 MB. Everything that went wrong was a power-budget failure wearing a data-loss costume, which is the sort of thing you only learn by flying the device rather than bench-testing it.

power budgetbrown-outsd write path

A business jet squeezes the cabin before it moves

The business jet does something the airliners only hinted at. On both legs the lowest cabin reading is not in the air — it is on the runway, −230 ft on the way out and −204 ft on the way back, in the seconds before the wheels leave. The jet deliberately pressurises the cabin slightly tighter than the air outside so that rotation is a smooth continuation rather than a step. The previous flight on the same type showed it too (−172 ft), and the over-water leg in the charts above went further still, −327 ft — so it is a habit of the aircraft, not a one-off. The airliners do it more gently: −172 ft on the A350, −152 and −54 ft on the A321s.

It also flies higher than any airliner in the run and still holds a lower cabin than the A330 did: FL410 outside and 6,357 ft inside on the way out, FL400 and 6,174 ft on the way back — about 155 ft of cabin for every 1,000 ft of aeroplane both times (and 154 again on the over-water leg at FL401), and over 1,600 ft of headroom under the 8,000 ft line the instrument is named for.

The newest six legs are on a different type, a Gulfstream G150, and it makes a different trade. On the four long legs it cruised at FL410–431, the highest of the run, and held the cabin at 7,480–7,507 ft every time — about 175 ft per 1,000 ft, closer to the A321 than to the other business jet, and the highest cabin the logger has recorded. Pinned that tightly, it reads like a pressurisation controller sitting on its limit rather than following a schedule. On the short hop at FL390–400 it ran a gentler 6,340–6,643 ft. The pre-takeoff squeeze is there on every leg, −200 to −309 ft.

pre-pressurisationdifferentialFL430

The cabin waits, then drops

Going down, the aeroplane and the cabin do not descend together. On both legs the cabin came down to a shelf 700–800 ft above the arrival field and held it while the jet flew the rest of the approach. Then, in roughly the last ninety seconds before touchdown, it let the remaining difference go at once: about 700 ft a minute averaged over that minute, with single readings over 900 on the return leg. Every other part of the flight changed cabin pressure more gently than that.

For most passengers that is a brief pressure in the ears. For anyone with a blocked ear or sinus, it is the part of the flight that hurts, and it happens when everyone is belted in and paying attention to the landing instead.

cabin rateapproach2 s sampling

The oxygen cell measures change, not altitude

The plan was for the oxygen cell to read low at altitude. Cells of this kind are usually described as tracking the partial pressure of oxygen, and at a 6,300 ft cabin that is about a fifth lower than on the ground, so the cell should have read about 16.5%. It did not. Settled at cruise, it read 20.3–20.7%, within a few tenths of the 20.9% on the ground.

What it did react to was pressure changing. It dipped to 19.2–19.4% in each climb, rose to 22.5–22.8% in each descent, and settled again once the cabin stopped moving. Neither of those is a real change in the air. As built, it is not a hypoxia instrument. It is a good pressure-rate detector, and that is a useful thing to find out before trusting its number on a flight where it matters.

sen0322electrochemical o₂transient

The interesting bug

A clock that lies quietly

The logger syncs time over NTP when it can find a network on the ground. When it cannot, it restores the clock from the card — and the restored value carries the date forward correctly while silently losing however long the device was powered off. Timestamps stay plausible. They are simply early, and they get earlier with every reboot.

Four boots in the earlier run had a real NTP fix. Nine did not. Nothing in the data announces which is which except one honest line in the event log, so a trace can look perfectly well-formed and still sit hours away from where it belongs. The fix was to stop trusting the logger's clock where it was not anchored, and re-derive the offset from an external reference: the airframe's own ADS-B track, which puts a hard timestamp on touchdown. That moved one sector by 4h35 and another by 3h17 — and corrected an earlier reconstruction that had anchored to the published timetable instead, which was wrong by up to 39 minutes because both aircraft landed early.

The general lesson is dull and worth repeating: a timestamp that looks reasonable is not evidence that it is right, and a device with no network is not in a position to know what time it is. Log the provenance of the clock alongside the reading, or you will not be able to tell the difference later.

Build

What it is

Raspberry Pi Pico 2 W running MicroPython. A BMP390 barometer on I²C, cross-checked against a second barometer, plus an electrochemical oxygen cell and an MPU-6050 accelerometer on a separate I²C bus. MicroSD over SPI for the log, and a low-power e-ink panel for a glanceable readout. Cabin altitude is derived from pressure against the fixed ISA sea-level datum of 1013.25 hPa — deliberately not corrected for local weather, because that is the definition of the quantity rather than an oversight.

The write path is built for sudden power loss: events are buffered in RAM while a freshly mounted card refuses I/O, the SD bus is pinned to a rate the card actually handshakes at rather than the one the driver claims, and a boot that cannot mount storage still runs and still displays. Most of the hardening in it exists because something failed in the air first.

micropythonrp2350bmp390mpu-6050o₂ cellspi / sde-inkads-b

A hobby instrument, not a certified one. Nothing here is an airworthiness measurement, and cabin altitude as recorded is a physical quantity, not a comment on any operator.

Instrument notes

Reading the turbulence trace

The logger carries an accelerometer. It writes two numbers per sample and shows one of them on its screen as TRB. The sensor reports three axes; the logger uses none of them directly, and takes the magnitude of the vector instead:

|a| = √(x² + y² + z²)

then subtracts the resting value measured at startup. Using magnitude rather than a single axis means orientation is irrelevant — the device can lie at any angle in a seat pocket and the numbers stay comparable between one flight and the next. There is no “this way up”.

Peak is the largest deviation in the sample window and is what the screen shows; RMS is the sustained energy across it. They answer different questions. Peak answers what was that jolt, RMS answers how rough was this leg overall. A sector reading RMS 0.2 throughout was genuinely uncomfortable; one reading RMS 0.02 with a single 0.8 peak hit one bump.

The baseline is measured, not assumed

Sitting still on a bench this sensor reads 1.0249 g, not 1.000 — a scale error of about 2.5%, comfortably inside its stated ±3% tolerance and completely disqualifying if you hard-code gravity as 1. You would publish a permanent 0.025 g of turbulence that does not exist.

So the logger spends its first thirty seconds after power-on learning what “still” reads for this sensor in this orientation, and measures everything afterwards from there. That cancels scale error, zero offset and mounting angle in one step. The cost is an operating rule: switch it on, stow it, leave it alone for half a minute. A baseline learned while it is being carried to the seat is wrong for the whole flight, and nothing downstream can detect that.

Before the table: these bands are a rule of thumb for reading one homemade instrument’s own traces. They are not how turbulence is classified.

ICAO and the FAA define turbulence by aircraft reaction and occupant effect, not by cabin acceleration. The objective standard used operationally is EDR (eddy dissipation rate), which is deliberately aircraft-independent, because the same air shakes a business jet and a widebody very differently. Nothing here substitutes for either, and none of it should be reported as a turbulence observation.

Peak deviation from the resting baseline — orientation for reading these traces, not a severity scale.
TRB peakWhat it usually means
0.00 – 0.03 gNoise floor. The device is still
0.03 – 0.15 gNormal cruise. Engine and airframe vibration
0.15 – 0.5 gLight chop. Noticeable; drinks ripple
0.5 – 1.0 gModerate. Strain against belts, walking difficult, loose items shift
> 1.0 gSevere. Violent against belts, unsecured objects thrown
1.2 – 2.5 g, briefAlmost certainly a touchdown spike, not turbulence
3 g and upSomeone picked it up

Four reasons this is not a severity instrument

It measures a seat pocket, not an airframe. This is the big one and no amount of signal processing fixes it. A passenger shifting, a trolley clipping the armrest, someone kicking the seatback — all of it looks exactly like turbulence to an accelerometer in a pocket. An isolated spike with a quiet minute either side is far more likely to be a person than weather.

Vector magnitude reads high. The conventional g-figures quoted for turbulence refer to vertical acceleration. This sums all three axes, so for the same bump it reads somewhat higher. Fine for comparing its own sectors against each other; wrong for comparing against anything published.

Range clipping. The sensor runs at ±4 g per axis, chosen because ±2 g would clip on a firm touchdown — one of the two events worth catching. A hard enough event can still saturate an axis, and when it does the computed magnitude under-reports. Large readings are a floor, not a ceiling.

Nothing here is certified. It is a hobby sensor on a hobby board, cross-checked against nothing but itself. The value is in the shape of a trace over two hours, not in any single number being right to three decimals.

What it is actually good for

The accelerometer did not go in to measure severity. It went in for timing. Two signatures are unmistakable: the take-off roll, sustained elevated RMS for thirty to forty seconds with a modest peak — a long push, not a jolt — and touchdown, a sharp isolated peak against low surrounding RMS.

Those give two hard local time markers. A boot that lost its time reference can be re-anchored against a public ADS-B track by lining up wheels-up and wheels-down. The turbulence channel earns its place as a clock before it earns anything as a weather instrument.

mpu-6050fifovector magnitudelearned baseline

The flight plotted above is the first to carry this channel. Cruise sat around 0.1 g, in the normal-cruise band. Most readings past 1 g are on the ground, during taxi and the turnaround, when the logger was most likely being handled. The five in the air, all on the return leg (1.1, 1.6, 2.3, 2.6 and 4.1 g), are each a single reading with about 0.1 g either side. By the table above, that is a person, not the weather. Its resting floor on the ground also read about 0.05 g rather than the 0.01–0.03 the bench gives, so read the whole band as sitting slightly high.

More

Back to the rest of the work

All work About