""" uv-belichter-software - The main program run at the Pi Picos startup 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 . """ import utils from lcdMenu import lcdMenu from WelcomeScreen import WelcomeScreen from time import sleep, time_ns from gc import collect # garbage collector for better memory performance config = utils.Config() btn_mapping = {"ok_btn": config.PIN_IN_BTN_1, "next_btn": config.PIN_IN_BTN_2} # the btn mapping for all lcdMenus # extra functions to access the garbage collector def manual(): config.LCD.clear() set_value = config.PIN_OUT_RELAIS.value() config.LCD.putstr(f"---- MANUAL ---- State: {set_value} ") while True: if set_value != config.PIN_IN_SWITCH.value(): config.PIN_OUT_RELAIS.value(config.PIN_IN_SWITCH.value()) set_value = config.PIN_OUT_RELAIS.value() config.LCD.putstr(f"---- MANUAL ---- State: {set_value} ") if config.PIN_IN_BTN_1.value() == 1 or config.PIN_IN_BTN_2.value() == 1: return True # exit on press of these buttons; True to disable the Quitting message from lcdMenu def timer(): timer_menu = lcdMenu(config.LCD, btn_mapping, scroll_direction=True, cycle=True, hide_menu_name=False, name="TIMERS") timer_values = [config.TIMER_1_DURATION, config.TIMER_2_DURATION, config.TIMER_3_DURATION] timer_splits = [lambda: divmod(round(timer_values[0]), 60), lambda: divmod(round(timer_values[1]), 60), lambda: divmod(round(timer_values[2]), 60)] def run_timer(timer_number: int, _timer: int): interrupt_pin = config.PIN_IN_BTN_1 reset_pin = config.PIN_IN_BTN_2 start_stop_pin = config.PIN_IN_SWITCH original = _timer 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: 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 = original # 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"{timer_splits[0]()[0]:02d}:{timer_splits[0]()[1]:02d}", lambda: run_timer(1, timer_values[0])), (f"{timer_splits[1]()[0]:02d}:{timer_splits[1]()[1]:02d}", lambda: run_timer(2, timer_values[1])), (f"{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() del timer_menu, timer_programs collect() return True # disable the "Quitting" message from lcdMenu def uv_on(): config.PIN_OUT_RELAIS.value(1) config.LCD.clear() config.LCD.putstr("------ UV ------ turned on ") sleep(1) return True # disable the "Quitting" message from lcdMenu def uv_off(): config.PIN_OUT_RELAIS.value(0) config.LCD.clear() config.LCD.putstr("------ UV ------ turned off ") sleep(1) return True # disable the "Quitting" message from lcdMenu def lcd_big_hello(): import lcd_big_hello as lbh lbh.run(config.LCD) del lbh collect() return True def input_tests(): import input_tests as input_tests input_tests.run(serial_output=False) collect() return True def settings(): settings_menu = lcdMenu(config.LCD, btn_mapping, scroll_direction=True, cycle=True, hide_menu_name=False, name="SETTINGS") def swap_welcome(): config.STARTUP_WELCOME_SHOW = not config.STARTUP_WELCOME_SHOW config.LCD.clear() config.LCD.putstr(f" Welcome Screen ") if config.STARTUP_WELCOME_SHOW: config.LCD.putstr("--- Enabled! ---") else: config.LCD.putstr("--- Disabled ---") sleep(1) def welcome_cycles(): config.LCD.clear() current_cycles = config.STARTUP_WELCOME_CYCLES option_down = [" ", "v"][current_cycles>1] config.LCD.putstr(f" Cycles \n{option_down} {str(current_cycles).center(12)} ^") while True: if config.PIN_IN_BTN_1.value() == 1: time_ns_when_pressed = time_ns() while config.PIN_IN_BTN_1.value() == 1: if (time_ns() - time_ns_when_pressed) > 1000000000: # if the time passed is longer than a second while config.PIN_IN_BTN_1.value() == 1: pass # wait till release config.STARTUP_WELCOME_CYCLES = current_cycles return True sleep(0.05) current_cycles -= 1 if current_cycles < 1: current_cycles = 1 option_down = [" ", "v"][current_cycles>1] config.LCD.putstr(f" Cycles \n{option_down} {str(current_cycles).center(12)} ^") if config.PIN_IN_BTN_2.value() == 1: time_ns_when_pressed = time_ns() while config.PIN_IN_BTN_2.value() == 1: if (time_ns() - time_ns_when_pressed) > 1000000000: # if the time passed is longer than a second while config.PIN_IN_BTN_2.value() == 1: pass # wait till release config.STARTUP_WELCOME_CYCLES = current_cycles return True sleep(0.05) current_cycles += 1 option_down = [" ", "v"][current_cycles>1] config.LCD.putstr(f" Cycles \n{option_down} {str(current_cycles).center(12)} ^") settings_programs = [("Show welcome", swap_welcome), ("Welcome cycles", welcome_cycles), ("Exit", settings_menu.stop)] settings_menu.setup(settings_programs) # give it the callback list settings_menu.run() # run the menu until it's closed del settings_menu, settings_programs collect() return True def run_demo_menu(): demo_menu = lcdMenu(config.LCD, btn_mapping, scroll_direction=True, cycle=True, hide_menu_name=False, name="DEMOS") demo_programs = [("LCD Demo", lcd_big_hello), ("Input tests", input_tests), ("Exit", demo_menu.stop)] demo_menu.setup(demo_programs) # give it the callback list ret = demo_menu.run() del demo_menu, demo_programs collect() return ret if config.STARTUP_WELCOME_SHOW: ws = WelcomeScreen(config.LCD, interrupt_pins=[config.PIN_IN_BTN_1, config.PIN_IN_BTN_2, config.PIN_IN_SWITCH], subtitle=config.STARTUP_PROJECT_NAME, starting_msg=config.STARTUP_MESSAGE_STARTING, started_msg=config.STARTUP_MESSAGE_FINISHED) ws.show(cycles=config.STARTUP_WELCOME_CYCLES) del ws collect() # create the menus main_menu = lcdMenu(config.LCD, btn_mapping, scroll_direction=True, cycle=True, hide_menu_name=False, name="PROGRAMS") main_programs = [("Timer", timer), ("Manual", manual), ("UV off", uv_off), ("UV on", uv_on), ("Demos", run_demo_menu), ("Settings", settings)] main_menu.setup(main_programs) # give it the callback list # and run the main menu (will be an endless loop) main_menu.run()