Skip to content

Let each of the three emitter banks be switched off individually - #15

Merged
MacNite merged 1 commit into
mainfrom
claude/hivetraffic-mosfet-toggles-4a5yqu
Aug 23, 2026
Merged

MacNite merged 1 commit into
mainfrom
claude/hivetraffic-mosfet-toggles-4a5yqu

Conversation

@MacNite

@MacNite MacNite commented Aug 22, 2026

Copy link
Copy Markdown
Owner

The 2026-08 board puts one IRLB8721 behind each MCP23017, which makes each third of the entrance independently switchable. Measured at 3.3 V:

Banks enabled Gates counted Draw
1 8 ~0.14 A
2 16 ~0.22 A
3 (default) 24 ~0.30 A

Roughly 80 mA per bank on top of a ~60 mA floor — dropping one saves about as much current as a quarter of a night of night mode, except it applies all day. For an entrance narrower than 24 gates, one partly closed for the season, or a supply that will not carry the whole board, this is the coarsest and most effective knob available. It composes with night mode rather than competing with it: a counter can be running one bank and be suspended.

Pairs with MacNite/HiveHub#170, which adds the three checkboxes and writes the mask.

Protocol v5

  • control opcode 0x03 SET_BANKS + a 1-byte enable bitmask (bit 0 = gates 00..07, bit 1 = 10..17, bit 2 = 20..27);
  • the control read-back gains a trailing mask byte — appended, so a client that reads five bytes and stops sees exactly what it always did;
  • the measurement document gains "banks", emitted unconditionally.

Emitting it unconditionally is the point: 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. Same argument as idle_s at v4, at a third of the counter each time.

Additive in both directions, so a v4 parser reads a v5 document correctly. A counter running v4 or earlier has no SET_BANKS; the write is ignored and logged, so the feature degrades to "this counter runs all three banks", never to an error. HiveHub gates the write on fw >= 5 rather than relying on that.

The rules, and why

The mask arithmetic lives in the new include/bank_state.h, free of Arduino and pinned by host tests, because every mistake it can make is silent — a bank that should be on but is off reads as a dead FET, and one that should be off but is on quietly costs 80 mA on a supply sized without it. It follows night mode's fail-open posture:

  • Not persisted. A reset comes back with all three banks counting; HiveHub re-asserts the mask on its next upload cycle. Worst case is one cycle of drawing more current than asked for — never a counter that boots blind on two thirds of its entrance because of a write it received a month ago.
  • A mask of 0 is refused, not applied. The counter keeps whatever it had. Blinding a counter entirely is not a configuration anyone needs — one that should count nothing is unpaired — and accepting it would let one corrupted byte stop counting until someone walks to the hive. Same reasoning as start == end disabling the night window rather than covering the whole day.
  • Bits above bank 3 are ignored, so a future four-FET board's mask cannot conjure a bank whose GPIO does not exist. A mask of only phantom bits is therefore a zero mask, and refused as one.

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 a hive entrance can pull one low. Feeding those readings to the state machine would invent crossings on gates the operator deliberately switched off. The gate state machines are also reset on both edges of a mask change, so a pairing from before a bank went dark cannot combine with a sample from after it came back.

The expander itself is still read and still health-checked — mcps_healthy keeps meaning "MCP23017s answering on the I²C bus" — and num_gates keeps reporting 24, because that describes what is wired. Active gates are popcount(banks) * 8, derived by the consumer, so the meaning of every stored reading stays fixed.

Testing

  • New test/test_bank_state/: default state, one-based bank numbering, the all-off refusal, phantom-bit masking, and that a steady-state re-assert is not a "change" (so a pairing in progress is not torn down every ten minutes).
  • test/test_measurement_json/ updated for v5 — nominal document, the mask on every document, num_gates staying at 24, and the saturated worst case (203 of 240 bytes; the buffer grew from 224).
  • ./Firmware/test/run_tests.sh — all four suites pass.

Firmware bumped to 0.3.0.

The bench console gains 4/5/6 to toggle banks live, named for the schematic's /GPIO4../GPIO6 FET rails (misleading net names — they are physically GPIO19/20/18 — but the labels silkscreened next to the FETs).

🤖 Generated with Claude Code

https://claude.ai/code/session_01TCTPLvKrrm1RmiaVHGxz4D

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
@MacNite
MacNite merged commit 3213338 into main Aug 23, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant