Firmware: BlinkyHawk_RA4M1 · config v7 · board rev V3
End-User Documentation

Blinky Hawk Firmware Manual

How the open-lead detector firmware works — and how to reconfigure a shipped unit over USB serial without touching the code.

The Blinky Hawk continuously answers one question: are my leads actually connected to anything? It flashes and beeps for continuity, warns on live voltage, and every behavioral knob — thresholds, beeper, timings — is stored in on-chip EEPROM and adjustable with plain-text serial commands.

This manual describes a hardware revision 3 board, which is what every current unit is. Revision 2 differs in two visible ways — it has DIP switches, and its buzzer is wired differently — and exactly one V2 unit exists. If you have it, read the appendix; everything else here applies to both.

1 · Overview

Three states, always live

The firmware loops continuously and classifies the test leads into one of three states:

StateMeaningLEDSpeaker
FLOATING (open) The leads are not connected to anything (or to a resistance above the active threshold). Dim blue flash, max 1 Hz Silent
CLOSED (continuity) The leads see a low resistance path. Green flash, max 2 Hz Beep on contact, then a repeat beep every second while held (configurable)
VOLTAGE An external voltage is present across the leads. The open/closed test is bypassed for safety. Red flash, max 2 Hz Double beep on detection (configurable)

While charging over USB the normal alerts are replaced by a slow dim red blink (green once the battery reads full), and at power-on the LED blinks green 1–4 times to show the battery level in quarters.

2 · Detection

How detection works

The analog front end measures a pseudo-differential voltage: the positive sense input is sampled by the RA4M1's 14-bit ADC and compared against a reference. (By default the negative side is a fixed 1.25 V pseudo-reference — see NEGFIX/NEGV — rather than a live second ADC read.) At rest the differential sits near 0 V, so everything works on the magnitude of the deviation from zero.

Each pass of the main loop runs this sequence:

  1. Rest. The bridge MOSFET is held ON (resting state) and the differential is read.
  2. Voltage check. If any single reading deviates more than VOLTFAST × REFBAND from REFCENTER, voltage is declared immediately. Otherwise VOLTAVG readings are averaged and compared against the REFBAND window. Voltage present → state = VOLTAGE, and the MOSFET test is skipped entirely.
  3. Open/closed test. The MOSFET switches OFF and the firmware derives an open/closed metric from the front end (the exact method is selectable — see below), then the MOSFET returns ON. If the metric exceeds the active threshold (one of four stored values — next section) the leads are FLOATING; otherwise they are CLOSED. The test can be required to agree TESTAGREE times in a row before it counts.
  4. Debounce. A newly detected state must repeat for STABLECOUNT consecutive passes before the LED/speaker switch to it, so a single noisy reading can't make the alerts stutter.

Detection methods

When the MOSFET switches off, the positive sense node is briefly pulled away from its resting point and then recovers back toward zero differential. How fast it recovers depends on the impedance across the leads — a dead short snaps back quickly, an open lead drifts back slowly. The DETMETHOD key selects how that recovery is turned into a single number to compare against the threshold. In every method a larger metric means more open, so the threshold table and the comparison work the same way for all three:

DETMETHODMetricThreshold unitsHow it works
0 — single|differential|volts The original method: take one differential reading SETTLEPREUS µs after the MOSFET switches off, and threshold its magnitude.
1 — time-to-returnrecovery timemilliseconds Sample the recovery and measure how long the differential takes to fall back within DETBAND of the resting center. Longer = more open. Naturally tolerant of unit-to-unit gain differences, since it measures a time constant rather than an amplitude.
2 — areatail integralvolt·milliseconds Integrate the magnitude of the recovery from DETAREAUS µs to DETWINUS µs. Larger area = more open. The tail window skips the large initial dip (which is nearly identical for every lead condition).

The threshold units change with the method. Because THRESH00…THRESH11 are compared directly against the metric, switching DETMETHOD changes what those four numbers mean (volts, milliseconds, or volt·milliseconds). After changing the method you must re-tune the threshold values for the new units, then !SAVE. The unit ships on method 1 (time-to-return), so its thresholds are in milliseconds.

