# Optional three-character GPIO bench controller

The primary three-module prototype uses **ESP32-C3 + one MCP23017 + BSS138 level shifter**, as described in [ELECTRICAL.md](ELECTRICAL.md). The future compact 2×7 is a separate design and may use different motors, mechanics and electronics.

This alternate is useful if a **classic ESP32-WROOM development board** is already available. It runs one, two or three complete 38-position mechanisms without MCP boards or a level shifter. It requires its own firmware build and wiring. It is not compatible with C3, S3 or WROVER/PSRAM pin assignments, and it cannot operate the full 14-character panel.

## Parts and wiring

Use the ordered unmodified 5 V, five-wire 28BYJ-48 motors with their matching ULN2003 boards. Each character needs its complete 38-leaf mechanism, one 3 × 1 mm magnet, one verified bare A3144 or US5881LUA Hall sensor, four 10 kΩ driver-input pulldowns, one 10 kΩ Hall-output pullup and one 100 nF Hall bypass capacitor. Three characters need 15 resistors and three bypass capacitors.

Use the current mechanical and P2S 0.4 mm print-preparation guide for the three independently supported test modules and their leaves. The current single-material route is black Generic PETG with paint-filled glyph recesses; no AMS is required. Do not substitute the historical two-material PLA plates without reslicing and checking the fit.

| Signal | Character 0 | Character 1 | Character 2 |
| --- | --- | --- | --- |
| ULN IN1 | GPIO16 | GPIO21 | GPIO23 |
| ULN IN2 | GPIO17 | GPIO22 | GPIO27 |
| ULN IN3 | GPIO18 | GPIO25 | GPIO32 |
| ULN IN4 | GPIO19 | GPIO26 | GPIO33 |
| Hall OUT | GPIO34 | GPIO35 | GPIO36 / VP |

Use GPIO numbers, not header positions. Confirm all these pins are actually exposed by the purchased board. The map avoids flash, UART and boot-strapping motor pins. GPIO34, GPIO35 and GPIO36 are input-only and require external pullups. [Espressif ESP32 datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf)

