# imports
import machine
import math
import time
#######################################
# Pin and constant definitions
#######################################
SEGMENT_START_PIN = 0 #gpio 0 to 11
DISPLAY_COUNT = 4 #4 digit seven segment
ADC_MAX = 65535 #2**16-1
DISPLAY_MAX = 9999 #filling the seven segment
SAMPLE_COUNT = 16
V_REF = 3.3 # maximum voltage + can be modefied
digit_list_hex = [#common anode reading 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 # no display
]
#######################################
# Global variables
#######################################
display_value = 0 #display 0 at first then the voltage value
current_index = 3 #leftmost digit
last_btn_time = 0
segment_pins = [] #from 0 to 8
select_pins = [] # from 8 to 12
analogue_pin = None
display_timer = None
btn_pressed = False
#######################################
# 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): # We can use the pin parameter if needed
global display_value, display_timer, V_REF, ADC_MAX, DISPLAY_MAX, SAMPLE_COUNT, current_index
reading = 0
for j in range(SAMPLE_COUNT):
reading += pin.read_u16()
average_reading = reading // SAMPLE_COUNT # averaging the value "percise measurement"
voltage = round((average_reading * V_REF)/ADC_MAX, 3)#voltage value in 3 decimal places
new_display_value = int(voltage * 1000) # converting to millivolt to be displayed
if new_display_value > DISPLAY_MAX:
print(f"The value is more than{DISPLAY_MAX}")
new_display_value = DISPLAY_MAX
if new_display_value != display_value:
print(f"The voltage is : {new_display_value} millivolt")
display_value = new_display_value
disable_display_timer()
current_index = 3
display_digit(16, -1) # turning off all the digits between each press
time.sleep(0.1) # be off for 100 ms between each press and reading value
enable_display_timer() # calling scan and displaying display value after changing to voltage
def interrupt_callback(pin):
global btn_pressed, last_btn_time
current_btn_ts = time.ticks_ms()
btn_delta_time = current_btn_ts - last_btn_time
if btn_delta_time > 200: #proper debouncing of 200 ms
last_btn_time = current_btn_ts
read_analogue_voltage(analogue_pin) #is called when pressing by irq falling
# 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)# handling with flickering
# 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 display_value, current_index
#from leftmost digit to be displayed then period of 4ms transferring to digit until rightmost
digit = int((abs(display_value) // (10**current_index)))%10 #getting the value of each digit by modulas
display_digit(digit, current_index, current_index==3)#display each digit in segments function, dp at leftmost[index(3)]
current_index = current_index - 1 #move to the other index"digit"
if current_index < 0: #if it's the last index return to the first index
current_index = 3
# 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):#between 0 and 16
return
for pin in select_pins:
pin.value(0) #turning off
for i in range(7):
segment_pins[i].value((digit_list_hex[digit_value] >> i)&1)# value of segments but shifting right
segment_pins[7].value(1 if dp_enable == False else 0)# enabling decimal point if true
if digit_index == -1:
for pin in select_pins:# display all the digits with value 16 empty
pin.value(1)
if 0 <= digit_index < 4: # [0,3]
select_pins[digit_index].value(1)# enabling the required digit
# Function to test avaiable 7-segment displays
def display_value_test():
global display_value
disable_display_timer()
current_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_display_timer()
# Function to setup GPIO/ADC pins, timers and interrupts
def setup():
global SEGMENT_START_PIN, DISPLAY_COUNT, analogue_pin, display_timer, select_pins, segment_pins
for i in range(SEGMENT_START_PIN + 8, SEGMENT_START_PIN + 8 + DISPLAY_COUNT):# range(8,12)"4"
pin = machine.Pin(i,machine.Pin.OUT)# i is 8 then 9 then 10 then 11
pin.value(0) # disable all digits
select_pins.append(pin) #gpio_8,9,10,11 in list
for i in range(SEGMENT_START_PIN, SEGMENT_START_PIN + 8):# range(0,8)"8" including dp(7)
pin = machine.Pin(i, machine.Pin.OUT)# i is 0 then 1 then 2 then 3 then 4 then 5 then 6 then7
pin.value(1) #disable all segments
segment_pins.append(pin) # gpio_0,1,2,3,4,5,6,7
analogue_pin = machine.ADC(machine.Pin(26)) #POT or NTC or LDR
interrupt_pin = machine.Pin(16, machine.Pin.IN, machine.Pin.PULL_UP)# push button to gnd
display_timer = machine.Timer() #read the time
enable_display_timer() #calling the scan_display function
interrupt_pin.irq(trigger=machine.Pin.IRQ_FALLING, handler=interrupt_callback)
if __name__ == '__main__':
setup()
#display_value_test()
#breif working idea:
#
#beginning with setup to display turn off digits and displaying 0s at all digits
#then if button pressed calling the read analogue value to measure the reading and equalling to display value
#then transferring to the scan which get the value and display each digit from the leftmost to the rightmost
#this is by display digit function wich get the value of segments by shifting right
#scan is repeated each 4 ms to display all digits"index" of the analogue or at first with 0