Everything in CODE-LIKE type above is an EEPROM configuration key. The full reference, including defaults and allowed ranges, is in section 7.

3 · Indicators

LED & speaker behavior

LED states

PatternMeaning
Dim blue flash (1 Hz max)Leads floating / open.
Green flash (2 Hz max)Continuity (closed).
Red flash (2 Hz max)Voltage present — detection bypassed.
Slow dim-red blink (25% duty)Charging over USB; normal alerts suppressed. !ALERTS,1 re-enables them for the session, but using the detector on USB power is not recommended: supply noise causes false alerts, and the cable can couple the meter to earth ground.
Slow dim-green blink while plugged inCharging and the battery reads full (≥ BATTFULLPCT %).
1–4 green blinks at power-onBattery level: 1 = 0–25%, 2 = 25–50%, 3 = 50–75%, 4 = 75–100%.
Off between flashesNormal — every alert is a rate-limited flash, not a steady light, to save power.

Speaker

4 · Threshold Select

Threshold selection

The unit stores four open/closed thresholds and uses one of them at a time. Which one is active is set by THRESHSEL, an ordinary configuration key:

THRESHSELPositionConfig keyFactory defaultSensitivity
000THRESH000.15 VMost sensitive — triggers on very high resistances.
101THRESH010.54 V 
210THRESH100.45 VThe factory setting.
311THRESH110.62 VLeast sensitive — only firmer connections read as closed.

Selection takes effect on the very next detection pass — there is no reboot and no !SAVE needed to try one out. Over serial the change is announced as $DIP,<position>,<threshold>. Follow with !SAVE to make it the unit's boot setting:

!SET,THRESHSEL,0        // switch to the most sensitive slot
$CFG,THRESHSEL,0
$DIP,0,0.1500
!SAVE
$OK,save

Why the odd position names? The four slots are called 00/01/10/11 because on the revision 2 board they were chosen with a pair of DIP switches, and the names carried over into the key names, the host tooling, and the $DIP message. On a V3 board they are simply slots 0–3.

What each slot means is re-programmable. The four values are just EEPROM entries: !SET,THRESH00,0.02 followed by !SAVE permanently changes what slot 00 means on that unit. This lets one firmware build ship with each unit's sensitivity map tuned to its application.

5 · Low Power

The low-power sleep mode

Running flat out, Blinky Hawk draws about 11 mA. Asleep it draws about 2 mA — and because it can still detect while asleep, sleeping is the normal operating state rather than a standby mode. The unit spends almost all of its life there and wakes fully only when it finds something.

What "asleep" actually does

After SLEEPSEC seconds in which the leads have read nothing but OPEN, the firmware parks every load it can switch — the LED rail, the speaker, the battery-sense divider, and optionally the bridge MOSFET — and puts the RA4M1 into Software Standby: CPU and peripheral clocks stopped, RAM retained. A real-time-clock interrupt wakes it every SLEEPTICKMS. Every SLEEPTICKS wakes it runs one cheap probe, and goes straight back to sleep unless the probe finds continuity or voltage — in which case the unit returns to full-rate operation and alerts normally.

Worst-case detection latency is therefore SLEEPTICKMS × SLEEPTICKS.

Wake period: SLEEPTICKMS

The wake period is produced by the RTC's periodic interrupt, which only offers a fixed ladder of rates. Whatever you set is snapped to the nearest available rung and the snapped value is written back, so !CFG always reports the rate actually in force:

2000100050025012563311684 ms

The rungs below 125 ms are rounded: 63 is really 62.5 ms (1/16 s) and 4 is really 3.90625 ms (1/256 s). Only the reported latency arithmetic uses the rounded number; the interrupt itself runs at the exact rate.

Faster is not automatically better. Sleep current is dominated by how often the unit probes, not by the standby floor — halving SLEEPTICKMS roughly doubles the average draw unless you raise SLEEPTICKS to keep the probe rate constant. Below roughly 30 ms the probe no longer fits inside the tick, the unit stops idling between wakes, and the draw climbs back toward the 11 mA awake figure. The bottom rungs exist for measuring that knee, not for shipping.

As shipped: SLEEPTICKMS 63 and SLEEPSEC 1 — the unit sleeps a second after the leads go open and checks them about sixteen times a second, for roughly 2 mA average. These are the factory defaults, so !DEFAULTS restores them rather than undoing them.

Wake thresholds

A probe taken out of standby measures a few percent high — the analog path has not fully settled and the rails have just come back up. If a threshold tuned on the bench sits below the sleeping unit's closed-lead reading, continuity will silently fail to wake the unit. The SLEEPTHR00…SLEEPTHR11 keys give each slot its own wake threshold for exactly this case; 0 means "use the ordinary THRESH value for that slot", which is the default.

Commands

CommandWhat it does
!SLEEP Arm the timeout to fire as soon as sleeping is allowed, instead of waiting out SLEEPSEC. Issue it over USB, then unplug — the unit sleeps the moment it is idle and off USB. !SLEEP,0 cancels. Replies $OK,sleep,armed.
!SLEEPTEST Run one sleeping-mode probe right now, awake and on USB, and report exactly what it decided — state, metric, the wake threshold used, the awake threshold, resting differential, return time, and area. The probe normally runs unplugged and silent, so this is the only way to see its numbers directly.
!SLEEPLOG Dump the probe history recorded while the unit was asleep (a 64-entry ring, oldest first) as $SLOG rows. !SLEEPLOG,0 clears it.
!FLOOR,<0–3> Park the board in one fixed state so a series ammeter reads a stable current: 1 = parked with the bridge resting, 2 = parked with the bridge off (the delta against 1 is the bridge's own draw), 3 = parked but idling instead of in standby (the delta against 1 is what standby buys). !FLOOR,0 exits.

!SLEEPLOG is the answer to "it won't wake off USB". The sleeping probe runs with USB unplugged and so cannot print — the unit behaves differently precisely when you cannot watch it. Every probe therefore records its decision to RAM. Unplug, exercise the leads, plug back in, and !SLEEPLOG shows what it actually measured. Rows are marked SLEEP or AWAKE, and comparing the two is the point: the ground reference — and therefore the metric — is not the same on battery as it is on the bench. Tune wake thresholds against the SLEEP rows, not against USB readings.

6 · Serial Interface

Talking to the unit

Connect over USB and open the port at 115200 baud. Any serial terminal works (Arduino Serial Monitor, PuTTY, a Python script). The protocol is line-based text:

Configuration commands

CommandWhat it doesReply
!SET,<key>,<value> Set a configuration value in RAM. Takes effect immediately; values outside the allowed range are clamped. Not yet permanent — follow with !SAVE. $CFG,<key>,<value> (the value actually stored)
!GET,<key>Report one configuration value. $CFG,<key>,<value>
!CFGDump every configuration key. One $CFG row per key, then $CFGEND
!SAVEWrite the RAM configuration to EEPROM — this is what makes changes survive a power cycle.$OK,save
!LOADDiscard unsaved RAM changes and reload from EEPROM. $OK,load
!DEFAULTSLoad factory defaults into RAM (EEPROM untouched until you !SAVE).$OK,defaults
!SNReport the unit's serial number. $SN,<value> (empty if unassigned)
!SN,<value>Write the serial number. Persists to its own EEPROM block immediately (no !SAVE needed). Max 15 characters, no commas.$SN,<value> then $OK,sn

Unit serial number

Each unit can carry a serial number — a short identity string (up to 15 characters) written once, usually at first bring-up, and read back on every boot. It is stored in its own EEPROM block, separate from the configuration, so it survives !DEFAULTS, a !SAVE of new settings, and even a firmware update that changes the config layout. Assign one with !SN,<value>; read it with a bare !SN. The current serial number is also reported at the end of every $STATUS line as sn=<value> (empty when unassigned).

The configuration GUI uses this. When you save a unit's configuration, the host GUI records that unit's full config — keyed by serial number — into a master CSV, giving you an as-shipped record of every unit. If a unit has no serial number yet, the GUI prompts you to assign one.

Status & diagnostic commands

CommandWhat it does
!STATUS or !?Print the $STATUS summary line (mode, DIP position, active threshold, detection method, live metric, charge/battery state, unsaved-changes flag, serial number…).
!ALERTS[,0|1]Re-enable the normal alerts while charging (1) or restore the charging blink (0). Bare = toggle. Auto-clears on unplug.
!DIAG[,0|1]Enter/exit diagnostic mode (bare = toggle). See section 9.
!STREAM[,0|1]Continuous raw ADC streaming on/off (diagnostic mode only).
!RATE,<ms>Streaming interval in milliseconds.
!VMODE,<0|1|2>Voltage detection override: 0 = auto, 1 = force "voltage present", 2 = disable voltage detection.
!MOSFET,<-1|0|1>MOSFET override: −1 = automatic (normal detection), 0 = hold off, 1 = hold on. Diagnostic mode only.
!CAP[,<ms>]High-speed ADC capture across a MOSFET toggle; dumps $CAPSTART/$CAP/$CAPEND rows for plotting transients.

Low-power commands

Described in full in section 5.

CommandWhat it does
!SLEEP / !SLEEP,0Arm / cancel "sleep as soon as allowed". Arm over USB, then unplug.
!SLEEPTESTRun one sleeping-mode probe now and print what it decided ($SLEEPTEST).
!SLEEPLOG / !SLEEPLOG,0Dump / clear the probe history recorded while asleep.
!FLOOR,<0–3>Park the board in a fixed state for a series-ammeter current measurement.

Data lines out

LineMeaning
$STATUS,…Key=value status summary (sent after most commands).
$CFG,<key>,<value>One configuration value.
$CFGENDEnd of a !CFG dump.
$SN,<value>The unit serial number (empty if unassigned).
$OK,<what> / $ERR,<what>,<detail>Command acknowledged / failed.
$DIP,<pos>,<threshV>The active threshold slot changed — new position (0–3) and the threshold now in force. Emitted in response to !SET,THRESHSEL (and, on a V2 board, when a DIP switch is flipped). The name is historical; host tooling keys on it.
$SLEEPTEST,…Result of !SLEEPTEST: state, metric, wake threshold, awake threshold, resting differential, return time, area, method.
$SLOGSTART,… / $SLOG,… / $SLOGENDSleep-probe log dump. Each $SLOG row is index, SLEEP/AWAKE, state, metric, threshold, return time, resting differential.
$DIAG,<ms>,<rawPos>,<rawNeg>,<posV>,<negV>,<diffV>One streamed raw sample.
$CAPSTART… / $CAP… / $CAPENDTransient-capture dump (raw counts; header carries full-scale and Vref for conversion).
7 · Configuration Reference

Every configuration key

All keys are set with !SET,<key>,<value> and persisted with !SAVE. Boolean keys take 0 or 1. Out-of-range values are clamped to the range shown and the clamped value is echoed back.

Board

KeyTypeDefaultRangeWhat it controls
HWREV2/332 … 3Which PCB this module is plugged into. This is a statement of fact about the hardware, not a preference — it decides whether D8 is a buzzer leg (V3) or a DIP-switch input (V2). It survives !DEFAULTS, exactly like the serial number, so a factory reset can never hand D8 to the buzzer on a V2 board. Change it only if a board is genuinely rebuilt. See the appendix.
SPKDIFFbool10/1V3 only: drive the piezo differentially (anti-phase across D8/D9) for roughly +6 dB over single-ended drive. 0 parks D8 low and drives D9 alone. Ignored on V2, whose buzzer is single-ended by construction.

Detection

KeyTypeDefaultRangeWhat it controls
REFCENTERvolts0.018−1 … 1Resting differential center. Voltage detection measures deviation from this point.
REFBANDvolts0.0250.001 … 1Half-width of the "no voltage present" window around REFCENTER.
THRESHSEL0–330 … 3Which threshold slot is active: 0 = THRESH00, 1 = THRESH01, 2 = THRESH10, 3 = THRESH11. Takes effect on the next detection pass. Ignored on a V2 board, where the DIP switches decide.
THRESH00units*0.150.001 … 3.3Open/closed threshold for slot 00 (THRESHSEL 0) — the most sensitive setting.
THRESH01units*0.540.001 … 3.3Threshold for slot 01 (THRESHSEL 1).
THRESH10units*0.450.001 … 3.3Threshold for slot 10 (THRESHSEL 2) — the factory setting.
THRESH11units*1.000.001 … 3.3Threshold for slot 11 (THRESHSEL 3) — the least sensitive setting.
DETMETHOD0/1/210 … 2Detection method: 0 = single reading (volts), 1 = time-to-return (ms), 2 = tail area (V·ms). See section 2. Changing this changes the units of the THRESH keys.
DETBANDvolts0.050.005 … 1Method 1 only: the differential is "returned" once it comes back within this band of the resting center.
DETWINUSµs1500200 … 5000Methods 1 & 2: maximum recovery-sampling window. Also the timeout — if the differential never returns, the metric maxes out (reads as fully open).
DETAREAUSµs4000 … 5000Method 2 only: where the area integration starts, measured from the MOSFET-off instant. Skips the common initial dip so only the discriminating tail is integrated.
VOLTFASTmultiplier5.01 … 50A single reading beyond VOLTFAST×REFBAND declares voltage instantly (no averaging).
VOLTAVGcount101 … 50Readings averaged for the normal voltage-present decision.
TESTAGREEcount11 … 10Consecutive matching MOSFET tests required before a result counts.
STABLECOUNTcount21 … 10Detection passes a new state must repeat before the alerts switch (display debounce).
SETTLEPREUSµs3000 … 5000Settle time between MOSFET-off and the test reading (DETMETHOD 0 only; methods 1 & 2 sample from the toggle instant).
SETTLEPOSTMSms30 … 50Idle after the test reading before the MOSFET returns on.
NEGFIXbool10/11 = use a fixed pseudo-reference (NEGV) for the negative side; 0 = read the negative sense pin live.
NEGVvolts1.250 … 3.3The fixed pseudo-reference voltage used when NEGFIX is 1.

* THRESH units follow DETMETHOD: volts when method 0, milliseconds when method 1, volt·milliseconds when method 2. The unit ships on method 1, so THRESH11's 1.00 default is 1.00 ms. Slots 00–10 still carry their old method-0 volt figures and have not been re-characterized for method 1 — only slot 11, the factory selection, is a bench-tuned value. Re-tune a slot before relying on it.

Alerts

KeyTypeDefaultRangeWhat it controls
LEDbool10/1Master enable for the detection LED alerts (charging/battery indications still show).
BEEPbool10/1Master enable for the speaker. !SET,BEEP,0 + !SAVE = permanently silent unit.
BOOTMUTEbool10/1Enable the "leads shorted at boot mutes audio for the session" feature.
PASSIVEbool10/11 = passive buzzer driven with a tone at the pitch below; 0 = active buzzer (fixed tone, pin simply switched on/off).
CONTFREQHz4000100 … 10000Continuity beep pitch (passive buzzer only). The buzzer is a resonator and is only usefully loud near 4 kHz — moving far from it mostly just makes the alert quieter.
VOLTFREQHz4000100 … 10000Voltage beep pitch (passive buzzer only). Same 4 kHz as CONTFREQ — the two alerts differ by pulse count, not pitch.
CONTPULSEScount11 … 5Pulses per continuity beep.
VOLTPULSEScount21 … 5Pulses per voltage beep (2 = the signature double-beep).
CONTREPbool10/1Keep re-beeping while continuity holds.
VOLTREPbool00/1Keep re-beeping while voltage persists.
CONTREPMSms1000100 … 60000Repeat period for the continuity beep.
VOLTREPMSms1000100 … 60000Repeat period for the voltage beep (when VOLTREP=1).
BEEPMINms25050 … 10000Minimum gap between beep sequences — the anti-machine-gun rate cap.

Beep pulse shape

These set the length of the individual pulses within a beep, as distinct from CONTREPMS/VOLTREPMS (how often a beep repeats) and CONTPULSES/VOLTPULSES (how many pulses each beep contains). Shorter on-times make a tighter, clickier alert; longer ones make it more insistent.

KeyTypeDefaultRangeWhat it controls
CONTONMSms1001 … 2000Continuity pulse on-time at first contact.
CONTHOLDMSms1001 … 2000Continuity pulse on-time for the ongoing re-beep while the connection is held. Separate from CONTONMS so the first contact can be a short click and the reminder a longer tone (or the reverse).
CONTOFFMSms101 … 2000Gap between pulses within a multi-pulse continuity beep.
VOLTONMSms201 … 2000Voltage pulse on-time.
VOLTOFFMSms101 … 2000Gap between pulses within the voltage beep — this is the gap that separates the VOLTPULSES pulses into an audibly distinct burst.

Alert LED

Each of the three detection states has its own brightness, flash length, and rate cap. The hue is fixed in firmware — blue, green and red are the meanings — but every other aspect is configurable, including switching a state's indication off entirely by setting its brightness to 0.

KeyTypeDefaultRangeWhat it controls
LEDFLOATBR0–255200 … 255Floating (blue) brightness. Deliberately dim — it is the state the unit is in most of the time. 0 = leave this state dark.
LEDFLOATMSms501 … 10000Floating flash on-time.
LEDFLOATPERms10001 … 60000Floating: minimum gap between flash starts — i.e. a 1 Hz rate cap.
LEDCLOSEDBR0–255640 … 255Continuity (green) brightness. 0 = this state dark.
LEDCLOSEDMSms2001 … 10000Continuity flash on-time.
LEDCLOSEDPERms5001 … 60000Continuity rate cap (2 Hz by default).
LEDVOLTBR0–2552000 … 255Voltage (red) brightness. 0 = this state dark.
LEDVOLTMSms2001 … 10000Voltage flash on-time.
LEDVOLTPERms5001 … 60000Voltage rate cap (2 Hz by default).

Brightness and duty cycle are battery. The LED is one of the larger switchable loads on the board. Raising LEDFLOATBR or lengthening LEDFLOATMS costs runtime continuously, because floating is the state the unit sits in almost all the time — the other two only fire when you have found something.

Low power

Behavior is described in section 5.

KeyTypeDefaultRangeWhat it controls
SLEEPSECseconds10 … 65535Open-lead idle time before the unit sleeps. 0 disables sleeping entirely. Anything other than an open lead restarts the countdown, as does being on USB or in diagnostic mode.
SLEEPTICKMSms634 … 2000Base wake period. Snapped to the nearest rate the RTC can produce (2000/1000/500/250/125/63/31/16/8/4) and the snapped value is written back.
SLEEPTICKScount11 … 255Probe every N wake ticks. Worst-case detection latency is SLEEPTICKMS × this. Raise it alongside a faster tick to hold the probe rate — and the current — constant.
SLEEPAVGcount31 … 50Readings per sleeping voltage check (against VOLTAVG when awake). Any one reading over the instant-bypass band wakes the unit; fewer reads = cheaper and quieter.
SLEEPHBticks320 … 255Heartbeat flash every N wake ticks. Counts ticks, not seconds — speed up SLEEPTICKMS and the heartbeat speeds up with it, so rescale this to match. 0 = no heartbeat.
SLEEPPARKbool00/11 = park the bridge MOSFET OFF while asleep, saving its leg of the current; 0 = leave it in the resting state it uses when awake.
SLEEPTHR00units*00 … 3.3Wake threshold for slot 00. 0 = use THRESH00.
SLEEPTHR01units*00 … 3.3Wake threshold for slot 01. 0 = use THRESH01.
SLEEPTHR10units*00 … 3.3Wake threshold for slot 10. 0 = use THRESH10.
SLEEPTHR11units*1.20 … 3.3Wake threshold for slot 11. 0 = use THRESH11.

Power & battery

KeyTypeDefaultRangeWhat it controls
CHGTHRESHvolts2.00.5 … 3.3VBUS-sense (VBUS/2) level above which the unit considers itself USB-powered / charging.
BATTEMPTYvolts3.702.5 … 4.0Battery voltage mapped to 0%. Set above the cell's electrical floor on purpose: below roughly 3.6 V the analog baseline drifts enough that lead movement alone can trip the voltage detector, so the gauge is calibrated to read empty while the unit is still trustworthy. Lowering this to chase runtime buys false alerts.
BATTFULLvolts4.203.0 … 4.5Battery voltage mapped to 100%.
BATTFULLPCT%9050 … 100Charge percentage at/above which the charging blink turns green.

Miscellaneous

KeyTypeDefaultRangeWhat it controls
LOOPMSms501 … 1000Main-loop pacing. The CPU sleeps (WFI) between passes — larger = lower power, slower response.
8 · Persistence

How EEPROM storage works

9 · Diagnostics

Diagnostic mode

!DIAG,1 switches the unit into diagnostic mode, intended for bench work and for host software (e.g. the Python configuration GUI). Detection keeps running (so the LED stays meaningful) unless you take manual control:

!DIAG,0 exits and clears the streaming/MOSFET overrides.

10 · Recipes

Common configuration recipes

Permanently disable the beeper

!SET,BEEP,0
$CFG,BEEP,0
!SAVE
$OK,save

Make threshold slot 00 trigger on very high resistances

!SET,THRESH00,0.02      // smaller threshold = more sensitive
$CFG,THRESH00,0.0200
!SET,THRESHSEL,0        // and make that slot the active one
$CFG,THRESHSEL,0
$DIP,0,0.0200
!SAVE
$OK,save

Shift the resting center after a hardware change

!SET,REFCENTER,-0.005
$CFG,REFCENTER,-0.0050
!SET,REFBAND,0.03
$CFG,REFBAND,0.0300
!SAVE
$OK,save

Quieter, slower continuity reminder

!SET,CONTREPMS,5000     // remind every 5 s instead of every 1 s
!SET,CONTHOLDMS,20      // and shorten the reminder pulse
!SAVE

Detuning CONTFREQ away from 4 kHz also makes it quieter, but it fights the buzzer's resonance rather than working with it — shortening the pulse or slowing the repeat gives a cleaner result.

Check what a unit is currently configured to

!CFG
$CFG,REFCENTER,-0.0100
$CFG,REFBAND,0.0250
… (one row per key) …
$CFGEND

Undo experiments you haven't saved

!LOAD
$OK,load            // RAM restored to the last-saved EEPROM state

Switch to the time-to-return detection method

!SET,DETMETHOD,1        // metric is now recovery time in ms
$CFG,DETMETHOD,1
!SET,THRESH11,0.9       // re-tune the active slot in the NEW units (ms)
$CFG,THRESH11,0.9000
!SAVE
$OK,save

Set up the shipping low-power configuration

!SET,SLEEPSEC,1         // sleep a second after the leads go open
$CFG,SLEEPSEC,1
!SET,SLEEPTICKMS,63     // wake ~16x/sec (snaps to the 1/16 s RTC rung)
$CFG,SLEEPTICKMS,63
!SET,SLEEPTICKS,1       // probe on every wake
!SET,SLEEPHB,0          // no heartbeat flash (it counts TICKS, not seconds)
!SAVE
$OK,save

Find out why a sleeping unit won't wake on continuity

!SLEEPTEST              // leads shorted: what does the sleeping probe see?
$SLEEPTEST,CLOSED,metric=0.3820,thr=0.4500,awakethr=0.4500,…
// If that says CLOSED but a real sleeping unit stays asleep, the
// difference is the battery ground reference, not the probe logic.
// Unplug, exercise the leads, plug back in, and look at the real thing:
!SLEEPLOG
$SLOGSTART,64,412,method=0
$SLOG,0,SLEEP,FLOAT,0.5100,0.4500,…
$SLOG,1,AWAKE,CLOSED,0.3800,0.4500,…
…
$SLOGEND
// SLEEP rows reading high against thr = raise the wake threshold for
// that slot, leaving the awake threshold alone:
!SET,SLEEPTHR10,0.55
!SAVE

Assign a serial number to a new unit

!SN                     // check first — is one already set?
$SN,                    // empty = unassigned
!SN,BH-2026-001
$SN,BH-2026-001
$OK,sn                 // written to EEPROM immediately; no !SAVE needed
11 · Hardware Map

Fixed (compile-time) hardware map

These are properties of the Blinky Hawk PCB and are not runtime-configurable — changing them requires editing and re-flashing the firmware (BlinkyHawk_RA4M1.ino).

FunctionPin / valueNotes
MCUSeeed XIAO RA4M1Renesas RA4M1, 14-bit ADC, 3.3 V reference.
Sense positiveA2Pseudo-differential positive input.
Sense negativeA1Not connected on V3 — leave NEGFIX=1. Setting NEGFIX=0 on a V3 board reads a floating pin; the firmware allows it for bench work but warns. On V2 it is a real input.
Bridge MOSFET gateD7HIGH = resting/bridge on.
Speaker, "hot" legD9Passive or active buzzer (PASSIVE key).
Speaker, anti-phase legD8V3: the piezo sits across D8/D9 and is driven differentially (SPKDIFF). V2: this pin is a DIP-switch input instead — see the appendix.
D10V3: no connection, parked as an output low. V2: DIP-switch second digit.
Status LEDLED1 on the PCB (SK6812, data pin 6)Colors are compile-time; brightness, flash length, and rate caps are configurable per state. On V3, LED1 is wired straight to the battery rail and cannot be power-gated, so its quiescent draw is a hardware floor rather than something the firmware can park.
USB / charge senseA3Reads VBUS/2 through a divider.
Battery senseBAT_DET / BAT_READ_ENOnboard Vbatt/2 divider, gated by the enable pin.
SerialUSB-CDC, 115200 baudLine-based text protocol (section 6).

Also compile-time: the LED hues, the charging-blink cadence, the sleep heartbeat's flash length and brightness, the 30-second post-boot grace period before the unit may sleep, and the transient-capture buffer size. (LED brightness/timing and beep pulse shaping are configurable — see section 7.)

12 · Appendix

Hardware revision 2

One revision 2 unit exists. If you are not holding it, skip this appendix — everything else in this manual describes the V3 board that all current units use. The firmware supports both from a single build, switched by the HWREV configuration key.

What is different

 Revision 2Revision 3 (current)
Threshold selection A 4-way DIP switch on the board, read live — flip it and the next detection pass uses the new threshold. No USB needed. The THRESHSEL configuration key. No switch on the board.
Buzzer Single-ended, driven from D9 alone. SPKDIFF does nothing. Piezo across D8/D9, driven anti-phase for roughly +6 dB (SPKDIFF).
D8 / D10 DIP-switch inputs, with pull-ups. D8 is the buzzer's second leg; D10 is unused.
A1 (sense negative) A real input — NEGFIX=0 works. No connection. Leave NEGFIX=1.

Reading the DIP switches

Two of the four switch positions (on pins D8 and D10) select which stored threshold is active. Each pin has a pull-up and the switch shorts it to ground, so a switch that is ON reads 0 and one that is OFF reads 1. The position code is the two pin readings, first digit = D8, second digit = D10 — which is where the THRESH00…THRESH11 key names come from:

PositionD8 switchD10 switchConfig keyFactory default
00ONONTHRESH000.15 V
01ONOFFTHRESH010.54 V
10OFFONTHRESH100.45 V (factory-set position)
11OFFOFFTHRESH110.62 V

The remaining two switch positions are wired into the analog bridge rather than to the microcontroller: they bypass resistors to set the permanent series resistance. The pairs are silkscreened on the PCB and are moved together — the switches the firmware reads tell it which resistance the other pair just selected.

HWREV must stay at 2 on this board, and it does so on its own. It survives !DEFAULTS, and any unit whose stored configuration predates the V3 firmware is pinned to HWREV 2 automatically when that configuration is migrated forward. You should never need to set it. If it were set to 3 on a V2 board, the firmware would drive D8 as a push-pull buzzer output into whatever the DIP switch has it connected to, and threshold selection would stop responding to the switches.

Everything else in this manual applies unchanged — detection methods, the low-power sleep mode, alerts, the serial protocol, and every configuration key not listed above. THRESHSEL and SPKDIFF are simply ignored.