Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RGB emergency - Add support for RGB channel, and use button long press to toggle effect #13

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 46 additions & 11 deletions examples/tiny_fx/examples/showcase/rescue_vehicle.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,42 @@
import time
from tiny_fx import TinyFX
from picofx import MonoPlayer
from picofx import ColourPlayer, MonoPlayer
from picofx.colour import RGBBlinkFX, RED, YELLOW, GREEN, CYAN, BLUE, MAGENTA
from picofx.mono import FlashSequenceFX, StaticFX

"""
Play an alternating flashing sequence on two of TinyFX's outputs,
recreating the effect of rescue vehicle beacons.
and the RGB channel, recreating the effect of rescue vehicle beacons.
The other outputs are static for illuminated head and tail lights.

Press "Boot" to exit the program.
Press "Boot" to exit the program, or long press to toggle RGB effects.
"""

# Constants
EMERGENCY = COLOURS = [RED,RED,RED,RED,BLUE,BLUE,BLUE,BLUE]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EMERGENCY doesn't seem to be used anywhere?

EMERGENCY_BLINK_SPEED = 8
ORANGE = (228,114,28)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps (255, 32, 0)?

HAZARD = [ORANGE]
HAZARD_BLINK_SPEED = 1.8

# Variables
tiny = TinyFX() # Create a new TinyFX object to interact with the board
player = MonoPlayer(tiny.outputs) # Create a new effect player to control TinyFX's mono outputs
player = ColourPlayer(tiny.rgb) # Create a new effect player to control TinyFX's RGB output
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

colour_player for clarity?

monoplayer = MonoPlayer(tiny.outputs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mono_player for readability


# Create and set up an red blue flashing effect to play, and a hazard one for later
rgbEffect = RGBBlinkFX(colour=COLOURS, # The colour (or colours to blink in sequence)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We tend to use snake case for our variable names, rather than camelCase. E.g. rgb_effect

phase=0.0, # The start time in the cycle (0-1)
speed=EMERGENCY_BLINK_SPEED, # The speed to cycle through colours at, with 1.0 being 1 second (1/T)
duty=0.5) # Amount of the cycle to be "on"

hazardEffect = RGBBlinkFX(colour=HAZARD, # The colour (or colours to blink in sequence)
phase=0.0, # The start time in the cycle (0-1)
speed=HAZARD_BLINK_SPEED, # The speed to cycle through colours at, with 1.0 being 1 second (1/T)
duty=0.4) # Amount of the cycle to be "on"

player.effects = [rgbEffect]



# Create a FlashSequenceFX effect for the beacon lights
@@ -27,7 +51,7 @@


# Set up the mono effects to play. The first two are flashing, the rest are static
player.effects = [
monoplayer.effects = [
flashing(0),
flashing(1),
headlights,
@@ -36,16 +60,27 @@
taillights
]

player.pair(monoplayer)

# Wrap the code in a try block, to catch any exceptions (including KeyboardInterrupt)
try:
player.start() # Start the effects running

# Loop until the effect stops or the "Boot" button is pressed
while player.is_running() and not tiny.boot_pressed():
pass

t = 0 # keep track of boot press duration
dont_exit_yet = True
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A simpler name would be running 😉

while dont_exit_yet:
player.start() # Start the effects running
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think start() should be outside of the first while loop. I wonder if repeated calls to it without calling stop first is the cause of your problem 🤔


# Loop until the effect stops or the "Boot" button is pressed
while player.is_running() and not tiny.boot_pressed():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The player is never stopped, so checking is_running() is unnecessary

pass
t = time.ticks_ms()
while player.is_running() and tiny.boot_pressed():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checking is_running() is unnecessary

pass
if time.ticks_ms() - t > 500: # long press - toggle effect
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more robust way to do this check is time.ticks_diff(time.ticks_ms(), t) > 500. See: https://docs.micropython.org/en/latest/library/time.html#time.ticks_diff

Also, from my resting, I found having short press be effect switch, and long press be stop, felt like a better user experience

player.effects = [hazardEffect] if player.effects[0] is rgbEffect else [rgbEffect]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised this worked! player.effects may appear as a list but is actually two functions hidden by properties. As such there may be cases where effects[0] would not equal the effect your originally entered into it.

Perhaps a safer way would be to have a separate mode variable that you use to set the new effect and then toggle for the next time e.g. mode = not mode

else: # short press - exit
dont_exit_yet = False
# Stop any running effects and turn off all the outputs
finally:
player.stop()
tiny.shutdown()