# Read-only digital probe `app.digital_probe` is the first Magnifica S development tool. It measures a single already-conditioned digital signal; it does not control the machine and never configures the ESP32-C3 pin as an output. ## Electrical boundary — required before connection Do **not** attach an unknown wire from the coffee machine directly to an ESP32-C3 GPIO. First identify the wire with the machine unplugged, then verify its voltage, polarity, ground relationship, and behaviour at power-on with appropriate test equipment. Connect it only through an interface that ensures the ESP32 input stays between GND and 3.3 V at all times, including transients. Use a board GPIO that is actually broken out and not occupied by the board. Avoid GPIO2, GPIO8, and GPIO9 (ESP32-C3 boot strapping), GPIO12–GPIO17 (normally flash), and GPIO18–GPIO19 when USB-JTAG is needed. GPIO3 is a candidate on boards that expose it, but confirm the board schematic first. Keep the probe ground disconnected until it is known to be safe to share a ground. If the machine signal is not confirmed low-voltage and ground-referred, use a suitably rated isolated/conditioned interface instead of a direct link. ## Install and use Deploy the whole `firmware/app/` directory. The probe is included in the OTA manifest, but it is not auto-started, so normal launcher behaviour is unchanged. At the MicroPython REPL: ```python from app.digital_probe import open_probe probe = open_probe(3) # Replace 3 after confirming your board pin and wiring. probe.state() probe.frequency(seconds=2) probe.pulse(timeout_us=1_000_000) probe.watch(seconds=5, max_events=200) ``` ## Continuous probe mode To collect data without interrupting the application, set the following in the device-local `/.env` and reset the board: ```env PROBE_ENABLED=true PROBE_GPIO=3 PROBE_MODE=frequency PROBE_FREQUENCY_SECONDS=2 PROBE_INTERVAL_SECONDS=3 ``` `PROBE_MODE` may be `state`, `frequency`, `pulse`, or `watch`. The corresponding `PROBE_*` settings in `.env.example` control the measurement window, timeout, or event cap. The mode continuously writes its results to the serial console; it does not expose any output pin or machine-control capability. Set `PROBE_ENABLED=false` and reset to return to normal application operation. `frequency()` counts rising edges in its measurement window. It is useful for signal discovery and approximate rates, but very fast or noisy signals can overflow or exceed MicroPython IRQ handling capacity. `pulse()` reports one high and one low width; negative results are timeouts (`-2` means the requested level did not arrive, `-1` means its pulse did not finish). `watch()` is a short, polling-based transition trace and can miss narrow pulses. For every capture, note the machine state, wire identifier, wiring/interface, measurement settings, and output. That context is necessary before mapping a panel signal to a machine event.