Overview
This project is a small wall display for the house: a 64×32 RGB LED matrix driven by an ESP32-S3, running ESPHome and pulling data from Home Assistant. The default layout is simple. The top line shows an outdoor temperature reading from a weather sensor already in Home Assistant, and the bottom line shows a static message (currently the obligatory “Hello World!”).
The interesting part has not been the firmware, which is only a few dozen lines of YAML. It has been everything around it: choosing the parts, working out a power budget, planning the wiring so the board actually boots, and preparing to move from a hand-soldered prototype to a proper PCB.
This post covers the design decisions and what I learned along the way. It is a work in progress. The hardware selection, wiring plan, power budget and schematics are done, but the PCB is not designed yet. Device names and network details are left out.
Hardware Choices
| Role | Part | Why |
|---|---|---|
| Microcontroller | LilyGo T7-S3 (ESP32-S3, 16 MB flash, 8 MB PSRAM) | Plenty of GPIOs, PSRAM for the frame buffer, Wi-Fi built in |
| Display | P5 64×32 RGB panel, 1/16 scan, HUB75 | Cheap, bright, widely supported |
| Power supply | Mean Well LRS-35-5 (5 V, 7 A) | Enclosed, well-regarded, factory-set to 5.0 V |
| Bulk capacitor (optional) | 1000 µF / 10 V electrolytic | Smooths pulsed scanning current |
The ESP32-S3 is a good fit for HUB75 panels. It has enough free GPIOs to drive all 13 signal lines directly, and the DMA-based HUB75 drivers support it well. The T7-S3 board is compact and breaks out the pins I needed. The PSRAM gives the display driver room for double-buffering.
The panel is a standard P5 (5 mm pitch) 64×32 module. Because it is 1/16 scan, it only needs four row-address lines (A–D) rather than the five that larger panels need.
Architecture
ESPHome"] MCU -->|"HUB75 ribbon
(3.3 V logic)"| Panel MCU <-->|"Wi-Fi
ESPHome API"| HA["Home Assistant"] Sensor["Weather sensor"] --> HA
Three things hold it together:
- Power: a single 5 V supply feeds both the panel and the microcontroller, with a shared ground.
- Signal: the ESP32-S3 drives the panel directly at 3.3 V logic through a 16-pin HUB75 ribbon cable. Most panels accept this without a level shifter.
- Firmware: ESPHome with the Arduino framework and the HUB75 display component. A
lambda:block decides what gets drawn. The temperature comes over the native ESPHome API from Home Assistant.
Power Budget
LED panels draw a lot of current, so I worked out the numbers before buying the PSU:
| Load | Current |
|---|---|
| Panel, worst case (all pixels white) | 4.0 A |
| ESP32-S3 board | 0.5 A |
| Total worst case | 4.5 A |
| PSU rating | 7.0 A |
| Headroom | 2.5 A |
A temperature readout uses only a fraction of the pixels, so real-world draw is far lower. I still sized for the all-white case, because a firmware bug or a test pattern can easily light the whole panel.
The panel must never be powered from the dev board’s onboard regulator. Those are good for a few hundred milliamps at most, and a HUB75 panel will cheerfully exceed that.
One safety note: the PSU is fed from 240 V mains. The mains side (live, neutral and earth into the supply) should be done by a qualified electrician. That is the rule in New Zealand, and it is good sense anywhere.
Wiring and Boot Pitfalls
The HUB75 connector carries six colour lines (R1/G1/B1 for the upper half, R2/G2/B2 for the lower half), four address lines, clock, latch, output-enable and three grounds. I mapped each signal to a T7-S3 GPIO and colour-coded the wires by function: red, green and blue for the colour data, yellow for address, white for control and black for ground. That is not strictly necessary, but it makes visual checks much easier.
Two things in this planning stage taught me the most.
Strapping pins
The ESP32-S3 samples a handful of “strapping” pins at reset to decide how to boot. An early draft of my pin map put the panel’s latch line on one of them. A HUB75 panel can hold its inputs low at power-up, which can stop the MCU from booting normally, even though everything looks fine on the bench with the panel disconnected.
The fix is easy: keep every panel signal off the strapping pins. The real lesson was about documentation. The bad assignment had made it into one document while another document said never to do it. I now treat one plain-text schematic as the single source of truth for pin assignments and check the others against it.
Power sequencing and back-powering
If the MCU is running while the panel is unpowered, the protection diodes in the panel’s logic chips can sink current through the GPIOs. That drags down the board’s 3.3 V regulator and causes brown-outs. Running both from the same PSU means they power up together, which avoids the problem.
The opposite risk is back-powering. If the PSU’s 5 V is wired to the board while USB is also plugged in for flashing, two supplies end up fighting each other. My flashing routine is therefore strict: disconnect the PSU feed, flash over USB, unplug USB, then reconnect the PSU.
Firmware Notes
ESPHome makes this part pleasantly boring. A few things caught me out, though:
- The HUB75 component uses
panel_widthandpanel_height, not the genericwidth/height. - Some panels use FM6126A driver chips that need an initialisation sequence. Without
shift_driver: FM6126Athey stay completely blank even when the wiring is correct. Check your panel’s chips before you start doubting your soldering. - Font
glyphslists work best as single-line quoted strings. A multi-line YAML block produced confusing “duplicate character” errors.
Credentials live in a separate secrets file that is excluded from version control, with an example template committed in its place.
Towards a PCB
The prototype is built on Vero board. I wrote small Python scripts with Pillow that generate an illustrated A3 wiring schematic and a solder guide drawn from the underside of the board. Having them as code means a pin change only needs a re-run, not a redraw.
The next step is a proper PCB. I found no ready-made T7-S3 footprint or symbol in any of the usual libraries (LibrePCB, KiCad, EasyEDA, SnapMagic and others). A couple of generic ESP32 libraries came close but didn’t match. My plan is to model the T7-S3 as nothing more than its pin headers, taken from LilyGo’s official schematic, and redraw the circuit by hand in the PCB tool. The text schematic can’t be imported, but it serves as a checklist.
What Worked / What Didn’t
Worked
- Doing the power budget first. It made the PSU choice obvious and left comfortable headroom.
- Function-based wire colours. These cut wiring mistakes down noticeably.
- Generated schematics. They are reproducible, consistent in style, and cheap to update.
- ESPHome. It gives Home Assistant integration almost for free.
Didn’t (or not yet)
- Several overlapping documents. They let a pin conflict slip through, which the single source of truth now prevents.
- No off-the-shelf PCB part for the board. I’ll be drawing my own.
- Some open questions remain. I still need to confirm the panel’s driver IC, and to decide whether the bulk capacitor is needed for my lead lengths.
Lessons Learned
- Check strapping pins before you assign GPIOs on an ESP32. External hardware can quietly break the boot.
- Power the panel and the MCU from one supply, and never connect USB and external 5 V at the same time.
- Use the vendor’s official pinmap, not community diagrams. They don’t always agree.
- If an IDC ribbon gives a blank display that no firmware change fixes, check pin 1 at both ends. A transposed row is easy to make and hard to spot.
- If 3.3 V logic gives a dim or corrupted image, try a 74HCT245 buffer. It is a cheap fix to try before blaming the panel.
- Keep one canonical pin map. Everything else should be generated from it or checked against it.
I’ll follow up once the PCB is drawn and fabricated.
Comments