Files
ESP32_Serial_Swiss_Army_Knife/wiring.md
T

13 KiB

Hardware wiring

This document records hardware-specific pin assignments. Keeping each assignment tied to a named board combination allows additional wiring profiles to be added later without treating one GPIO map as universal.

Profile: ESP32-S3-DevKitC-1 N16R8 with Adafruit MAX3243

This initial profile is for:

The Adafruit board provides three logic-to-RS-232 drivers (TX, RTS, and DTR), five RS-232-to-logic receivers (RX, CTS, DSR, DCD, and RI), valid-signal detection, and shutdown control. It is a level shifter, not a galvanic isolator.

Wiring table

Adafruit breakout pin Direction at ESP32 ESP32-S3 connection DevKit header Purpose
Vin Power 3V3 J1-1 or J1-2 Power the MAX3243 with 3.3 V logic levels
GND Power GND J1-22 Common logic and RS-232 signal ground
TX ESP32 → breakout GPIO17 J1-10 UART1 transmit
RX Breakout → ESP32 GPIO18 J1-11 UART1 receive
RTS ESP32 → breakout GPIO15 J1-8 UART1 hardware receive-flow-control output
CTS Breakout → ESP32 GPIO16 J1-9 UART1 hardware transmit-flow-control input
DTR ESP32 → breakout GPIO7 J1-7 Software-controlled data-terminal-ready output
DSR Breakout → ESP32 GPIO5 J1-5 Data-set-ready input
DCD Breakout → ESP32 GPIO4 J1-4 Carrier/connect-state input
RI Breakout → ESP32 GPIO6 J1-6 Ring-indicator input
VLD Breakout → ESP32 GPIO8 J1-12 Valid RS-232 voltage indication
OFF ESP32 → breakout GPIO9 J1-15 Optional active-low transceiver shutdown

Use the GPIO labels printed on the development board when wiring a compatible clone; its physical header numbering may differ from the official DevKitC-1 documentation.

Wiring diagram

The arrows show signal direction at the breakout's 3.3 V logic header.

ESP32-S3-DevKitC-1 N16R8       Adafruit MAX3243 breakout
────────────────────────       ──────────────────────────
3V3              ────────────> Vin
GND              ────────────> GND

GPIO17 / U1TXD   ────────────> TX
GPIO18 / U1RXD   <──────────── RX

GPIO15 / U1RTS   ────────────> RTS
GPIO16 / U1CTS   <──────────── CTS

GPIO7            ────────────> DTR
GPIO5            <──────────── DSR
GPIO4            <──────────── DCD
GPIO6            <──────────── RI

GPIO8            <──────────── VLD
GPIO9            ────────────> OFF

UART and flow-control pins

UART1 is used for the external RS-232 data path. GPIO17 and GPIO18 are the ESP32-S3's conventional U1TXD and U1RXD pins. GPIO15 and GPIO16 are physically adjacent to them on header J1 and are routed to UART1 RTS and CTS through the ESP32-S3 GPIO matrix.

The GPIO matrix means GPIO15 and GPIO16 can serve UART1 even though their fixed-function labels mention UART0 RTS and CTS. UART0 logging remains on GPIO43 and GPIO44 through the board's USB-to-UART bridge. GPIO19 and GPIO20 remain free for future native USB CDC-ACM support.

RTS/CTS flow control will be configurable. When enabled, the UART peripheral can handle it in hardware so backpressure does not depend on application-task scheduling. When disabled, firmware must place the output signals in compatible idle states.

Modem-control signals

GPIO4 through GPIO7 form a compact group for the remaining modem-control lines:

  • GPIO4 reads DCD.
  • GPIO5 reads DSR.
  • GPIO6 reads RI.
  • GPIO7 drives DTR.

DCD, DSR, and RI are ordinary GPIO inputs rather than hardware-managed UART signals. Firmware will monitor them and make their state available to the serial session broker and user interfaces. DTR is a software-controlled GPIO output.

VLD on GPIO8 reports whether the MAX3243 detects a valid RS-232 voltage on at least one receiver. It is a useful connection hint but does not prove that the cable, signal direction, or serial parameters are correct.

The breakout's OFF pin is connected to the MAX3243 active-low !FORCEOFF input. High or unconnected keeps the transceiver enabled; low forces shutdown. Its onboard pull-up makes it safe to leave unconnected during initial testing. If firmware uses GPIO9 later, it should preferably configure it as an open-drain output that is released to enable the transceiver and driven low to disable it.

Power and cable notes

  • Connect breakout Vin to 3V3, not 5V. ESP32-S3 GPIOs are not 5 V tolerant.
  • The MAX3243 generates the positive and negative RS-232 voltages required on the DE-9 side.
  • The breakout is not isolated: ESP32 ground, breakout ground, USB ground, and DE-9 pin 5 are electrically connected.
  • The breakout is electrically DTE-style: TX, RTS, and DTR drive the DE-9, while RX, CTS, DSR, DCD, and RI receive from it.
  • A straight-through male-to-male gender changer changes connector gender only. Use a straight-through cable for a DCE peer and an appropriate null-modem cable for another DTE peer.

GPIO8 and GPIO9 are not adjacent on the official J1 header. GPIO3 and GPIO46 lie between them and are boot-strapping pins, so follow the printed GPIO labels instead of counting header positions.

Phase 0 loopback tests

The hardware-characterization firmware never starts a test automatically. Wire exactly one configuration below while the board is powered down, inspect the connections, power it again, and then invoke the corresponding console command.

