import time , math , machine
"""
Voltage Monitor with 7-Segment Display
Reads voltage from the circuit and displays on 4-digit 7-segment display
Button press prints current voltage to console
"""
# ---------------------------
# HARDWARE CONFIGURATION
# ---------------------------
SEGMENT_DISPLAY_START_PIN = 0 # First pin for 7-segment display control
ANALOG_INPUT_PIN = 26 # Pin for LDR voltage measurement
BUTTON_INPUT_PIN = 16 # Pin for button input
# ---------------------------
# DISPLAY SETTINGS
# ---------------------------
DIGIT_COUNT = 4 # Number of digits in 7-segment display
SAMPLE_AVERAGE_COUNT = 10 # Number of samples to average for stable reading
VOLTAGE_DECIMAL_PLACES = 3 # Decimal places to display (e.g., 3 = 3.456V)
# ---------------------------
# HARDWARE CONSTANTS
# ---------------------------
ADC_MAX_VALUE = 65535 # Maximum value for 16-bit ADC (0-65535)
BUTTON_DEBOUNCE_MS = 50 # Debounce time for button in milliseconds
# ---------------------------
# 7-SEGMENT DISPLAY PATTERNS
# Hex values for digits 0-9, letters A-F, and blank display
# Each bit represents a segment (a-g + decimal point)
# ---------------------------
SEGMENT_PATTERNS = [
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 # Blank display
]
# ---------------------------
# GLOBAL STATE VARIABLES
# ---------------------------
current_display_number = 0 # Current value being displayed (as integer)
previous_voltage_reading = -1 # Last voltage reading for change detection
last_button_press_time = 0 # Timestamp of last button press
active_digit_position = DIGIT_COUNT - 1 # Currently active display digit
segment_control_pins = [] # List of segment control pins (a-g + dp)
digit_select_pins = [] # List of digit select pins
voltage_sensor = None # ADC object for voltage measurement
button = None # Button input object
display_refresh_timer = None # Timer for display multiplexing
# ---------------------------
# VOLTAGE MEASUREMENT FUNCTION
# ---------------------------
def measure_voltage(adc_pin):
"""Read and process voltage from ADC pin with error handling"""
global current_display_number, previous_voltage_reading
try:
# Take multiple readings and average them to reduce noise
raw_readings = []
for _ in range(SAMPLE_AVERAGE_COUNT):
raw_readings.append(adc_pin.read_u16())
time.sleep_us(100) # Small delay between readings
raw_avg = sum(raw_readings) // len(raw_readings)
# Convert raw ADC value to voltage (0-3.3V range)
measured_voltage = round((raw_avg / ADC_MAX_VALUE) * 3.3, VOLTAGE_DECIMAL_PLACES)
# Only update display if voltage has changed
if measured_voltage != previous_voltage_reading:
previous_voltage_reading = measured_voltage
# Convert voltage to integer for display (e.g., 3.3V → 3300)
display_integer = min(int(measured_voltage * 10**VOLTAGE_DECIMAL_PLACES),
10**DIGIT_COUNT - 1)
if current_display_number != display_integer:
current_display_number = display_integer
reset_display() # Update the display with new value
return measured_voltage
except Exception as e:
print(f"Error reading voltage: {e}")
return None
# ---------------------------
# DISPLAY FUNCTIONS
# ---------------------------
def update_display_segments(timer):
"""Timer callback for display multiplexing (refreshes each digit)"""
global active_digit_position
# Extract current digit value from display number
digit_value = int(abs(current_display_number) // 10**active_digit_position) % 10
# Determine if decimal point should be lit (based on DECIMAL_PLACES position)
show_decimal = active_digit_position == VOLTAGE_DECIMAL_PLACES and VOLTAGE_DECIMAL_PLACES != 0
# Output the digit to the display
illuminate_digit(digit_value, active_digit_position, show_decimal)
# Move to next digit position (right to left, wrapping around)
active_digit_position = (active_digit_position - 1) % DIGIT_COUNT
def illuminate_digit(value, position, decimal_point=False):
"""Light up a single digit on the 7-segment display"""
if 0 <= value < len(SEGMENT_PATTERNS):
# Turn off all digit select pins
for pin in digit_select_pins:
pin.value(0)
# Get segment activation pattern from lookup table
segment_mask = SEGMENT_PATTERNS[value]
# Set each segment pin according to the pattern
for segment in range(7):
segment_control_pins[segment].value((segment_mask >> segment) & 1)
# Set decimal point (inverted logic - LOW turns it on)
segment_control_pins[7].value(not decimal_point)
# Turn on the current digit select pin
if 0 <= position < DIGIT_COUNT:
digit_select_pins[position].value(1)
def reset_display():
"""Reinitialize display multiplexing sequence"""
global active_digit_position
display_refresh_timer.deinit() # Stop current timer
active_digit_position = DIGIT_COUNT - 1 # Reset to leftmost digit
illuminate_digit(16, -1) # Blank display (using special value 16)
time.sleep(0.1) # Brief pause
# Restart timer for display multiplexing (4ms refresh per digit)
display_refresh_timer.init(
period=4,
mode=machine.Timer.PERIODIC,
callback=update_display_segments
)
# ---------------------------
# HARDWARE INITIALIZATION
# ---------------------------
def initialize_hardware():
"""Configure all hardware components"""
global segment_control_pins, digit_select_pins, voltage_sensor, button, display_refresh_timer
# Initialize ADC for voltage measurement
voltage_sensor = machine.ADC(ANALOG_INPUT_PIN)
# Initialize button with internal pull-up resistor
button = machine.Pin(BUTTON_INPUT_PIN, machine.Pin.IN, machine.Pin.PULL_UP)
# Set up digit select pins (for multiplexing)
digit_select_pins = [
machine.Pin(pin_num, machine.Pin.OUT)
for pin_num in range(SEGMENT_DISPLAY_START_PIN + 8,
SEGMENT_DISPLAY_START_PIN + 8 + DIGIT_COUNT)
]
# Set up segment control pins (a-g + decimal point)
segment_control_pins = [
machine.Pin(pin_num, machine.Pin.OUT)
for pin_num in range(SEGMENT_DISPLAY_START_PIN,
SEGMENT_DISPLAY_START_PIN + 8)
]
# Initialize display timer
display_refresh_timer = machine.Timer()
reset_display() # Start display multiplexing
# ---------------------------
# MAIN PROGRAM 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 for button press with debouncing
if button.value() == 0 and time.ticks_ms() - last_button_press_time > BUTTON_DEBOUNCE_MS:
last_button_press_time = time.ticks_ms()
voltage = measure_voltage(voltage_sensor)
if voltage is not None:
print(f'Current Voltage: {voltage} V')
# Small delay to prevent CPU overload
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)