import machine
import math
import time
# Constants and pin configuration
SEVEN_SEGMA = 0
ANALOGUE_INPUT = 26
DISPLAY_COUNT = 4
MEASUREMENT = 16
PRECISION = 3
ADC_MAX_VALUE = float((2 ** 16) - 1)
BUTTON_INPUT_PIN = 16
# 7-segment display hex values (0-9, A-F, blank)
DIGITAL_LIST_HEX = [
0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78,
0x00, 0x10, 0x08, 0x03, 0x46, 0x21, 0x06, 0x0E, 0x7F
]
# Globals
display_value = 0
segment_pins = []
displays_pins = []
analogue_voltage_pin = None
current_display_index = DISPLAY_COUNT - 1
display_timer = None
analogue_voltage = -1
prev_analogue_voltage = -1
button_active = False
button_was_pressed = False
last_press_time = 0
debounce_delay = 200
# Read ADC and convert to voltage
def read_analogue_voltage(pin):
global display_value, prev_analogue_voltage, analogue_voltage
total_value = 0
for _ in range(MEASUREMENT):
total_value += pin.read_u16()
average_value = total_value // MEASUREMENT
analogue_voltage = round((average_value / ADC_MAX_VALUE) * 3.3, PRECISION)
if analogue_voltage != prev_analogue_voltage:
prev_analogue_voltage = analogue_voltage
new_display_value = int(analogue_voltage * (10 ** PRECISION))
max_val = int(10 ** DISPLAY_COUNT) - 1
if new_display_value > max_val:
print(f'Warning: {new_display_value} exceeds {max_val}, clipping')
new_display_value = max_val
if display_value != new_display_value:
print(f'Voltage: {analogue_voltage} V')
display_value = new_display_value
disable_display_timer()
display_digit(16, -1) # Turn off display
time.sleep(0.1)
enable_display_timer()
# Timer control functions
def disable_display_timer():
global display_timer
display_timer.deinit()
def enable_display_timer():
global display_timer
display_timer.init(period=4, mode=machine.Timer.PERIODIC, callback=scan_display)
# Scan display and update digits
def scan_display(timer):
global current_display_index, display_value
digit = int((abs(display_value) // (10 ** current_display_index)) % 10)
display_digit(
digit,
current_display_index,
current_display_index == PRECISION and PRECISION != 0
)
current_display_index -= 1
if current_display_index < 0:
current_display_index = DISPLAY_COUNT - 1
# Display a single digit on the 7-segment
def display_digit(digit_value, digit_index, dp_enable=False):
if digit_value < 0 or digit_value >= len(DIGITAL_LIST_HEX):
return
for pin in displays_pins:
pin.value(0)
mask = DIGITAL_LIST_HEX[digit_value]
for i in range(7):
segment_pins[i].value((mask >> i) & 1)
segment_pins[7].value(0 if dp_enable else 1)
if digit_index == -1:
for pin in displays_pins:
pin.value(1)
elif 0 <= digit_index < DISPLAY_COUNT:
displays_pins[digit_index].value(1)
# Setup GPIO and timers
def setup():
global segment_pins, displays_pins, analogue_voltage_pin, display_timer
for i in range(SEVEN_SEGMA, SEVEN_SEGMA + 8):
pin = machine.Pin(i, machine.Pin.OUT)
pin.value(1)
segment_pins.append(pin)
for i in range(SEVEN_SEGMA + 8, SEVEN_SEGMA + 8 + DISPLAY_COUNT):
pin = machine.Pin(i, machine.Pin.OUT)
pin.value(1)
displays_pins.append(pin)
analogue_voltage_pin = machine.ADC(ANALOGUE_INPUT)
display_timer = machine.Timer()
enable_display_timer()
# Button interrupt handler
def button_interrupt(pin):
global button_was_pressed
button_was_pressed = True
# Setup button interrupt
def setup_button():
global button_input
button_input = machine.Pin(BUTTON_INPUT_PIN, machine.Pin.IN, machine.Pin.PULL_UP)
button_input.irq(trigger=machine.Pin.IRQ_FALLING, handler=button_interrupt)
# Main program
if __name__ == '__main__':
setup()
setup_button()
last_press_time = time.ticks_ms()
while True:
if button_was_pressed:
current_time = time.ticks_ms()
if time.ticks_diff(current_time, last_press_time) > debounce_delay:
read_analogue_voltage(analogue_voltage_pin)
last_press_time = current_time
button_was_pressed = False
time.sleep_ms(10)