import machine
import math
import time
#######################################
# Pin and constant definitions
#######################################
ANALOG_PIN = machine.Pin(26, machine.Pin.IN)
BUTTON_PIN = machine.Pin(16, machine.Pin.IN, machine.Pin.PULL_UP)
START_PIN = 0
DISPLAY_COUNT = 4
MEASUREMENT_COUNT = 16
DECIMAL_PRECISION = 3
ADC_RANGE = float((2 ** 16 - 1))
button_state = 0
digit_list_hex = [
0x40, # 0
0x79, # 1
0x24, # 2
0x30, # 3
0x19, # 4
0x12, # 5
0x02, # 6
0x78, # 7
0x00, # 8
0x10, # 9
0x08, # A
0x03, # B
0x46, # C
0x21, # D
0x06, # E
0x0E, # F
0x7F # Empty
]
#######################################
# Global variables
#######################################
display_value = 0
segment_pins = []
display_select_pins = []
analogue_voltage_pin = None
current_display_index = DISPLAY_COUNT - 1
display_timer = None
prev_analogue_voltage = -1
#######################################
# 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_voltage(pin):
global display_value, prev_disp_val, display_timer
global prev_analogue_voltage, DECIMAL_PRECISION
values = [pin.read_u16() for _ in range(MEASUREMENT_COUNT)]
average_value = sum(values) // MEASUREMENT_COUNT
voltage = round((average_value / ADC_RANGE) * 3.3, DISPLAY_COUNT - 1)
if voltage != prev_analogue_voltage:
prev_analogue_voltage = voltage
new_display_value = int(voltage * math.pow(10, DECIMAL_PRECISION))
if False:
DECIMAL_PRECISION = 2
temp = 0
try:
temp = round(1 / (math.log(1 / (ADC_RANGE / average_value - 1)) / 3950 + 1.0 / 298.15) - 273.15, 1)
print(f'temp: {temp} C')
except:
pass
new_display_value = int(temp * math.pow(10, DECIMAL_PRECISION))
max_val = math.pow(10, DISPLAY_COUNT) - 1
if new_display_value > max_val:
print(f'warn: {new_display_value} exceeds {max_val}, clipping')
new_display_value = max_val
if display_value != new_display_value:
print(f'voltage: {voltage} mV')
display_value = new_display_value
disable_timer()
current_display_index = DISPLAY_COUNT - 1
display_digit(16, -1)
time.sleep(0.1)
enable_timer()
# Function to disable timer that triggers scanning 7 segment displays
def disable_timer():
global display_timer
display_timer.deinit()
# Function to enable timer that triggers scanning 7 segment displays
def enable_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_int):
global current_display_index, display_value
digit = int((abs(display_value) // math.pow(10, current_display_index))) % 10
display_digit(digit, current_display_index,
current_display_index == DECIMAL_PRECISION and 0 != DECIMAL_PRECISION)
current_display_index = (current_display_index - 1)
if current_display_index < 0:
current_display_index = DISPLAY_COUNT - 1
# 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 display_select_pins:
pin.value(0)
mask = digit_list_hex[digit_value]
for i in range(7):
segment_pins[i].value((mask >> i) & 1)
segment_pins[7].value(1 if dp_enable == False else 0)
if digit_index == -1:
for pin in display_select_pins:
pin.value(1)
elif 0 <= digit_index < DISPLAY_COUNT:
display_select_pins[digit_index].value(1)
# Function to test avaiable 7-segment displays
def display_test():
global display_value
disable_timer()
current_display_index = 0
for i in range(0, len(digit_list_hex)):
display_digit(i, -1, i % 2 != 0)
time.sleep(0.75)
for i in range(0, len(digit_list_hex)):
display_digit(i, DISPLAY_COUNT - 1 - (i % DISPLAY_COUNT), True)
time.sleep(0.75)
enable_timer()
#Function for pressing the pushbutton
def button_pressed(pin):
global button_state
button_state = button_state << 1 | pin.value()
button_state = button_state & 0xFFFF
return button_state == 0x8000
# Function to setup GPIO/ADC pins, timers and interrupts
def setup():
global segment_pins, display_select_pins, analogue_voltage_pin, voltage_value
global display_timer
for i in range(START_PIN + 8, START_PIN + 8 + DISPLAY_COUNT):
pin = machine.Pin(i, machine.Pin.OUT)
pin.value(0)
display_select_pins.append(pin)
for i in range(START_PIN, START_PIN + 8):
pin = machine.Pin(i, machine.Pin.OUT)
pin.value(1)
segment_pins.append(pin)
analogue_voltage_pin = machine.ADC(ANALOG_PIN)
display_timer = machine.Timer()
enable_timer()
if __name__ == '__main__':
setup()
#display_value_test()
while True:
if button_pressed(BUTTON_PIN):
read_voltage(analogue_voltage_pin)
time.sleep(0.5)