from machine import Pin
import time
# ==== GPIO Pins on ESP32 ====
DATA = Pin(23, Pin.OUT) # Serial Data Input (DS)
LATCH = Pin(18, Pin.OUT) # Latch Clock (ST_CP)
CLOCK = Pin(19, Pin.OUT) # Shift Register Clock (SH_CP)
# ==== Segment Byte Codes (Common Cathode 7-segment: 0-9) ====
digits = [
0b11000000, # 0
0b11111001, # 1
0b10100100, # 2
0b10110000, # 3
0b10011001, # 4
0b10010010, # 5
0b10000010, # 6
0b11111000, # 7
0b10000000, # 8
0b10010000 # 9
]
# ==== Digit Select Bitmasks for each of 4 digits ====
digit_masks = [
0b00001000, # Digit 1 (leftmost)
0b00000100, # Digit 2
0b00000010, # Digit 3
0b00000001 # Digit 4 (rightmost)
]
# ==== Helper: Shift out 1 byte MSB first ====
def shift_out(byte):
for i in range(8):
bit = (byte >> (7 - i)) & 1
DATA.value(bit)
CLOCK.value(1)
CLOCK.value(0)
# ==== Pads number string to 4 digits with leading zeros ====
def pad_left_zeros(s, length=4):
return '0' * (length - len(s)) + s
# ==== Main Display Function for 10 displays ====
def display_all(d1, d2, d3, d4, d5, d6, d7, d8, d9, d10):
vals = [pad_left_zeros(str(x)) for x in [d1, d2, d3, d4, d5, d6, d7, d8, d9, d10]]
for pos in range(4): # For each digit position (0 to 3)
seg_data = digits[int(vals[0][pos])] if vals[0][pos].isdigit() else 0xFF
shift_out(seg_data) # 1st IC: Segment byte
# Now push digit control data for IC2–IC11 (Displays 1–10)
for i in range(10):
ch = vals[i][pos]
digit_val = digit_masks[pos] if ch.isdigit() else 0x00
shift_out(digit_val)
LATCH.value(0)
LATCH.value(1)
time.sleep_ms(1) # Small delay for multiplexing
# ==== Test Display Values ====
# You can set any 4-digit number per display here
disp_vals = [1234, 5678, 2025, 9999, 3141, 8080, 1111, 4242, 7777, 1010]
# ==== Main Loop ====
while True:
for _ in range(100): # Refresh screen to keep display stable
display_all(*disp_vals)