190 lines
8.7 KiB
Python
190 lines
8.7 KiB
Python
"""
|
|
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 <https://www.gnu.org/licenses/>.
|
|
"""
|
|
|
|
|
|
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()
|