# imports
import machine
import math
import time
from machine import Timer
#######################################
# Pin and constant definitions
#######################################
Main_Button_PIN = 16
DISPLAY_Count = 4
DECIMAL_places = 3
ADC_REF_VOLTAGE = 3.3
ADC_RANGE = 65535
DEBOUNCE_TIME_Per_ms = 200
digit_list_hex = [0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10, 0x08, 0x03, 0x46, 0x21, 0x06, 0x0E, 0x7F]
#######################################
# Global variables
#######################################
display_value = 0
pin_list = []
volt_pin = None
select_pin_list = []
but_pin = None
display_signal = DISPLAY_Count - 1
display_timer = None
previous_analogue_voltage = -1
last_button_pressed = 0
debounce_timer = Timer()
#######################################
# Function definitions
#######################################
# Function to read the ADC pin and
# to convert the digital value to a voltage level in the 0-3.3V range
# This function updates the value of the display_value global variable
def read_analogue_voltage(pin):
global display_value, previous_analogue_voltage
val = pin.read_u16()
analogue_voltage = round((val / ADC_RANGE) * ADC_REF_VOLTAGE, DECIMAL_places)
if analogue_voltage != previous_analogue_voltage:
previous_analogue_voltage = analogue_voltage
new_display_value = int(analogue_voltage * 1000)
if display_value != new_display_value:
display_value = new_display_value
reset_display()
return analogue_voltage
# Function to disable timer that triggers scanning 7 segment displays
def disable_display_timer():
global display_timer
display_timer.deinit()
# Function to enable timer that triggers scanning 7 segment displays
def enable_display_timer():
global display_timer
display_timer.init(period=4, mode=machine.Timer.PERIODIC, callback=scan_display)
# Function to handle scanning 7 segment displays
# Display the value stored in the display_value global variable
# on available 7-segment displays
def scan_display(timer_interrupt):
global display_signal, display_value
digit = int(abs(display_value) // math.pow(10, display_signal)) % 10
display_digit(digit, display_signal, display_signal == DECIMAL_places)
display_signal = (display_signal - 1) % DISPLAY_Count
# Function display the given value on the display with the specified index
# dp_enable specifies if the decimal pooint should be on or off
def display_digit(digit_value, digit_index, dp_enable=False):
if digit_value < 0 or digit_value > len(digit_list_hex):
return
for pin in select_pin_list:
pin.value(0)
mask = digit_list_hex[digit_value]
for i in range(7):
pin_list[i].value((mask >> i) & 1)
pin_list[7].value(not dp_enable)
if digit_index == -1:
for pin in select_pin_list:
pin.value(1)
elif 0 <= digit_index < DISPLAY_Count:
select_pin_list[digit_index].value(1)
# Function to handle the button interrupt
def but_interrupt(pin):
global last_button_pressed
current_time = time.ticks_ms()
if current_time - last_button_pressed > DEBOUNCE_TIME_Per_ms:
last_button_pressed = current_time
voltage = read_analogue_voltage(volt_pin)
if voltage is not None:
print(f'Voltage: {voltage} V')
# Function to setup GPIO/ADC pins, timers and interrupts
def setup():
global pin_list, select_pin_list, volt_pin, but_pin, display_timer
select_pin_list = [machine.Pin(i, machine.Pin.OUT) for i in range(8, 8 + DISPLAY_Count)]
for pin in select_pin_list:
pin.value(0)
pin_list = [machine.Pin(i, machine.Pin.OUT) for i in range(0, 8)]
for pin in pin_list:
pin.value(1)
volt_pin = machine.ADC(26)
but_pin = machine.Pin(Main_Button_PIN, machine.Pin.IN, machine.Pin.PULL_UP)
# Set up interrupt for the button
but_pin.irq(trigger=machine.Pin.IRQ_FALLING, handler=but_interrupt)
display_timer = machine.Timer()
enable_display_timer()
# The following Function is declared to reset the display
def reset_display():
global display_signal
disable_display_timer()
display_signal = DISPLAY_Count - 1
display_digit(16, -1)
time.sleep(0.1)
enable_display_timer()
# Function to test avaiable 7-segment displays
def display_value_test():
for i in range(16):
display_digit(i, 0)
time.sleep(0.5)
if __name__ == '__main__':
setup()
while True:
time.sleep(1)