# Debugging and Testing Embedded Code — Arduino & Embedded C

Source: https://www.geekswithgeeks.com/en/arduino-embedded-c/debug-test

> Serial logs, logic analysers and host-side unit tests.

## See what the device is really doing

**Serial logging** is the first tool: print state changes and key values with timestamps, behind a debug flag so you can turn it off. Remember printing takes time and can change timing-sensitive behaviour. A **multimeter** checks voltages and continuity; a **logic analyser** captures digital signals over time and can decode UART, I2C and SPI, which is invaluable when a bus misbehaves; an oscilloscope shows analog detail such as noise or slow edges. Some boards support hardware debuggers with breakpoints. For correctness, separate **pure logic** (parsing, filtering, state transitions, unit conversions) from hardware access so it can be compiled and **unit-tested on your PC** with a normal compiler; test hardware-touching code on the device. Tools such as PlatformIO include unit-test runners; check their docs.

## Logic separated from hardware, tested on the host

Plain C: the conversion function has no hardware dependencies, so it compiles both for the board and for a PC test program.

```c
/* temp.h / temp.c: pure logic, shared by firmware and tests */
#include <stdint.h>

/* TMP36 on a 10-bit, 5 V ADC: returns tenths of a degree C */
int16_t tmp36_tenths_c(uint16_t raw) {
    int32_t millivolts = (int32_t)raw * 5000 / 1023;
    return (int16_t)(millivolts - 500);   /* 10 mV per degC = 1 mV per 0.1 degC */
}

/* test_temp.c: built with a desktop compiler, not uploaded */
#include <assert.h>
int main(void) {
    assert(tmp36_tenths_c(0) == -500);    /* 0 V    -> -50.0 C */
    assert(tmp36_tenths_c(153) == 247);   /* ~0.748 V -> about 24.7 C */
    return 0;
}
```

## Compile and run the host test

Shown, not run; any desktop C compiler works.

```bash
gcc -Wall -Wextra -o test_temp test_temp.c temp.c
./test_temp && echo "all tests passed"
```

## Debug macros that compile away

Wrap logging in a macro such as DEBUG_PRINT that expands to nothing when a DEBUG flag is off, so release builds pay no flash, RAM or timing cost.

**Quiz:** Which tool is best for seeing why an I2C transaction fails?

- [ ] A thermometer on the chip
- [ ] Adding a longer delay() at random places
- [x] A logic analyser that captures and decodes SDA and SCL
- [ ] Recompiling with a different baud rate

*Answer:* A logic analyser that captures and decodes SDA and SCL. Seeing the actual bus traffic shows missing ACKs, wrong addresses or timing issues.
