Add photos and datasheet; correct wiring and protocol docs

The 20L203 input is RS-232 (reference build uses a MAX3232), it runs on
5-24 V, and it boots in non-scrolling overwrite mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mangavalkandClaude Opus 5.5 committed 2026-10-31 17:44:07 +01:00
1 parent bd9389e04a
commit 3fcd15ad86
7 files changed
+113 -52

No files matched your search

+91 -34
View File
@@ -1,16 +1,23 @@
# Samsung serial VFD — ESPHome component
An ESPHome external component for the Samsung 2-line × 20-character serial VFD
(vacuum fluorescent display) that takes 5 V TTL serial at 9600 baud, 8N1.
An ESPHome external component for the Samsung 20L203 2-line × 20-character VFD
(vacuum fluorescent display) pole display, driven over a single serial wire at
9600 baud.
It keeps a copy of the screen in RAM and only sends data when something
changes. Updates overwrite the screen in place instead of clearing it first,
so the clock doesn't flicker.
<p>
<img src="docs/front.jpg" alt="Front of the display" height="300">
<img src="docs/back.jpg" alt="Back of the controller board" height="300">
</p>
```
components/samsung_vfd/ the component (Python schema + C++)
examples/samsung-vfd.yaml full example: clock + two Home Assistant text entities
examples/secrets.yaml.example
docs/ photos and the 20L203DA12 datasheet
```
## Using it from your ESPHome server
@@ -43,24 +50,70 @@ into your ESPHome config folder. Add the keys from
[examples/secrets.yaml.example](examples/secrets.yaml.example) to your
`secrets.yaml`.
## Wiring
## Hardware
The component only sends to the display. The ESP32's 3.3 V output is enough for
most 5 V TTL inputs. ESP32 GPIOs are **not** 5 V tolerant, so never connect the
display's TX back to the ESP32 without a level shifter or divider.
The board in the photos is a 20L203DA5 (rev A). The included
[datasheet](docs/20L203DA12-datasheet.pdf) is for the 20L203DA12, a variant
with the same command set.
| Display | ESP32 |
|---------|-------|
| RX | GPIO17 (UART TX) |
| GND | GND |
| 5 V | external 5 V supply |
### Connector (3-pin Molex 5046-03A)
The display draws more current than a dev-board regulator can comfortably
supply. Power it from its own supply and connect the grounds together.
| Pin | Signal | Connect to |
|-----|--------|------------|
| 1 | VCC | 5–24 V DC supply |
| 2 | RXD | MAX3232 T1OUT (T1IN ← ESP32 GPIO17), see below |
| 3 | GND | supply GND, MAX3232 GND **and** ESP32 GND |
To use GPIO1 (TX0, shared with USB logging), set `tx_pin: GPIO1` and
`logger: baud_rate: 0` so log output doesn't end up on the display. If the
display stays blank at 3.3 V levels, add a 74HCT125 or similar level shifter.
### Power
The display takes 5–24 V. At 5 V it draws about 0.8 A typical and 1.2 A
maximum, and the inrush current at power-on can be up to five times that. A
dev-board regulator can't supply this, so give the display its own supply,
for example 12 V at 1 A, and connect the grounds together.
### Signal levels
The RXD input goes through an RS-232 receiver: it expects ±3 to ±15 V and
idles at the negative level (mark). It tolerates ±30 V, so a 3.3 V ESP32 pin
can't damage it. There are two ways to connect it:
- **Through a MAX3232 (recommended, and how the original build is wired).**
Power the MAX3232 from the ESP32's 3.3 V, then wire GPIO17 → T1IN and
T1OUT → display RXD. The MAX3232 produces real RS-232 levels and does the
inversion itself, so use the plain `tx_pin: GPIO17`.
- **Direct from the ESP32.** A plain TTL signal arrives inverted, so wire
GPIO17 straight to RXD and invert the pin in the UART config:
```yaml
uart:
id: uart_vfd
tx_pin:
number: GPIO17
inverted: true
baud_rate: 9600
```
This relies on the receiver's switching threshold, which on most RS-232
receivers is around 1.3 V. It isn't guaranteed by the spec, which asks for
at least 3 V.
If the display shows garbage or nothing at all, the inversion setting is the
first thing to check: off with a MAX3232, on without one.
### Jumpers
The 2×8 pin header on the board selects the following. All jumpers open is the
factory default.
| Jumpers | Setting | Default (open) |
|---------|---------|----------------|
| 1, 2 | baud rate: 9600 / 4800 / 2400 / 19200 | 9600 |
| 3, 4 | parity: none / odd / even | none |
| 5 | self-test at power-on | off |
| 6, 7, 8 | font for codes 0x80–0xFF | PC437 |
This component expects 9600 baud and no parity, which ESPHome's UART uses by
default.
## Configuration
@@ -70,7 +123,7 @@ samsung_vfd:
uart_id: uart_vfd
cols: 20 # default 20 (1–80)
rows: 2 # default 2 (1–8)
send_newlines: false # default false; send CR LF between lines
send_newlines: false # default false; leave off for this display
```
The UART must be 9600 baud with a `tx_pin`. The component requires a `time:`
@@ -121,26 +174,30 @@ characters become spaces.
## Protocol
These are the commands the component uses. The datasheet, section 5.4, lists
the rest, including cursor positioning, brightness, blinking and the
annunciator triangles.
| Bytes | Effect |
|-------|--------|
| `1B 40` (`ESC @`) | init / reset |
| `0C` | clear screen |
| `0B` | cursor home |
| text | printed at the cursor; wraps to the next line by itself |
| `1B 40` (`ESC @`) | initialise: reset settings, clear, cursor home |
| `0C` | clear screen, cursor home |
| `0B` | cursor home (top-left) |
| `20`–`FF` | print a character and move the cursor right |
Each update sends `0B` (home) followed by both lines, each padded to exactly
`cols` characters.
At power-on the display is in overwrite mode. After the last column of the top
line the cursor continues on the bottom line, and after the last column of the
bottom line it goes back to the top-left. Nothing scrolls. Each update
therefore sends `0B` (home) followed by both lines, each padded to exactly 20
characters.
## Troubleshooting
- **Line 2 lands on the wrong row, or text runs together:** try
`send_newlines: true`.
- **The screen scrolls up a line after each update:** the display scrolls as
soon as the last cell is written. Use `cols: 19` together with
`send_newlines: true`.
- **A stray character appears top-left:** the display doesn't treat `0B` as
home. Change `CMD_HOME` in
[samsung_vfd.h](components/samsung_vfd/samsung_vfd.h).
- **Garbled characters:** check that `uart:` is at 9600 baud and that the
display takes 5 V TTL levels, not RS-232 levels. A real RS-232 input needs a
MAX232 inverter.
- **Garbage or nothing on the display:** toggle `inverted:` on the TX pin (see
[Signal levels](#signal-levels)). Check that the baud jumpers 1 and 2 are
open (9600) and that parity jumpers 3 and 4 are open (none).
- **The display runs its self-test for about 20 s after power-on:** jumper 5 is
shorted.
- **Line 2 text lands on line 1:** make sure `send_newlines` is off. With
20-column lines the cursor has already wrapped to line 2, and an extra line
feed sends it back to line 1.