Software engineers underestimate how much of embedded work is epistemics — figuring out what's actually true about the physical world — rather than logic. A bug in a web app is reproducible. A bug caused by a loose solder joint that only manifests above 30°C is a different kind of problem entirely.
Things that transferred cleanly
State machines. Firmware is basically state machines all the way down, and if you've written game AI or UI flow logic, you already have the right mental model. Version control discipline also transfers directly — treat your firmware and your PCB design files with the same rigor as application code.
Things that didn't
- "Just add logging" isn't free. A
Serial.printlnon a tight interrupt loop can change your timing enough to hide the bug you're chasing. - Nothing is instant. Every sensor read, every I2C transaction, has a real-world latency that software intuition wants to treat as zero.
- Failure is physical, not just logical. A software dependency doesn't corrode. A connector does.
The advice I'd give my past self
Prototype the electrical and mechanical uncertainty first, and the software last. It's tempting to do the opposite because code is what you're fast at — but the sensor rig that taught me the most started as a breadboard with no code on it at all, just proving the signal was clean before I wrote a single line of firmware.