How to build a reset loop in micropython

66 Views Asked by At

I'm trying to build a alarm clock with my Pi Pico microcontroller. I have a LCD Display to visualize the output and 4 Buttons for the input.

There is no alarm function yet, I try to get to the destination step by step.

My Program looks like this right now: Enter the time via the Buttons in Hours, Minutes and Seconds. After that the values are linked(Initialized) to the internal RTC of my Pico and are being displayed on the LCD. The LCD Display gets updated every second to show the current time.

However, I want to start the "Time Input Process" again when Button4 is pressed for 3 seconds. This should be possible as often as required, as long as the current time is displayed in the LCD.

import utime

import machine
from machine import Pin
from machine import I2C
from lcd_api import LcdApi
from pico_i2c_lcd import I2cLcd

I2C_ADDR     = 0x27
I2C_NUM_ROWS = 4
I2C_NUM_COLS = 20

i2c = I2C(0, sda=machine.Pin(0), scl=machine.Pin(1), freq=400000)
lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)    



#Own Code 

Hour = 0
Minute = 0
Second = 0
prev_Hour = 0
prev_Minute = 0
prev_Second = 0

current_step= "Hour"

#clear Display
lcd.clear()

rtc = machine.RTC()
#rtc.datetime((2024, 1, 21, Hour, Minute, Second, 0, 0))
#print(rtc.datetime())


#GPIO 10,11,12,13 for Buttons !!!PIN 14,15,16,17!!!
#initialisze GPIO's as Input, Pulldown
Button1 = Pin(10, Pin.IN, Pin.PULL_DOWN)
Button2 = Pin(11, Pin.IN, Pin.PULL_DOWN)
Button3 = Pin(12, Pin.IN, Pin.PULL_DOWN)
Button4 = Pin(13, Pin.IN, Pin.PULL_DOWN)

def show_time_Hour():
    lcd.clear()
    print("current Hour: {:02d}:{:02d}:{:02d}".format(Hour, Minute, Second))
    lcd.putstr("Hour:  {:02d}:{:02d}:{:02d}".format(Hour, Minute,Second))       

def show_time_Minute():
    lcd.clear()
    print("current Minute: {:02d}:{:02d}".format(Hour, Minute))
    lcd.putstr("Minute:{:02d}:{:02d}:{:02d}".format(Hour, Minute,Second))  

def show_time_Second():
    lcd.clear()
    print("current Second: {:02d}:{:02d}:{:02d}".format(Hour, Minute, Second))
    lcd.putstr("Second:{:02d}:{:02d}:{:02d}".format(Hour, Minute,Second))  

def show_current_Time():
    while True:
        lcd.clear()
        current_time= rtc.datetime()
        Hour, Minute, Second = current_time[4], current_time[5], current_time[6]
        print("current Time: {:02d}:{:02d}:{:02d}".format(Hour, Minute, Second))
        lcd.putstr("{:02d}:{:02d}:{:02d}".format(Hour, Minute, Second))
        utime.sleep(0.95)


#Set Hour   Button Up = +1 Hour 
#           Button Down= -1 Hour
def input_Hour():
    global Hour, prev_Hour, current_step
    # Variable to save the last time the button was pressed
    last_button_press = utime.ticks_ms()

    while True:
        # Checks whether more than 100 milliseconds have elapsed since the last button was pressed (debouncing)
        if utime.ticks_ms() - last_button_press > 50:
            if Button1.value():
                Hour = (Hour + 1) % 24
            elif Button2.value():
                Hour = (Hour - 1) % 24

            # Check if the value from Hour has changed 
            # than print time over show_time()
            if Hour != prev_Hour:
                show_time_Hour()
                prev_Hour = Hour

             # Hour is Set
            if Button3.value():
                print("Hour is set")
                current_step = "Minute"
                break
            # Update the time of the last button presss
            last_button_press = utime.ticks_ms()
        utime.sleep(0.1)

def input_Minute():
    global Minute, prev_Minute, current_step

    # Variable to save the last time the button was pressed
    last_button_press = utime.ticks_ms()

    while True:
        # Checks whether more than 100 milliseconds have elapsed since the last button was pressed (debouncing)
        if utime.ticks_ms() - last_button_press > 50:
            if Button1.value():
                Minute = (Minute + 1) % 60
            elif Button2.value():
                Minute = (Minute - 1) % 60

            # Checks whether the value of Minute has changed
            if Minute != prev_Minute:
                show_time_Minute()
                prev_Minute = Minute

            # Checks whether the value of Second has changed
            if Button3.value():
                print("Minute is set")
                current_step= "Second"
                break

            # Update the time of the last button press
            last_button_press = utime.ticks_ms()

        utime.sleep(0.1)

def input_Second():
    global Second, prev_Second, current_step

    # Variable to save the last time the button was pressed
    last_button_press = utime.ticks_ms()

    while True:
        # Checks whether more than 100 milliseconds have elapsed since the last button was pressed (debouncing)
        if utime.ticks_ms() - last_button_press > 50:
            if Button1.value():
                Second = (Second + 1) % 60
            elif Button2.value():
                Second = (Second - 1) % 60

            # Checks whether the value of Second has changed
            if Second != prev_Second:
                show_time_Second()
                prev_Second = Second

            # Check whether button3 has been pressed
            if Button3.value():
                print("Second is set")
                current_step= "Show Time"

                 #Pass Input Time into the RTC
                rtc.datetime((2024, 1, 1, 1, Hour, Minute, Second, 0,))

                break

            # Update the time of the last button press
            last_button_press = utime.ticks_ms()

        utime.sleep(0.1)


#--------------------------------------------------------------------------------------------------#

#Set Hour
lcd.putstr("Set Hour")
print("Set Hour (0-23):")
input_Hour()

utime.sleep_ms(100)

#Set Minute
if current_step=="Minute":
    lcd.clear()
    lcd.putstr("Set Minute")
    print("Set Minute (0-59):")
    input_Minute()

utime.sleep_ms(100)

#Set Second
if current_step=="Second":
    lcd.clear()
    lcd.putstr("Set Second")
    print("Set Second (0-59):")
    input_Second()
    

utime.sleep_ms(100)

#Show actual time 
show_current_Time()


I think I need some kind of loop, but all my attempts have failed to this point. Also I'm not sure if its a problem that the function show_current_Time() is a while loop. I implemented this loop to constantly update my LCD display. ChatGPT has helped me well so far, but I am failing at this task.

1

There are 1 best solutions below

0
nekomatic On

To do what you want with the minimum of changes to what you've already got, I would start by taking your while True: loop out of show_current_Time(), so that that function simply updates the display with the current time once. Then in the main body of your program, put the time setting code inside a while loop and add a second while loop inside that to update the time and monitor the button, something like:

while True:
    # time setting code goes here
    
    # inner loop to update display and check the button 
    stored_time = utime.ticks_ms()
    while utime.ticks_ms - stored_time < 3000:
        utime.sleep_ms(200)
        show_current_Time()
        if not Button4.value():
            stored_time = utime.ticks_ms()

So if Button4 is not pressed, stored_time is updated each time round the inner loop, but if you press and hold the button, eventually the difference between ticks_ms() and stored_time will exceed 3 seconds, the inner loop will exit and the outer loop will repeat.

I've changed your sleep to 200 ms here so that your display will update the seconds more smoothly.

A more elegant solution would probably make use of asyncio, which is explained in Peter Hinch's tutorial.