Software reliability is usually about correctness: given valid input, does the program produce the right output? Hardware reliability is about survival: does this device keep working after three years of heat, vibration, and voltage noise? IoT products need both, and the interesting failures happen where the two definitions meet.
A device can run perfectly correct firmware and still be unreliable, because the firmware assumed conditions the hardware cannot guarantee. Equally, robust hardware can be made fragile by software that trusts it too much.
This guide covers that boundary: how physical faults appear to software, how to write firmware that survives them, and how to build devices that can explain themselves when something goes wrong.
Why Correct Software Still Fails on Real Hardware
Software engineering assumes a reliable substrate: memory holds what you wrote, instructions execute in order, peripherals respond. Embedded systems violate all three occasionally.
| Physical reality | How it appears in software |
|---|---|
| Supply voltage sags during radio transmission | Random reset, or a corrupted flash write |
| Electrical noise on an I2C bus | A sensor read that hangs forever |
| Temperature drift in an oscillator | Timing that is accurate at 20°C and wrong at −10°C |
| Flash wear after years of writes | A write that silently fails to persist |
| Connector vibration | Intermittent sensor values that look like real events |
| Battery internal resistance rising with age | Brownouts that appear only during transmission |
None of these are software bugs, and all of them must be handled by software, because software is the only layer that can detect and respond to them in the field.
Firmware that assumes the hardware always works is correct code that produces an unreliable product.
Writing Firmware That Expects Hardware to Misbehave
Never block forever on a peripheral
Every bus transaction, sensor read, and radio operation needs a timeout and a defined recovery path. A single hung I2C read with no timeout will freeze an entire device, and it is one of the most common causes of units that need a power cycle.
Validate everything that comes from the physical world
Range-check sensor readings, verify checksums on serial data, and reject values that are physically impossible. A temperature of −3000°C is a bus error, not a measurement, and treating it as data corrupts everything downstream.
Make persistent writes atomic
Power can disappear mid-write. Use a write-then-commit pattern with a validity marker or a dual-copy scheme so an interrupted write leaves the previous good data intact rather than a half-updated record.
Use the watchdog properly
A watchdog should be fed from a point that proves the system is actually working — the main control path completing a cycle — not from a timer interrupt that keeps running while everything else is stuck. A badly placed watchdog feed hides exactly the fault it exists to catch.
Define a safe state and return to it
After an unexpected reset, the device must start in a state that is safe regardless of what it was doing before: outputs off, actuators neutral, then re-establish context. Resuming blindly from stored state after an unexplained reset is how physical accidents happen.
Report faults instead of hiding them
When a sensor fails, send an explicit error rather than a default value. A missing reading is a manageable gap; a plausible wrong one is a corrupted decision that nobody will question for months.
Making Devices That Can Explain Themselves
Field failures are diagnosed with whatever the device chose to record. A handful of cheap telemetry fields turn an unexplained fault into a clear answer.
- Reset cause. Power-on, brownout, watchdog, or software reset. This single register separates electrical problems from firmware stalls, and without it the two are indistinguishable.
- Supply voltage under load. Measured during transmission, not at idle, so sagging rails and ageing batteries are visible before they cause failures.
- Board temperature. Explains drift and correlates failures with environmental conditions.
- Peripheral error counters. Bus retries, checksum failures, and timeouts since boot show degradation long before total failure.
- Uptime and reset count. A device resetting daily is in trouble even if every individual reading looks fine.
These fields are the difference between remote diagnosis and a site visit, and they belong in the lifecycle event stream from the first build rather than being added after the first incident.
Testing the Boundary Deliberately
Frequently Asked Questions
Conclusion
Reliability in IoT is a property of the boundary, not of either discipline alone. Hardware determines what can go wrong physically; firmware determines whether the product notices, recovers, and explains itself.
Write firmware that expects peripherals to hang, power to disappear mid-write, and sensors to lie. Record reset causes, supply voltage and error counters from the first prototype. Test at the extremes and interrupt power on purpose. Devices built that way fail less, and when they do fail they tell you why.