Each ULN IN pin gets **10 kΩ to GND**. Each Hall OUT gets **10 kΩ to ESP 3V3**, never to 5 V in this direct-GPIO build. The Hall VDD still goes to external 5 V. For US5881LUA in the UA package, the datasheet pin order is 1=VDD, 2=GND, 3=OUT; confirm the package diagram and sensor face before wiring. Its open-drain output supports this separate 3.3 V pullup. Test the magnet pole and installed gap before gluing. [Melexis US5881 datasheet](https://www.melexis.com/-/media/files/documents/datasheets/us5881-datasheet-melexis.pdf)

The driver board's motor connector, motor common lead and flyback COM connection must reach the external regulated **5 V** rail. No motor winding connects directly to an ESP pin. Direct 3.3 V ULN drive is conditional on the actual board's input/LED loading and low-current coils: TI specifies an ON-input limit of 2.4 V at 200 mA collector current and VCE=2 V. Verify the delivered driver and winding rather than assuming generic boards have identical circuits. Never use a BSS138 open-drain shifter as a motor-input push-pull buffer. [TI ULN2003A datasheet](https://www.ti.com/lit/ds/symlink/uln2003a.pdf)

## Power

Power the ESP only from a computer USB data cable during commissioning. External motor +5 V must not join ESP VIN/5V or USB power. Connect the grounds. Feed driver/motor and Hall branches from a regulated 5 V supply through covered, fused distribution, with dedicated motor-current returns. A 5 V / 3 A supply is a reasonable starting choice; verify actual simultaneous load and margin. Start with a 1 A motor fuse and a separate 1 A logic/Hall fuse, suitable DC holders, short 22 AWG feeds and a 470–1000 µF capacitor rated at least 10 V at distribution. Do not send motor current through breadboards or thin signal jumpers.

Measure common-to-phase winding resistance, energized current, voltage drop and temperatures. The seller's generic resistance description is not acceptance evidence. A two-phase estimate is `2 × 5 / measured_resistance` amps per motor before driver loss, multiplied by the actual energized count. Fuse or supply changes require measured demand and wire/connector ratings. Keep the external power plug accessible; firmware stop is not an independent hardware power cutoff.

### Optional current-limited lab supply for supervised commissioning

The [Westmont pickup option](../westmont.html) includes an enclosed Korad KD3005D as an optional bench tool. This is a separate, temporary power arrangement, not approval to omit the fuses from the permanent 4 A or 6 A brick harness. Independently verify the lab output at **5.00 V with a hardware current limit no higher than 1.00 A**, following the supplied manual with the load disconnected. Select a current setting below 1 A (for example 0.8 A) to allow tolerance, then verify the actual limit. Lock its settings. All leads, blocks and connections must be rated above that current limit; use short 18 AWG input/bridges and 22 AWG motor branches. Keep exposed conductors insulated and the output cutoff accessible. Confirm actual winding/current behavior one motor at a time; do not raise the limit to hide voltage collapse or a fault.

For this current-limited source, four covered five-port blocks provide a complete separate-power map. Each block is one electrical node; never join positive and ground on the same block. One conductor per port, no loose clips on component pins:

| Block | Connections |
| --- | --- |
| D1, positive input | Supply +; bridge to P1; Hall +5 V backbone; bulk capacitor +; one spare |
| P1, motor positive | Bridge from D1; driver 0 +5 V; driver 1 +5 V; driver 2 +5 V; one spare |
| G1, motor returns | Driver 0 GND; driver 1 GND; driver 2 GND; bridge to G5; one spare |
| G5, common ground | Bridge from G1; supply −; Hall ground backbone; ESP GND; bulk capacitor − |

Keep the controller powered only by its USB data cable. External +5 V must not reach ESP 5V/VIN/USB; the grounds join at G5. The three Hall outputs still pull up to **ESP 3V3**. Keep each 100 nF bypass at its Hall sensor and the polarized 1000 µF / at least 10 V capacitor at distribution. Secure and insulate the Hall/backbone and logic joints; motor current does not pass through the logic board.

Configure with external motor power off. For one sensor use `activeModules=1`. After all three independent sensors and mechanisms pass, explicitly save **`activeModules=3, maxActive=1`** and read the settings back; do not load the default three-module profile, which permits three moving motors. Configuration changes restart homing, so press Stop after configuring, then enable external motor power and use Recover/Home. The scheduler holds the active slot through settling until coils are released. Three characters can therefore update sequentially; this is not a claim of three-motor simultaneous current capability. Stop and disconnect power before moving any sensor or motor connection.

## Build, configure and calibrate

From the project folder, with the existing build environment installed:

```bash
cd firmware
npm run assets
../.venv/bin/pio run -e esp32_wroom_bench
../.venv/bin/pio run -e esp32_wroom_bench -t buildfs
```

This compiles only. It does not flash or move hardware. Flash only an explicitly identified WROOM board with motor power disconnected, using matching application and filesystem images. Its environment is `esp32_wroom_bench`; the primary C3 images must not be flashed to it.

The WROOM build starts with one active module and a separate `bench38` NVS namespace. Read the serial token at 460800 baud, join the setup hotspot and use the same device UI described in [SOFTWARE.md](SOFTWARE.md). After each mechanism passes, expand while keeping its saved calibration:

```bash
python3 scripts/splitflap.py --token-file /path/to/token expand 3 --max-active 1
python3 scripts/splitflap.py --token-file /path/to/token bench ORD
python3 scripts/splitflap.py --token-file /path/to/token calibrate 0 --turns 8
```

The text request is atomic across the active one to three positions. The same fixed-point revolution calibration, Hall limits, acceleration ramp, coil release, stop/recover behavior and latest-pending-target policy apply to both hardware backends. Guided calibration measures one module at a time and never automatically overwrites settings. Repeat for modules 1 and 2, explicitly apply each successful result, adjust alignment offsets and inspect every symbol.

The alternate WROOM cannot expand to 14 electronically. If changing these three test mechanisms to the primary C3/MCP controller, export the WROOM configuration first, retain module IDs 0–2, and copy the first three offsets and revolution counts plus the common Hall reference into the C3 configuration. The controllers use separate NVS namespaces; moving wires does not transfer saved settings. Reuse of these larger mechanisms in the future compact 2×7 is not promised.

Software compilation, native tests and a mocked browser UI are distinct from hardware acceptance. No controller has been flashed or motor run as part of this design update. Check printed fit, Hall polarity/gap, driver input current, coil current, actual loaded speed, supply droop and temperatures before closing the enclosure.
