You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Let each of the three emitter banks be switched off individually
The 2026-08 board puts one IRLB8721 behind each MCP23017, which makes each
third of the entrance independently switchable. Measured at 3.3 V, one bank
draws ~0.14 A, two ~0.22 A and three ~0.30 A — roughly 80 mA per bank on top
of a ~60 mA floor — so for an entrance narrower than 24 gates, or a supply
that will not carry the full board, this is the coarsest and most effective
power knob available. It composes with night mode rather than competing with
it.
Protocol v5:
* control opcode 0x03 SET_BANKS + a 1-byte enable bitmask;
* the control read-back gains a trailing mask byte (appended, so a client
that reads five bytes and stops sees what it always did);
* the measurement document gains "banks", emitted unconditionally — a field
that only appeared when interesting would make "all banks on" and "counter
too old to say" the same absence, and a switched-off bank produces exactly
the flat totals a dead FET does.
The mask rules live in the new include/bank_state.h, free of Arduino and
pinned by host tests, because every mistake they can make is silent. They
follow night mode's fail-open posture: never persisted, re-asserted by HiveHub
every cycle, all three banks on after any reset, and an all-off mask refused
rather than applied so one corrupted byte cannot blind a counter until someone
walks to the hive.
Gates on a dark bank are skipped, not read as "clear". An unpowered QRE1113 is
a bare phototransistor under a 100k pull-up and direct sun into a hive entrance
can pull one low, which would invent crossings on gates deliberately switched
off. The expander is still read and health-checked, so mcps_healthy keeps
meaning "MCP23017s answering", and num_gates keeps reporting what is wired.
The IR_DEBUG console gains 4/5/6 to toggle banks on the bench, named for the
schematic's /GPIO4../GPIO6 FET rails.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TCTPLvKrrm1RmiaVHGxz4D
Copy file name to clipboardExpand all lines: Firmware/README.md
+21-2Lines changed: 21 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -61,6 +61,10 @@ The previous 2-FET build split U3's gates across banks 1 and 2 (00..13 / 14..27)
61
61
62
62
Driving the GPIO HIGH turns the bank's emitters on. In the default `LedMode::AUTO` the emitters are **pulsed**: all three banks are lit together only for the settle + MCP-read window of each poll (~1.75 ms at 100 kHz), then switched off until the next poll. This drops the emitter duty cycle from 100% to roughly 35% at the default 5 ms poll interval, cutting average emitter current proportionally, with no change to detection behaviour. The IR_DEBUG console's `1` / `0` / `a` keys force steady-on, blackout and pulsed mode respectively for bench work.
63
63
64
+
Each bank can also be **switched off entirely**, which is a separate control from the LED mode: HiveHub writes an enable bitmask to the control characteristic (`SET_BANKS`, protocol v5) and `include/bank_state.h` decides what is applied. One bank draws ~0.14 A at 3.3 V, two ~0.22 A, three ~0.30 A, so this is the coarsest and most effective power knob on the board — for an entrance narrower than 24 gates, or a supply that will not carry the full one.
65
+
66
+
All three banks are enabled by default and after any reset; the mask is never persisted, and HiveHub re-asserts it every upload cycle. A mask of `0` is refused rather than applied. Gates on a dark bank are **skipped**, not read as "clear": an unpowered QRE1113 is a bare phototransistor under a 100 kΩ pull-up, and direct sun into the entrance can pull one low. The expander itself is still read and health-checked, so `mcps_healthy` keeps its meaning. The IR_DEBUG console's `4` / `5` / `6` keys toggle banks 1/2/3 for bench work.
67
+
64
68
### Counting
65
69
66
70
Each gate is a small state machine:
@@ -180,10 +184,18 @@ Press a single key in the serial monitor:
180
184
|`0`| Force IR LEDs OFF |
181
185
|`a`| IR LEDs AUTO (normal pulsed mode) |
182
186
|`n`| Arm / clear a 60 s night-mode suspension (press again to resume) |
187
+
|`4`| Toggle emitter bank 1 (GATE_00..07) |
188
+
|`5`| Toggle emitter bank 2 (GATE_10..17) |
189
+
|`6`| Toggle emitter bank 3 (GATE_20..27) |
183
190
|`h`| Show the command list |
184
191
185
-
Each reading lists the raw MCP23017 port words plus a per-gate `BLOCK`/`clear`
186
-
line for the inner and outer sensor. The emitters are pulsed on for every read
192
+
The bank keys are `4`/`5`/`6` because the schematic labels those rails `/GPIO4`,
193
+
`/GPIO5` and `/GPIO6` — misleading net names (they are physically GPIO19/20/18)
194
+
but the ones silkscreened next to the FETs.
195
+
196
+
Each reading lists the raw MCP23017 port words, the current bank mask, plus a
197
+
per-gate `BLOCK`/`clear` line for the inner and outer sensor. A gate whose bank
198
+
is switched off prints `<bank disabled>` rather than a beam state. The emitters are pulsed on for every read
187
199
regardless of the LED mode, so the readout is always valid. Wave a finger or a
188
200
bee through a gate and you should see that gate's `inner`/`outer` flip to
189
201
`BLOCK`.
@@ -282,6 +294,13 @@ No ESP32, no MCP23017 and no bee required.
282
294
well-formed documents full of zeros, which is indistinguishable from a spell
283
295
of bad weather until someone reads a week of totals — so none of this is
284
296
something a bench session would catch.
297
+
***`include/bank_state.h`** — the emitter-bank enable mask. Every mistake it
298
+
can make is silent: a bank that should be on but is off produces a
299
+
permanently flat third of the totals, which reads exactly like a dead FET,
300
+
and a bank that should be off but is on quietly costs ~80 mA on a supply
301
+
sized without it. The suite pins the refusal of an all-off mask, the
302
+
one-based bank numbering that `gates::TABLE[].led_bank` depends on, and the
303
+
masking of bits above the last physical bank.
285
304
286
305
Everything hardware-facing stays in `src/main.cpp` and is still verified on the
0 commit comments