Important: DE-9 pins 3 (TX), 4 (DTR), and 7 (RTS) are all driven outputs. Never connect any of these three pins to another one of these output pins. Connect each output only to the receiver input specified by the selected test.

The temporary Dupont-wire breakout is mechanically fragile. Keep wires short, make all changes with power removed, and prevent loose conductors from touching neighboring pins.

Configuration A: primary data and handshake pairs

Connect:

From driven output To 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 loopback-a. The firmware cycles all eight TX/DTR/RTS logic combinations, waits for the MAX3243 outputs and receivers to settle, and verifies all three receiver states plus VLD. Two inversions occur—once in the driver and once in the receiver—so the final ESP32 logic levels must match.

Configuration A can also be used for:

  • valid-test, with no external RS-232 peer connected.
  • uart-loopback <baud> [format] [bytes], although only the pin 3 to pin 2 link is needed by that command.
  • uart-suite, again using only the pin 3 to pin 2 data link.

Configuration B: remaining receivers

Remove all configuration A jumpers, then connect:

From driven output To 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 loopback-b. Together, configurations A and B exercise all three MAX3243 drivers and all five receivers.

Configuration C: CTS transmit gating

Disconnect every external DE-9 cable or peer, power the ESP32 and breakout down, and remove every previous jumper. Confirm that the two jumpers below are the only connections to these RS-232 pins before powering up again.

From driven output To receiver input Test purpose
DE-9 pin 3, TX DE-9 pin 2, RX Return UART1 transmitted data for exact comparison
DE-9 pin 4, DTR DE-9 pin 8, CTS Let software-controlled DTR present inactive and active CTS states
DE-9 pin 3 TX   ─────> pin 2 RX
DE-9 pin 4 DTR  ─────> pin 8 CTS

Run cts-flow-test. The test operates UART1 at 115200 baud with hardware CTS enabled and performs two phases:

  1. DTR logic 1 produces CTS logic 1, the inactive/high state. The firmware queues 512 bytes and verifies that transmission does not complete and no byte reaches RX during a 250 ms observation period.
  2. DTR changes to logic 0, producing active/low CTS. The queued transmission must resume automatically, and all 512 bytes must return through RX without missing, extra, or corrupted data and without UART errors.

A buffered UART transmitter is used so the console command itself cannot deadlock while CTS is blocking transmission. The firmware does not manipulate the UART transmit queue between the blocked and resumed phases.

Configuration D: RTS receive backpressure

Disconnect every external DE-9 cable or peer, power the ESP32 and breakout down, and remove every previous jumper. Confirm that the two jumpers below are the only connections to these RS-232 pins before powering up again.

From driven output To receiver input Test purpose
DE-9 pin 4, DTR DE-9 pin 2, RX Carry UART2-generated test data into UART1 RX
DE-9 pin 7, RTS DE-9 pin 1, DCD Return UART1 RTS through DCD 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 rts-flow-test. GPIO7 is temporarily routed from UART2 TX through the MAX3243 DTR driver. GPIO4 receives UART1 RTS through the DCD receiver and is simultaneously routed to UART2 CTS. This creates a complete hardware-controlled flow loop without an external serial peer.

The test queues 4096 bytes from UART2 but initially does not read UART1. UART1's receive ring eventually fills, its hardware FIFO crosses the configured threshold, and UART1 automatically deasserts RTS. That state passes through the physical pin 7 to pin 1 jumper and blocks UART2 through CTS. The firmware then drains UART1, which must automatically reassert RTS and allow UART2 to finish.

UART_BUFFER_FULL is expected during this deliberate pressure test. It means the UART ISR could not fit its current received-data batch into the software RX ring, confirming receive-side resource pressure. The driver preserves that batch while hardware RTS stops the sender. UART_FIFO_OVF, framing errors, parity errors, breaks, missing bytes, extra bytes, or data mismatches are failures.

Manual voltage and polarity checks

With no DE-9 loopback jumpers installed, use the static drivers command and measure each driven output relative to DE-9 pin 5 (GND):

drivers 0 0 0

Each of pins 3, 4, and 7 should be at a positive RS-232 voltage. Then run:

drivers 1 1 1

Each output should be at a negative RS-232 voltage. Exact values vary with supply, load, meter, and charge-pump behavior; polarity is the primary check. The firmware leaves all outputs at logic 1 after automated tests.

  1. Start with no DE-9 jumpers and run status.
  2. Use drivers 0 0 0 and drivers 1 1 1 for the three output-polarity measurements.
  3. Power down, install configuration A, power up, and run loopback-a.
  4. With configuration A still installed and no external peer, run valid-test.
  5. Keep only the pin 3 to pin 2 jumper and run a basic test such as uart-loopback 9600 8N1 256.
  6. If that passes, run uart-suite.
  7. Power down, replace the jumpers with configuration B, power up, and run loopback-b.
  8. Power down, install configuration C, power up, and run cts-flow-test.
  9. Power down, install configuration D, power up, and run rts-flow-test.

RTS and CTS remain ordinary GPIO signals during static and basic UART loopback tests. Only the two dedicated flow-control commands hand them to UART peripherals. Every test shuts the MAX3243 down while changing GPIO-matrix routing and restores all outputs to static logic 1 afterward.

Future hardware profiles

Alternative boards—such as the LILYGO T-Display-S3—or different RS-232 transceivers will receive separate profiles here. GPIO assignments must be reviewed for each board's display, buttons, USB connection, flash/PSRAM wiring, boot-strapping pins, and onboard peripherals.