From b0b61d36f919248bb1c2252313dd300d5f008738 Mon Sep 17 00:00:00 2001 From: "Paul (Pololu)" Date: Thu, 2 Mar 2023 21:31:34 -0800 Subject: [PATCH 1/2] micropython demo: default to menu, blink LED smoothly in menu --- micropython_demo/main.py | 2 +- .../extras/splash_loader.py | 42 +++++++++++++++---- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/micropython_demo/main.py b/micropython_demo/main.py index d4c8638..1fa3802 100644 --- a/micropython_demo/main.py +++ b/micropython_demo/main.py @@ -28,7 +28,7 @@ try: from pololu_3pi_2040_robot.extras.splash_loader import splash_loader splash_loader( - default_program = "blink.py", + default_program = None, # "my_program.py" splash_delay_s = 6, # delay while waiting for a button run_file_delay_ms = 700 # extra delay to show the action ) diff --git a/micropython_demo/pololu_3pi_2040_robot/extras/splash_loader.py b/micropython_demo/pololu_3pi_2040_robot/extras/splash_loader.py index f06c653..a3b012e 100644 --- a/micropython_demo/pololu_3pi_2040_robot/extras/splash_loader.py +++ b/micropython_demo/pololu_3pi_2040_robot/extras/splash_loader.py @@ -27,7 +27,7 @@ def splash_loader(*, default_program, splash_delay_s, run_file_delay_ms): buzzer = Buzzer() # turns off buzzer rgb_leds = RGBLEDs() # turns off RGB LEDs rgb_leds.set_brightness(4) - YellowLED() # turns off yellow LED + YellowLED() # turns off the yellow LED def del_vars(): nonlocal display, splash, button_a, button_b, button_c, battery @@ -67,7 +67,11 @@ def initial_screen(): display.blit(splash, 0, offset) display.text('Push C for menu', 0, 68+offset) display.text('Default ({}s):'.format(countdown_s), 0, 78+offset) - display.text(' '+default_program, 0, 88+offset) + + if default_program: + display.text(' '+default_program, 0, 88+offset) + else: + display.text(' menu', 0, 88+offset) display.show() @@ -89,6 +93,7 @@ def initial_screen(): def run_file(filename): rgb_leds.off() + YellowLED() # turns off the LED even from PWM if run_file_delay_ms: display.fill(0) display.text('Run file:', 0, 0) @@ -105,6 +110,7 @@ def run_file(filename): # Runs the bootloader in the RP2040's Bootrom. def run_bootloader(): rgb_leds.off() + YellowLED() # turns off the LED even from PWM if run_file_delay_ms: display.fill(0) display.text('Bootloader...', 0, 0) @@ -121,6 +127,7 @@ def run_bootloader(): # your program or by sending Ctrl+C to the USB virtual serial port. def run_repl(): rgb_leds.off() + YellowLED() # turns off the LED even from PWM if run_file_delay_ms: display.fill(0) display.text('exit to REPL...', 0, 0) @@ -136,6 +143,13 @@ def menu(): from pololu_3pi_2040_robot.extras.menu import Menu import os + from machine import PWM + from math import exp + + pwm = PWM(YellowLED().pin) + pwm.duty_u16(65535) # 100% off + pwm.freq(1000) + start_ms = time.ticks_ms() options = sorted(f for f in os.listdir() if f.endswith(".py") and f != "main.py") options += ["bootloader", "exit to REPL"] @@ -148,16 +162,25 @@ def menu(): menu.next_button = button_c i = None mv = None + while i == None: t = time.ticks_ms() + elapsed_ms = time.ticks_diff(t, start_ms) + + x = (elapsed_ms % 3000 - 1500) / 1500 + b = exp(-x**2/(2*0.2**2)) + pwm.duty_u16(65535 - int(b * 65535)) + if not mv or time.ticks_diff(t, mv_time) > 200: mv = battery.get_level_millivolts() mv_time = t - if time.ticks_diff(t, start_ms) % 4000 < 2000: - menu.top_message = "Run: (^A *B Cv)" + if elapsed_ms % 4000 < 2000: + menu.top_message = 'Run: (^A *B Cv)' else: - menu.top_message = "Battery: {:.2f} V".format(mv/1000) + menu.top_message = f"Battery: {mv/1000:.2f} V" + i = menu.update() + option = options[i] if option == "bootloader": run_bootloader() @@ -176,10 +199,13 @@ def menu(): button = initial_screen() if button == None: - run_file(default_program) - elif button == "C": + if default_program: + run_file(default_program) + else: + menu() + elif button == 'C': menu() - elif button == "B": + elif button == 'B': run_bootloader() else: # A run_repl() From 8c4d2ba4afda1d622fe83baf37abf60aaad2381d Mon Sep 17 00:00:00 2001 From: "Paul (Pololu)" Date: Fri, 3 Mar 2023 16:24:56 -0800 Subject: [PATCH 2/2] micropython: fix yellow led glitch and clean up some items left in the global namespace in main.py --- micropython_demo/main.py | 3 ++ .../extras/splash_loader.py | 28 ++++++++++++------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/micropython_demo/main.py b/micropython_demo/main.py index 1fa3802..7853cb8 100644 --- a/micropython_demo/main.py +++ b/micropython_demo/main.py @@ -60,5 +60,8 @@ from pololu_3pi_2040_robot.rgb_leds import RGBLEDs RGBLEDs() # turn off RGB LEDs + # don't leave extra classes lying around + del Motors, Buzzer, RGBLEDs, splash_loader + # make the REPL friendlier, if you enter it the right way from pololu_3pi_2040_robot import robot diff --git a/micropython_demo/pololu_3pi_2040_robot/extras/splash_loader.py b/micropython_demo/pololu_3pi_2040_robot/extras/splash_loader.py index a3b012e..6912eca 100644 --- a/micropython_demo/pololu_3pi_2040_robot/extras/splash_loader.py +++ b/micropython_demo/pololu_3pi_2040_robot/extras/splash_loader.py @@ -19,6 +19,7 @@ def splash_loader(*, default_program, splash_delay_s, run_file_delay_ms): from pololu_3pi_2040_robot.rgb_leds import RGBLEDs from pololu_3pi_2040_robot.yellow_led import YellowLED import time + from machine import PWM button_a = ButtonA() button_b = ButtonB() @@ -27,13 +28,23 @@ def splash_loader(*, default_program, splash_delay_s, run_file_delay_ms): buzzer = Buzzer() # turns off buzzer rgb_leds = RGBLEDs() # turns off RGB LEDs rgb_leds.set_brightness(4) - YellowLED() # turns off the yellow LED + + # Initialize a PWM on the yellow LED at 0% duty cycle, which + # corresponds to full brightness. We can't initialize PWM with + # the LED off so we'll just have it on for a while. + pwm = PWM(YellowLED().pin) + pwm.freq(1000) + pwm.duty_u16(0) def del_vars(): nonlocal display, splash, button_a, button_b, button_c, battery - nonlocal buzzer, rgb_leds + nonlocal buzzer, rgb_leds, pwm + + pwm.deinit() + YellowLED() # turn off yellow LED and reset to an output + del display, splash, button_a, button_b, button_c, battery - del buzzer, rgb_leds + del buzzer, rgb_leds, pwm def read_button(): if button_a.is_pressed(): return "A" @@ -89,6 +100,7 @@ def initial_screen(): rgb_leds.set(4-i, [0, 0, 0]) rgb_leds.set((4+i)%6, [0, 0, 0]) rgb_leds.show() + return None def run_file(filename): @@ -143,13 +155,8 @@ def menu(): from pololu_3pi_2040_robot.extras.menu import Menu import os - from machine import PWM from math import exp - pwm = PWM(YellowLED().pin) - pwm.duty_u16(65535) # 100% off - pwm.freq(1000) - start_ms = time.ticks_ms() options = sorted(f for f in os.listdir() if f.endswith(".py") and f != "main.py") options += ["bootloader", "exit to REPL"] @@ -167,8 +174,9 @@ def menu(): t = time.ticks_ms() elapsed_ms = time.ticks_diff(t, start_ms) - x = (elapsed_ms % 3000 - 1500) / 1500 - b = exp(-x**2/(2*0.2**2)) + x = ((elapsed_ms + 1500) % 3000 - 1500) / 1500 + b = exp(-12.5*x*x) + pwm.duty_u16(65535 - int(b * 65535)) if not mv or time.ticks_diff(t, mv_time) > 200: