20 KiB
Electrical tests
These procedures verify the Phase 7A OLED and buttons, MAX3243 breakout, UART1 data path, hardware flow control, and session broker. They are manual tests: the firmware never starts one automatically.
Safety: With power removed, install only the wiring required by the selected test. DE-9 pins 3 (
TX), 4 (DTR), and 7 (RTS) are driven outputs. Never connect one of these outputs to another driven output. Keep temporary Dupont wiring short and secure. Power the OLED only from 3.3 V because module-mounted I²C pull-ups may connect SDA and SCL to the OLEDVCCrail.
Phase 7 OLED and button bring-up
Use the exact OLED and button connections in Hardware wiring. Display diagnostics initially operate I²C at 100 kHz and probe the standard 7-bit 0x3c and 0x3d addresses. The connected test module acknowledges at 0x3c, whose 8-bit write/read forms are 0x78 and 0x79. A missing or unresponsive display is nonfatal: diagnostics should report it without disrupting UART0 or the serial services.
1. Power-off wiring checks
Disconnect both USB connectors and every other power source before checking or changing wiring.
- Confirm OLED
VCCgoes only to3V3, OLEDGNDgoes toGND, SDA goes to GPIO11, and SCL goes to GPIO12. - Check for an unintended short between
3V3andGND, and verify ground continuity between the OLED and ESP32 board. - Determine whether the OLED module has SDA/SCL pull-ups and verify that any module-mounted or external pull-ups terminate at 3.3 V, never 5 V. Add suitable external pull-ups to
3V3only if the module does not provide them; account for parallel resistance if more than one set is fitted. - Confirm each button is wired between its input and
GND: previous/back GPIO10, select/confirm GPIO13, and next GPIO14. With a meter, each button should be open when released and near zero ohms toGNDwhen pressed. - Check that no button shorts two GPIOs together and that SDA and SCL are not swapped or shorted.
2. Powered idle checks and address probe
Apply power, but do not initialize the OLED yet.
- Measure OLED
VCCrelative toGND; it should be approximately 3.3 V. - Measure idle SDA on GPIO11 and idle SCL on GPIO12. Both should be near 3.3 V. Power down immediately if either bus line rises toward 5 V; correct the OLED supply or pull-up wiring before continuing.
- Run
debug display statusand record the diagnostic state. - Run
debug display probe. Confirm that it tests only 7-bit0x3cand0x3dat the initial 100 kHz bus rate. The tested module should acknowledge at0x3c(8-bit0x78write /0x79read).
If the expected address does not respond, treat the result as a nonfatal hardware finding. On this dedicated local-UI bus, debug display scan --force may identify an unexpected address before further investigation. Otherwise leave the serial core running, power down, and recheck 3.3 V power, common ground, SDA/SCL order, solder joints, and pull-ups. Do not scan a bus shared with unrelated I²C devices.
3. Initialization and display patterns
Initialize the address observed during the scan. The tested module uses 7-bit 0x3c, equivalently 8-bit 0x78 (write) and 0x79 (read):
debug display init 0x3c
Then run:
debug display pattern clear
debug display pattern fill
debug display pattern checker
debug display pattern grid
debug display pattern corners
Confirm that clear and fill affect the full 128×64 area, checker and grid have regular spacing without shifted or wrapped columns, and all four corner markers are visible in the correct locations. Display diagnostics pause the periodic status UI for 30 seconds so the selected pattern remains observable. Record any unexpected mirroring, rotation, clipping, or column offset for correction.
4. Rendered status/content layout
Run the Phase 7B panel-layout pattern:
debug display pattern layout
Confirm that the status text is entirely in the yellow 128×16 panel (rows 0–15), content text is entirely in the blue 128×48 panel (rows 16–63), and the physical black divider between them remains visible. Record any text crossing the divider, clipping, incorrect panel color, or divider obscuration.
5. Row 15/16 color-boundary test
Clear the display, illuminate row 15, and record its physical color and position:
debug display pattern clear
debug display row 15
Repeat for row 16:
debug display pattern clear
debug display row 16
Verified result: row 15 is the last yellow addressable row and row 16 is the first blue addressable row. The two colored areas are separated by a narrow physical black divider, so later UI rendering must treat the 128×16 yellow and 128×48 blue regions as separate panels rather than one visually continuous canvas. Also test another endpoint row if needed with debug display row <0..63> to confirm row addressing and orientation.
6. Contrast, inversion, and display-off checks
With a visible pattern loaded, exercise the bounded contrast range and confirm that brightness changes without bus errors. On the validated module, the useful visible brightness range begins at 1 and extends through 255:
debug display contrast 0
debug display contrast 64
debug display contrast 128
debug display contrast 255
Then verify inversion toggles all displayed pixels and can be restored:
debug display invert on
debug display invert off
Finally run debug display off and confirm the panel turns off cleanly. Use debug display status, then debug display init 0x3c (or equivalently 0x78 or 0x79) before further display tests.
7. Button checks
With all buttons released, run debug buttons status. Confirm previous/back GPIO10, select/confirm GPIO13, and next GPIO14 report released/high due to their internal pull-ups; each should report pressed/low while held to GND.
Run debug buttons test for the default 10-second interval. During the test, press and release each button separately with a deliberate short press, then repeat with a sustained long press. Confirm that the correct button and short/long classification are reported exactly once per intended action.
Repeat with an explicit duration, for example:
debug buttons test 30
Use the longer run to check:
- Debounce: press with normal switch bounce and make several deliberately quick taps; one physical press must not produce a burst of duplicate press/release or short/long events.
- Long press: hold each button long enough for the diagnostic to classify it as long, then release it; it must not also create an unintended short-press action.
- Stuck button: hold one button before starting the test and keep it held. The input must remain identified as pressed/stuck without blocking checks of the other buttons, and the bounded diagnostic must still exit after the selected duration.
- Recovery: release the held button and confirm
debug buttons statusreturns to released/high without a reboot.
debug buttons test [seconds] accepts 1 through 30 seconds and defaults to 10 seconds when omitted. Record unexpected event duplication, missed transitions, incorrect GPIO mapping, false long presses, or a test that fails to terminate.
8. Read-only status UI (Phase 7C)
After boot, the OLED starts on the OVERVIEW page. A short previous/back press on GPIO10 and a short next press on GPIO14 must wrap through these read-only pages:
- OVERVIEW — serial, broker, USB, HTTPS/WebSocket, SSH, and Wi-Fi summary.
- RS232 MODEM — framing, modem inputs, byte counters, queue depth, drops, and faults.
- BROKER — connected clients, current writer marker, pending output, and drop/event counters.
- NETWORK SERVICES — Wi-Fi state/RSSI/IP/AP state and HTTPS, WebSocket, and SSH service state.
Confirm that each page remains entirely within the blue content panel. The yellow panel must retain the same fixed icon positions while pages change: serial, segmented Wi-Fi strength, USB, WebSocket, SSH, broker clients, and alert. Active icons are solid with a value below; inactive icon slots remain completely blank and omit their value. Confirm that page text uses readable upper/lowercase, separates items and values with colons, and displays the active station SSID or AP SSID with its channel on the Overview and Network pages.
The UI refreshes at 4 Hz maximum and is read-only: select (GPIO13) must not change a service, acquire/release a writer, inject serial data, or expose passwords, credentials, tickets, or key material. With UART0, USB CDC, WebSocket, and SSH active, navigate pages and confirm that the display continues to update without disrupting serial traffic or UART0 recovery.
For the OLED-aging policy, leave all three buttons untouched and verify:
- At five minutes, display contrast drops to
1while the contents remain present. - At ten minutes, the OLED switches off.
- The first debounced press of any button wakes the OLED at contrast
127without changing the current page. - A subsequent previous/next press navigates normally and restarts the inactivity timers.
debug display status may verify an individual transition in a separate timing run. Every display diagnostic counts as activity and holds normal UI rendering for 30 seconds, so do not invoke it between the five- and ten-minute observations of one continuous run. Record a missing, stale, clipped, or implausible status value or incorrect dim/off/wake transition before Phase 7C is marked complete.
9. Local controls (Phase 7D)
From a status page, use a short Select press to open Controls. Previous/next selects an item; Select activates it. The menu includes serial start/stop, Wi-Fi start/stop/reconnect/next-profile, HTTPS start/stop, SSH start/stop, writer revocation, display off, and reboot. WiFi:next profile requests the enabled station profile after the active one in priority order and wraps safely; it must never show or change credentials, Wi-Fi profile configuration, serial framing, TLS/SSH keys, or I²C scan controls.
Stopping a service, Wi-Fi reconnect, Wi-Fi next-profile, writer revocation, and reboot open a confirmation page. Verify that:
- Previous/back cancels the confirmation without changing the selected service or writer.
- A short Select press does not execute the action.
- Only one continuous two-second Select hold executes the action once; releasing it does not repeat the action.
- Any simultaneous button chord is ignored and cannot confirm an action.
- An untouched confirmation expires to the menu after 30 seconds.
- A dimmed/off OLED consumes the first button press for wake only; its later release and hold must not navigate or confirm an action.
For Wi-Fi lifecycle calls, confirm the immediate result says Requested, then use the status pages to observe the asynchronous state change. For WiFi:next profile, configure at least two enabled station profiles, cancel once with Previous/back, then hold Select for two seconds; verify the current station disconnects, the next enabled profile is attempted, and the Overview/Network WiFi:<SSID> Ch:<channel> value (or wifi status) changes. Repeat until the selection wraps to the first profile. HTTPS and SSH starts must fail cleanly when neither station nor AP networking is available. Writer revocation must only release the current writer—never assign a replacement—and the UI must never appear as a broker client. For reboot, observe Restarting..., then verify all normal boot services and UART0 recovery return.
Run these checks with UART0 available. Repeat appropriate stop/revoke cases with USB CDC, WebSocket, and SSH clients connected; verify the intended session/service is interrupted, unrelated recovery paths remain responsive, and no action injects serial data.
10. Phase 7E persistence and fault recovery
First shorten the delays for a bounded aging-policy test:
display status
display set dim-seconds 5
display set off-seconds 10
display save
reboot
After reboot, display status must report the stored 5/10-second values. Verify dim at five seconds, off at ten seconds, and one consumed wake press. Run display load, then test display defaults without saving and confirm 300/600 seconds are restored only in RAM. Run display reset, reboot, and confirm the defaults persisted. Verify invalid combinations such as dim 10 with off 5 are rejected without changing the working values. Set either timeout to 0, save/reboot, and confirm that transition is disabled; finish with display reset.
Exercise the following fault matrix while keeping UART0 available:
| Fault/stress | Procedure | Required result |
|---|---|---|
| OLED absent at boot | Power down, remove the OLED, then boot. | UART0, serial, USB, Wi-Fi, HTTPS/WebSocket, and SSH startup remain independent; no reset or probe loop occurs. |
| Reattach | Power down before reconnecting loose wiring, boot, and press one button. If using a connector explicitly suitable for live removal, avoid shorts and reconnect before pressing. | One bounded reprobe initializes the panel; the wake press does not navigate or execute an action. |
| NACK/timeout | With safe test wiring, interrupt the display during refresh or hold one bus line low briefly, then release it. | One bounded frame fails and marks the OLED unavailable; no watchdog reset, repeated log flood, serial loss, or broker ownership change occurs. A later new press can recover after the bus is healthy. |
| Stuck button | Hold each button continuously for at least ten seconds, then operate each of the other buttons. | The held input is quarantined, the other controls remain usable, and no action repeats. Release and debounce the held input; it must rearm without rebooting. |
| Real chord | Press two healthy buttons together before either is quarantined. | The chord is ignored and cannot confirm an action. |
| Repeated actions | Re-enter Controls and repeat start/stop, reconnect, next-profile, writer-revoke, and display-off requests during transitions. | Each confirmation hold executes once; stale state produces an error rather than the opposite action; queue saturation, if reached, reports an error and leaves the Wi-Fi alert/counter visible. |
For the final concurrency regression, connect USB CDC, one WebSocket terminal, and one SSH terminal while UART1 carries sustained bidirectional traffic. Navigate the UI, run the persistence checks, exercise service stop/start and writer revocation, and inject the display/stuck-button faults above. Confirm UART0 remains responsive, the UI never appears as a broker client or injects serial bytes, writer ownership is always the expected client or none, and serial/broker drop counters do not increase unexpectedly. Record memory, transport counters, wifi counters, and debug display status before and after the run.
Configuration A: data and handshake pairs
Connect the following pairs:
| Driven output | Receiver input | Expected ESP32 logic |
|---|---|---|
DE-9 pin 3, TX |
DE-9 pin 2, RX |
RX == TX |
DE-9 pin 4, DTR |
DE-9 pin 6, DSR |
DSR == DTR |
DE-9 pin 7, RTS |
DE-9 pin 8, CTS |
CTS == RTS |
DE-9 pin 3 TX ─────> pin 2 RX
DE-9 pin 4 DTR ─────> pin 6 DSR
DE-9 pin 7 RTS ─────> pin 8 CTS
Run debug loopback-a. The test cycles all TX/DTR/RTS states and verifies the three receivers and VLD. Driver and receiver inversions cancel, so the resulting ESP32 logic levels must match.
This configuration also supports debug valid-test, debug uart-loopback <baud> [format] [bytes], and debug uart-suite; the UART commands need only the pin 3-to-2 connection.
Configuration B: remaining receivers
Remove every configuration A jumper, then connect:
| Driven output | Receiver input | Expected ESP32 logic |
|---|---|---|
DE-9 pin 3, TX |
DE-9 pin 1, DCD |
DCD == TX |
DE-9 pin 4, DTR |
DE-9 pin 9, RI |
RI == DTR |
DE-9 pin 7, RTS |
DE-9 pin 2, RX |
RX == RTS |
DE-9 pin 3 TX ─────> pin 1 DCD
DE-9 pin 4 DTR ─────> pin 9 RI
DE-9 pin 7 RTS ─────> pin 2 RX
Run debug loopback-b. Configurations A and B together exercise all three drivers and five receivers.
CTS transmit gating
Disconnect all external DE-9 equipment, power down, and remove previous jumpers. Install only:
| Driven output | Receiver input | Purpose |
|---|---|---|
DE-9 pin 3, TX |
DE-9 pin 2, RX |
Return UART1 data for comparison |
DE-9 pin 4, DTR |
DE-9 pin 8, CTS |
Present inactive and active CTS states |
DE-9 pin 3 TX ─────> pin 2 RX
DE-9 pin 4 DTR ─────> pin 8 CTS
Run debug cts-flow-test. At 115200 baud with hardware CTS enabled, the firmware first queues 512 bytes while CTS is inactive and confirms that no data is sent for 250 ms. It then activates CTS and verifies automatic, exact transmission and reception of all bytes.
RTS receive backpressure
Disconnect all external DE-9 equipment, power down, and remove previous jumpers. Install only:
| Driven output | Receiver input | Purpose |
|---|---|---|
DE-9 pin 4, DTR |
DE-9 pin 2, RX |
Carry UART2-generated data to UART1 RX |
DE-9 pin 7, RTS |
DE-9 pin 1, DCD |
Return UART1 RTS to UART2 CTS |
UART2 TX / DE-9 pin 4 DTR ─────> pin 2 RX / UART1 RX
UART1 RTS / DE-9 pin 7 RTS ─────> pin 1 DCD / UART2 CTS
Run debug rts-flow-test. UART2 queues 4096 bytes while UART1 is initially unread. Once UART1 reaches its receive threshold, it deasserts RTS and stops UART2 through CTS. Draining UART1 must reassert RTS and let UART2 finish. UART_BUFFER_FULL is expected; FIFO overflows, framing/parity errors, breaks, or any data mismatch are failures.
Voltage and polarity checks
With no DE-9 loopback jumpers installed, measure pins 3, 4, and 7 relative to DE-9 pin 5 (GND):
debug drivers 0 0 0
Each output should be at a positive RS-232 voltage. Then run:
debug drivers 1 1 1
Each output should be negative. Exact voltages depend on supply, load, meter, and charge-pump behavior; polarity is the important result.
Recommended order
- With no DE-9 jumpers, run
status. - Measure output polarity with
debug drivers 0 0 0anddebug drivers 1 1 1. - Power down, install configuration A, power up, and run
debug loopback-a. - Run
debug valid-testwith configuration A still installed. - Keep only pin 3-to-2 and run
debug uart-loopback 9600 8N1 256, thendebug uart-suite. - Power down, install configuration B, power up, and run
debug loopback-b. - Power down, install CTS wiring, power up, and run
debug cts-flow-test. - Power down, install RTS wiring, power up, and run
debug rts-flow-test.
RTS and CTS remain GPIO signals during static and basic UART tests. Only the flow-control tests assign them to UART peripherals. The firmware shuts down the MAX3243 while changing GPIO-matrix routing and restores outputs to static logic 1 after each test.
Session-broker loopback
This test verifies broker fan-out and writer ownership independently of the diagnostics. Disconnect external peers, power down, remove previous jumpers, and connect only DE-9 pin 3 (TX) to pin 2 (RX). Power up and run:
serial start
broker connect writer
broker connect observer
broker clients
Use the client IDs printed by the device:
broker request-writer <writer-id>
broker send-hex <writer-id> 0055aaff1b5b33316d
broker read <writer-id> 64
broker read <observer-id> 64
Both clients should receive 0055aaff1b5b33316d. A read may return zero if UART1 has not returned the bytes yet; repeat it shortly afterward.
Verify writer exclusion and administrative reassignment:
broker request-writer <observer-id>
broker send-hex <observer-id> dead
broker force-writer <observer-id>
broker send-hex <observer-id> 112233
broker read <writer-id> 64
broker read <observer-id> 64
broker events <writer-id>
broker events <observer-id>
The competing request and its initial send should fail. After reassignment, both clients should receive 112233; events should show denial, revocation, and grant. Clean up:
broker disconnect <observer-id>
broker disconnect <writer-id>
serial stop
Remove the loopback jumper with power off before connecting an external serial device.