""" uv-belichter-software - the TIMER submenu Copyright (C) 2024 Benjamin Burkhardt This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ from time import sleep, time_ns # All the arguments this method takes are there for one reason: reduce the amount of libraries loaded into the picos memory and thus improving performance # config: utils.Config object # btn_mapping: a dict containing the btn mapping for the menu operation (given to the lcdMenu object) # log: the utils.log function # lcdMenu: the lcdMenu class (not an object of that class!) def run(config, btn_mapping, log, lcdMenu): timer_menu = lcdMenu(config.LCD, btn_mapping, scroll_direction=True, cycle=True, hide_menu_name=False, name="TIMERS") timer_values_original = [config.TIMER_1_DURATION, config.TIMER_2_DURATION, config.TIMER_3_DURATION] timer_values = timer_values_original.copy() # here, the current timers time is stored when interrupting via the interrupt_pin (see below) timer_splits = [lambda: divmod(round(timer_values[0]), 60), lambda: divmod(round(timer_values[1]), 60), lambda: divmod(round(timer_values[2]), 60)] interrupt_pin = config.PIN_IN_BTN_1 # the interrupt btn stops the timer, saves the current time and goes back to the menu reset_pin = config.PIN_IN_BTN_2 # the reset btn restores the default value start_stop_pin = config.PIN_IN_SWITCH # the start_stop switch starts/stops the timer # timer_number is the number of the timer that will be run, starting at 1 # the _timer variable is needed because otherwise python will throw crazy errors regarding "variable accessed before assignment"... # ...just see it as a copy of the timer_number-1'th elemnt of the timer_values list (see above) def run_timer(timer_number: int, _timer: int): config.LCD.clear() config.LCD.putstr(f"Timer {timer_number}".center(16)) last_start_stop_value = start_stop_pin.value() config.PIN_OUT_RELAIS.value(last_start_stop_value) last_time_ns = time_ns() while True: # now run the timer (if the switch is high) config.LCD.move_to(0,1) _timer_div = divmod(round(_timer), 60) config.LCD.putstr(f"{_timer_div[0]:02d}:{_timer_div[1]:02d}".center(16)) if interrupt_pin.value() == 1: timer_values[timer_number-1] = _timer # save the current state last_start_stop_value = 0 # turn the LEDs off! config.PIN_OUT_RELAIS.value(last_start_stop_value) return None if reset_pin.value() == 1: _timer = timer_values_original[timer_number-1] # reset the timers if _timer <= 0: config.PIN_OUT_RELAIS.off() return True sleep(0.05) if last_start_stop_value != (new_value := start_stop_pin.value()): last_start_stop_value = new_value config.PIN_OUT_RELAIS.value(new_value) last_time_ns = time_ns() if start_stop_pin.value() == 1: _timer -= (time_ns() - last_time_ns) / 1000**3 last_time_ns = time_ns() timer_programs = [(f"T1 - {timer_splits[0]()[0]:02d}:{timer_splits[0]()[1]:02d}", lambda: run_timer(1, timer_values[0])), (f"T2 - {timer_splits[1]()[0]:02d}:{timer_splits[1]()[1]:02d}", lambda: run_timer(2, timer_values[1])), (f"T3 - {timer_splits[2]()[0]:02d}:{timer_splits[2]()[1]:02d}", lambda: run_timer(3, timer_values[2])), ("Exit", timer_menu.stop)] timer_menu.setup(timer_programs) # give it the callback list timer_menu.run() return True # disable the "Quitting" message from lcdMenu if __name__ == "__main__": from utils import Config, log from lcdMenu import lcdMenu config = Config() btn_mapping = {"ok_btn": config.PIN_IN_BTN_1, "next_btn": config.PIN_IN_BTN_2} # the btn mapping for all lcdMenus run(Config(), btn_mapping, log, lcdMenu)