import time, math, machine
# Constants
SEGMENT_START_PIN = 0 # Starting GPIO pin for segment control
ANALOG_IN = 26 # ADC pin connected to sensor
BUTTON_IN = 16 # GPIO pin for push button input
DIGITs_COUNTs = 4 # Number of digits in the 7-segment display
SAMPLE_AVERAGE = 10 # Number of ADC samples to average
DECIMAL_PLACES = 3 # Decimal precision for voltage display
ADC_HIGHEST_VALUE = 65535 # Max value from 16-bit ADC reading
pushBUTTON_DEBOUNCE = 50 # Debounce time in milliseconds
# 7-segment encoding for hexadecimal digits 0-F + blank (last entry)
SEGMENT_CODES = [
0x40, 0x79, 0x24, 0x30, 0x19, 0x12,
0x02, 0x78, 0x00, 0x10, 0x08, 0x03,
0x46, 0x21, 0x06, 0x0E, 0x7F
]
# Global variables
current_display_NO = 0 # Value currently displayed
previous_V_reading = -1 # Previous voltage to detect changes
last_button_press = 0 # Timestamp of last button press
active_digit_place = DIGITs_COUNTs - 1 # Current digit being refreshed
control_pins = [] # Pins for segments (a-g, dp)
select_pins = [] # Pins to activate specific digit positions
V_sensor = None # ADC object
push_button = None # Button input pin object
refresh_timer = None # Timer for display multiplexing
# Measures voltage from ADC and triggers display update if it changes
def measure_voltage(adc_pin):
global current_display_NO, previous_V_reading
try:
raw_readings = []
for _ in range(SAMPLE_AVERAGE):
raw_readings.append(adc_pin.read_u16()) # Read ADC value
time.sleep_us(100)
raw_avg = sum(raw_readings) // len(raw_readings)
measured_voltage = round((raw_avg / ADC_HIGHEST_VALUE) * 3.3, DECIMAL_PLACES)
if measured_voltage != previous_V_reading:
previous_V_reading = measured_voltage
display_integer = min(int(measured_voltage * 10**DECIMAL_PLACES), 10**DIGITs_COUNTs - 1)
if current_display_NO != display_integer:
current_display_NO = display_integer
reset_display()
return measured_voltage
except Exception as e:
print(f"Error reading voltage: {e}")
return None
# Updates one digit of the 7-segment display in a multiplexed fashion
def update_display_segments(timer):
global active_digit_place
digit_value = int(abs(current_display_NO) // 10**active_digit_place) % 10
show_decimal = active_digit_place == DECIMAL_PLACES and DECIMAL_PLACES != 0
illuminate_digit(digit_value, active_digit_place, show_decimal)
active_digit_place = (active_digit_place - 1) % DIGITs_COUNTs
# Lights up a single digit with given value and optional decimal point
def illuminate_digit(value, position, decimal_point=False):
if 0 <= value < len(SEGMENT_CODES):
for pin in select_pins: pin.value(0) # Turn off all digits
segment_mask = SEGMENT_CODES[value] # Get segment pattern
for segment in range(7):
control_pins[segment].value((segment_mask >> segment) & 1) # Set segments a-g
control_pins[7].value(not decimal_point) # Decimal point (dp) logic
if 0 <= position < DIGITs_COUNTs: select_pins[position].value(1) # Enable one digit
# Resets and restarts display refresh timer
def reset_display():
global active_digit_place
refresh_timer.deinit() # Stop current timer
active_digit_place = DIGITs_COUNTs - 1 # Start from rightmost digit
illuminate_digit(16, -1) # Clear display (16 is blank code)
time.sleep(0.1)
refresh_timer.init(period=4, mode=machine.Timer.PERIODIC, callback=update_display_segments)
# Initializes pins and timer
def initialize_hardware():
global control_pins, select_pins, V_sensor, push_button, refresh_timer
V_sensor = machine.ADC(ANALOG_IN) # Set up ADC pin
push_button = machine.Pin(BUTTON_IN, machine.Pin.IN, machine.Pin.PULL_UP) # Button with pull-up
select_pins = [machine.Pin(pin_num, machine.Pin.OUT) for pin_num in range(SEGMENT_START_PIN + 8, SEGMENT_START_PIN + 8 + DIGITs_COUNTs)] # Digit selectors
control_pins = [machine.Pin(pin_num, machine.Pin.OUT) for pin_num in range(SEGMENT_START_PIN, SEGMENT_START_PIN + 8)] # Segment controls
refresh_timer = machine.Timer() # Timer object
reset_display() # Start display refresh
# Main loop
if __name__ == '__main__':
print("Starting digital voltmeter...")
time.sleep(2.5)
print("set the (LDR -or- NTC -or- slide potentiometer) before running the program..")
time.sleep(2.5)
print("press the button to see the voltage measurement on the multi 7-segment.... ")
initialize_hardware()
while True:
# Check button press with debounce
if push_button.value() == 0 and time.ticks_ms() - last_button_press > pushBUTTON_DEBOUNCE:
last_button_press = time.ticks_ms()
voltage = measure_voltage(V_sensor) # Read and display voltage
if voltage is not None: print(f'Current Voltage: {voltage} V')
time.sleep(0.1)
change this wire connection
press this button
change the value of these to read the output voltage
EMBEDDED VOLTMETER ....READS VOLTAGE VALUE OF EACH (LDR -- NTC -- SLIDE POTENTIOMETER)
Made by : Abdullah Mohammed