7-Segment Displays
Driving numeric 7-segment displays from an ESP32 using the TM1637 (2-wire), MAX7219, and MAX7221 (SPI) driver modules for cockpit altimeters, speed tapes, and frequency readouts.
A 7-segment display has seven LED segments (a–g) plus an optional decimal point. Driving them directly from an ESP32 requires 8 pins per digit — impractical for multi-digit readouts. Driver ICs handle the multiplexing internally and communicate over a 2- or 4-wire bus.
| Module | Interface | Digits | GPIO pins used | Best for |
|---|---|---|---|---|
| TM1637 | Custom 2-wire (CLK + DIO) | 4 (expandable) | 2 | Simple readouts, easy wiring |
| MAX7219 | SPI-like (MOSI + CLK + LOAD) | 8 per chip (daisy-chainable) | 3 (shared across chain) | Multi-display panels, altitude, speed |
| MAX7221 | True SPI (MOSI + CLK + CS̄) | 8 per chip (daisy-chainable) | 3 (shared SPI bus) | Mixed SPI bus, cockpit near radio equipment |
| Direct + 74HC595 | Shift register + GPIO mux | 1 per 595 | 3 + 1 digit-select pin | Custom segment control, unusual layouts |
Segment map
| Bit | Segment | Position on digit |
|---|---|---|
| 0 (0x01) | a | Top horizontal |
| 1 (0x02) | b | Upper-right vertical |
| 2 (0x04) | c | Lower-right vertical |
| 3 (0x08) | d | Bottom horizontal |
| 4 (0x10) | e | Lower-left vertical |
| 5 (0x20) | f | Upper-left vertical |
| 6 (0x40) | g | Middle horizontal |
| 7 (0x80) | dp | Decimal point |
| TM1637 pin | Connect to |
|---|---|
| CLK | GPIO 22 |
| DIO | GPIO 23 |
| VCC | 3.3 V |
| GND | GND |
Basic number display
// Library Manager → search "TM1637Display" by Avishkar Mishra / Arduino TM1637
#include <TM1637Display.h>
const int CLK_PIN = 22;
const int DIO_PIN = 23;
TM1637Display display(CLK_PIN, DIO_PIN);
void setup() {
display.setBrightness(5); // 0 (dim) – 7 (bright)
display.showNumberDec(0, true); // show "0000" with leading zeros
}
void loop() {
// Show current altitude from X-Plane (example: 35000 ft)
int altitude = 35000;
display.showNumberDec(altitude);
delay(100);
}Colons and custom segments
// Colons and individual segments
#include <TM1637Display.h>
TM1637Display display(22, 23);
void showTime(int hours, int minutes) {
// showNumberDecEx: value, dots mask, leading zeros, length, position
// dots mask 0x40 = colon on (centre dots)
display.showNumberDecEx(hours * 100 + minutes, 0x40, true);
}
void showLabel() {
// Custom segments for text — e.g. "AL t" (altitude label)
const uint8_t SEG_A = 0b01110111; // A
const uint8_t SEG_L = 0b00111000; // L
const uint8_t SEG_T = 0b01111000; // t
uint8_t data[] = { SEG_A, SEG_L, 0, SEG_T };
display.setSegments(data);
}| Pin | Connect to |
|---|---|
| DIN | GPIO 23 (MOSI) — via level shifter |
| CLK | GPIO 18 (SCK) — via level shifter |
| CS / LOAD | GPIO 5 |
| VCC | 5 V external supply |
| GND | Common GND |
| DOUT | DIN of next chip in chain |
RSET — segment current resistor
Both ICs require an external resistor between ISET (pin 18) and V+ to set the peak segment current. The setIntensity() call in software then scales brightness from 0 to 15 within that ceiling.
| RSET value | Peak segment current | Use when |
|---|---|---|
| 10 kΩ | ~40 mA | Maximum brightness (check display's absolute max) |
| 28 kΩ | ~15 mA | Standard 7-segment modules |
| 33 kΩ | ~12 mA | Conservative choice, good for most cockpit panels |
| 47 kΩ | ~9 mA | Low-power or high-efficiency LED displays |
The LedControl library works with both MAX7219 and MAX7221 without any code changes — the constructor and all method calls are identical.
// Library Manager → search "LedControl" by Eberhard Fahle
#include <LedControl.h>
// LedControl(DIN, CLK, CS, numDevices)
LedControl lc = LedControl(23, 18, 5, 1);
void setup() {
lc.shutdown(0, false); // wake up MAX7219 (starts in power-down mode)
lc.setIntensity(0, 8); // brightness 0–15
lc.clearDisplay(0);
}
void showAltitude(int feet) {
// Write individual digits right-to-left (position 0 = rightmost)
for (int pos = 0; pos < 8; pos++) {
lc.setDigit(0, pos, feet % 10, false);
feet /= 10;
if (feet == 0) { break; }
}
}
void loop() {
showAltitude(35000);
delay(100);
} To drive multiple chips, set numDevices to the chain length and pass the device index (0-based) to each lc.* call.
The MAX7221 is a drop-in replacement for the MAX7219 with the same pinout, register map, and software interface. Two hardware differences matter for cockpit builds.
| Feature | MAX7219 | MAX7221 |
|---|---|---|
| Chip-select type | LOAD — active-high latch | CS̄ — active-low, true SPI |
| DOUT when idle | Always driven (not tri-stated) | High-impedance when CS̄ is high |
| Segment output slew rate | Fast (higher EMI) | Slew-rate limited (lower EMI) |
| Shutdown current | ~150 µA | ~10 µA |
| SPI bus sharing | Not possible (DOUT always active) | Fully supported |
| LedControl library | Supported | Supported — identical API |
| Cost | Lower | Slightly higher |
When to choose the MAX7221
SPI bus sharing. The MAX7219's DOUT is permanently driven, which corrupts the MISO line for any other SPI device sharing the bus. The MAX7221 tri-states DOUT whenever CS̄ is high, so it coexists cleanly with other SPI peripherals (SD cards, OLED displays, accelerometers) on the same three-wire bus.
Cockpit radio-frequency environment. The MAX7221's slew-rate-limited segment drivers reduce high-frequency switching noise on the display lines. In a cockpit with COM / NAV receivers, lower EMI from display drivers lowers the risk of interference with sensitive radio equipment — a meaningful practical advantage even if the effect is small on a home simulator.
| Application | Driver | Digits needed | Notes |
|---|---|---|---|
| COM / NAV radio frequency | TM1637 | 6 | Two 4-digit modules; show active & standby |
| Altitude (MCP / FCU) | MAX7219 | 5 | 5-digit altitude, leading zeros suppressed |
| Heading bug (HDG) | TM1637 | 3 | 000–359, padded with leading zeros |
| VS (vertical speed) | TM1637 | 4 | ±4 digits; use custom segment for minus sign |
| Transponder code | TM1637 | 4 | Octal display (0–7 per digit), show squawk code |
| Multi-panel CDU scratchpad | MAX7219 chain | 8+ | Daisy-chain two MAX7219 for full alphanumeric row |