Skip to content
scsiwygest. ‘26
Sign in
get startedmcpcommunityapiplaygroundswaggersign insign up
KAIRair — Backyard Weather Network·From Four Sketches to One Firmware13 Jul 2026David Olsson
KAIRair — Backyard Weather Network

From Four Sketches to One Firmware

#kairair#firmware#esp8266#building-in-public#refactor#architecture

David OlssonDavid Olsson

The day I decided to fix this, I was trying to add a board.

I had a new controller on the bench, a slightly different sensor loadout, and a simple goal: get it reporting like the others. So I did the obvious thing. I found the sketch that was closest, copied the whole file, and started changing pins.

Halfway through, I stopped. Because I'd done this exact thing before. Three times.

I had four sketches by then. Four .ino files, each one a complete little firmware for one specific board. And copying a fifth wasn't building a network — it was digging the hole deeper.


what the four sketches were

They're still in the repo, in a folder literally named ARCHIVE/, as a reminder. Four directories: a plain weather station, an "enhanced" one, a command-center variant, and the BME680 build. Honest names for what they were — four takes on the same idea, each grown independently.

Every one of them contained a full copy of everything a station has to do:

  • Connect to Wi-Fi and hold the connection.
  • Read the sensors and turn raw registers into numbers.
  • Package the numbers and POST them to the server.
  • Draw the current reading on the little OLED.
  • Listen for an over-the-air update and apply it.

That's five real responsibilities. And they existed, in slightly mutated form, in four different files. The Wi-Fi reconnect logic in the "enhanced" sketch had a fix the "simple" one never got. The display code in one drew the temperature one way; another rounded it differently. None of it was wrong, exactly. It was just four cousins who'd stopped talking to each other.


the duplication tax

Here's the moment that actually changes your mind about this.

You find a bug — say, the station wedges itself if the Wi-Fi drops at exactly the wrong time. You fix it. You test it. It works. You feel good.

And then you remember it's wrong in three other files.

So now every fix is four fixes, and every fix you forget to make in the other three is a station in someone's backyard running the old, broken version. The duplication isn't a style problem. It's a correctness problem. It guarantees your fleet is inconsistent, because no human reliably copies the same change into four files forever.

That was the realization: the duplication was the bug. Not a bug in the code — a bug in the shape of the project. Four sketches meant four sources of truth for behavior that should have exactly one.


separating what's the same from what differs

The fix has an old, boring name: a hardware abstraction layer. A HAL.

The idea is to split the firmware into two kinds of thing.

The first kind is everything that's the same on every station, regardless of hardware. Talking to the server. Signing and verifying an OTA image. Running the boot self-test. Drawing a reading on a screen. That logic has no business knowing which exact board it's on. It should be written once, live in one place, and be identical on every device in the field.

The second kind is everything that's different. Which pin the sensor sits on. Which sensor it even is. How much voltage the board wants. The screen's I²C address. That's a small, specific set of facts — and it's the only thing that should change from one station type to the next.

So that's what firmware/kairair-node/ became. One firmware. The shared behavior lives in real modules — net for the server conversation, sensor for reading hardware, display for the screen, ota for signed updates, selftest for the boot checks, bus for the shared I²C plumbing. The differences get pushed out to the edges, into two small header files: board_config.h and kit_config.h.

Fix the Wi-Fi reconnect now, and you fix it once. Every station that ever pulls an update gets the fix. There is no "other three files."


the rule I wrote down

I put a rule in the project's instructions, in plain language, so I couldn't weasel out of it later:

When asked to add a second board profile, that is the trigger to start the shared-HAL firmware refactor — rather than copy another monolithic sketch.

That sentence is doing more work than it looks like. The temptation, always, is to copy the sketch one more time — just this once, I'll clean it up later. The rule says: no. The second variant is exactly the moment the cost of duplication becomes real, and exactly the moment it's cheapest to fix. Not the fifth. Not "someday." The second.

Adding a board type is no longer a copy-paste-and-pray. It's a new set of those two small config headers, pointed at the same shared firmware everyone else runs.


the config headers aren't written

There's one more thing, and it's the setup for the next post.

I said board_config.h and kit_config.h hold the pin maps and the hardware facts. But I don't write those files. They're generated — stamped out from a single definition that also produces the wiring diagram and the parts list. If I hand-edited them, I'd just be reintroducing duplication one level down: a pin number that lives in the firmware header and the diagram and the docs, free to drift apart.

So they're marked generated, and hand-editing them is off the table.

That's the real end of the four-sketches problem. It wasn't enough to have one firmware. The one firmware had to get its differences from one source, too.

Which is the next story: the single pile of YAML that every pin map, diagram, and bill of materials in the whole project is generated from.


Part two of the KAIRair build series. Previous: Air, Out Loud. Next: one source of truth — how a folder of definitions generates the firmware, the wiring diagram, and the BOM, so none of them can ever disagree.

Share
𝕏 Post