From 14076208d96a44b55e18dd6a71b7e2f134768047 Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Tue, 8 Oct 2024 12:49:39 +0100 Subject: [PATCH] Additional colour and static examples --- examples/tiny_fx/README.md | 27 +++++++++++ .../tiny_fx/examples/effects/colour/blink.py | 35 ++++++++++++++ .../examples/effects/colour/static_hsv.py | 34 +++++++++++++ .../examples/effects/colour/static_rgb.py | 34 +++++++++++++ .../effects/mono/static_brightness.py | 43 +++++++++++++++++ picofx/__init__.py | 30 +++++++++++- picofx/colour/__init__.py | 4 +- picofx/colour/blink.py | 48 +++++++++++++++++++ 8 files changed, 253 insertions(+), 2 deletions(-) create mode 100644 examples/tiny_fx/examples/effects/colour/blink.py create mode 100644 examples/tiny_fx/examples/effects/colour/static_hsv.py create mode 100644 examples/tiny_fx/examples/effects/colour/static_rgb.py create mode 100644 examples/tiny_fx/examples/effects/mono/static_brightness.py create mode 100644 picofx/colour/blink.py diff --git a/examples/tiny_fx/README.md b/examples/tiny_fx/README.md index 138656b..fbbf393 100644 --- a/examples/tiny_fx/README.md +++ b/examples/tiny_fx/README.md @@ -7,6 +7,7 @@ These are micropython examples for the Pimoroni [TinyFX](https://shop.pimoroni.c - [Sensor Meter](#sensor-meter) - [Voltage Meter](#voltage-meter) - [Mono Effect Examples](#mono-effect-examples) + - [Static Brightness](#static-brightness) - [Single Blink](#single-blink) - [Single Flashing](#single-flashing) - [Single Flicker](#single-flicker) @@ -18,6 +19,9 @@ These are micropython examples for the Pimoroni [TinyFX](https://shop.pimoroni.c - [Binary Counter](#binary-counter) - [Traffic Light](#traffic-light) - [Colour Effect Examples](#colour-effect-examples) + - [Static RGB](#static-rgb) + - [Static HSV](#static-hsv) + - [Blink](#blink) - [Rainbow](#rainbow) - [Random](#random) - [Hue Step](#hue-step) @@ -55,6 +59,12 @@ Use TinyFX's mono outputs as a bargraph to show the voltage that is powering the ## Mono Effect Examples +### Static Brightness +[effects/mono/static_brightness.py](examples/effects/mono/static_brightness.py) + +Show a static brightness on one of TinyFX's outputs. + + ### Single Blink [effects/mono/single_blink.py](examples/effects/mono/single_blink.py) @@ -117,6 +127,23 @@ Play a traffic light sequence on TinyFX's outputs. ## Colour Effect Examples +### Static RGB +[effects/colour/static_rgb.py](examples/effects/colour/static_rgb.py) + +Show a static colour on TinyFX's RGB output. + + +### Static HSV +[effects/colour/static_hsv.py](examples/effects/colour/static_hsv.py) + +Show a static colour on TinyFX's RGB output, using HSV. + + +### Blink +[effects/colour/blink.py](examples/effects/colour/blink.py) +Play a blinking sequence effect on TinyFX's RGB output. Each blink in the sequence can be a different colour. + + ### Rainbow [effects/colour/rainbow.py](examples/effects/colour/rainbow.py) diff --git a/examples/tiny_fx/examples/effects/colour/blink.py b/examples/tiny_fx/examples/effects/colour/blink.py new file mode 100644 index 0000000..35da4d0 --- /dev/null +++ b/examples/tiny_fx/examples/effects/colour/blink.py @@ -0,0 +1,35 @@ +from tiny_fx import TinyFX +from picofx import ColourPlayer +from picofx.colour import RGBBlinkFX, RED, YELLOW, GREEN, CYAN, BLUE, MAGENTA + +""" +Play a blinking sequence effect on TinyFX's RGB output. Each blink in the sequence can be a different colour. + +Press "Boot" to exit the program. +""" + +# Constants +COLOURS = [RED, YELLOW, GREEN, CYAN, BLUE, MAGENTA] + +# Variables +tiny = TinyFX() # Create a new TinyFX object to interact with the board +player = ColourPlayer(tiny.rgb) # Create a new effect player to control TinyFX's RGB output + + +# Create and set up a rainbow effect to play +player.effects = RGBBlinkFX(colour=COLOURS, # The colour (or colours to blink in sequence) + speed=0.5) # The speed to cycle through colours at, with 1.0 being 1 second + + +# 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 + +# Stop any running effects and turn off all the outputs +finally: + player.stop() + tiny.shutdown() diff --git a/examples/tiny_fx/examples/effects/colour/static_hsv.py b/examples/tiny_fx/examples/effects/colour/static_hsv.py new file mode 100644 index 0000000..683a4ca --- /dev/null +++ b/examples/tiny_fx/examples/effects/colour/static_hsv.py @@ -0,0 +1,34 @@ +from tiny_fx import TinyFX +from picofx import ColourPlayer +from picofx.colour import HSVFX + +""" +Show a static colour on TinyFX's RGB output, using HSV. + +Press "Boot" to exit the program. +""" + +# Constants +HUE = 0.0 # The colour's hue (from 0.0 to 1.0) +SAT = 1.0 # The colour's saturation (from 0.0 to 1.0) +VAL = 1.0 # The colour's value/brightness (from 0.0 to 1.0) + +# Variables +tiny = TinyFX() # Create a new TinyFX object +player = ColourPlayer(tiny.rgb) # Create a new effect player to control TinyFX's RGB output + +# Set up the colour effect to play +player.effects = HSVFX(HUE, SAT, VAL) + +# 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 + +# Stop any running effects and turn off all the outputs +finally: + player.stop() + tiny.shutdown() diff --git a/examples/tiny_fx/examples/effects/colour/static_rgb.py b/examples/tiny_fx/examples/effects/colour/static_rgb.py new file mode 100644 index 0000000..c8c64f1 --- /dev/null +++ b/examples/tiny_fx/examples/effects/colour/static_rgb.py @@ -0,0 +1,34 @@ +from tiny_fx import TinyFX +from picofx import ColourPlayer +from picofx.colour import RGBFX + +""" +Show a static colour on TinyFX's RGB output. + +Press "Boot" to exit the program. +""" + +# Constants +R = 255 # The amount of red (from 0 to 255) +G = 0 # The amount of green (from 0 to 255) +B = 0 # The amount of blue (from 0 to 255) + +# Variables +tiny = TinyFX() # Create a new TinyFX object +player = ColourPlayer(tiny.rgb) # Create a new effect player to control TinyFX's RGB output + +# Set up the colour effect to play +player.effects = RGBFX(R, G, B) + +# 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 + +# Stop any running effects and turn off all the outputs +finally: + player.stop() + tiny.shutdown() diff --git a/examples/tiny_fx/examples/effects/mono/static_brightness.py b/examples/tiny_fx/examples/effects/mono/static_brightness.py new file mode 100644 index 0000000..2b83b22 --- /dev/null +++ b/examples/tiny_fx/examples/effects/mono/static_brightness.py @@ -0,0 +1,43 @@ +from tiny_fx import TinyFX +from picofx import MonoPlayer +from picofx.mono import StaticFX + +""" +Show a static brightness on one of TinyFX's outputs. + +Press "Boot" to exit the program. +""" + +# Constants +BRIGHTNESS = 1.0 # The brightness (from 0.0 to 1.0) + +# 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 + + +# Create and set up a blink effect to play +player.effects = [ + StaticFX(BRIGHTNESS), + + # No effects played on the rest of the outputs (unnecessary to list, but show for clarity) + None, + None, + None, + None, + None, +] + + +# 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 + +# Stop any running effects and turn off all the outputs +finally: + player.stop() + tiny.shutdown() diff --git a/picofx/__init__.py b/picofx/__init__.py index 2751695..0f56041 100644 --- a/picofx/__init__.py +++ b/picofx/__init__.py @@ -5,7 +5,7 @@ from machine import Pin, PWM, Timer -PICOFX_VERSION = "1.0.0" +PICOFX_VERSION = "1.0.1" def rgb_from_hsv(h, s, v): @@ -96,6 +96,34 @@ def reset(self): self.__offset = 0 +class CyclingAction(Updateable): + def __init__(self, speed): + self.speed = speed + self.__offset_ms = 0 + self.__offset = 0 + + def next(self): + pass + + def prev(self): + pass + + def tick(self, delta_ms): + self.__offset_ms += int(delta_ms * self.speed) + if self.__offset_ms >= 1000: + self.__offset_ms -= 1000 + self.next() + elif self.__offset_ms < 0: + self.__offset_ms += 1000 + self.prev() + + self.__offset = self.__offset_ms / 1000 + + def reset(self): + self.__offset_ms = 0 + self.__offset = 0 + + class EffectPlayer: DEFAULT_FPS = 100 diff --git a/picofx/colour/__init__.py b/picofx/colour/__init__.py index 1370a65..e2e6d03 100644 --- a/picofx/colour/__init__.py +++ b/picofx/colour/__init__.py @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: MIT +from .blink import RGBBlinkFX from .colour import RGBFX, HSVFX from .rainbow import RainbowFX, RainbowWaveFX from .step import HueStepFX @@ -20,5 +21,6 @@ HSVFX, RainbowFX, RainbowWaveFX, - HueStepFX + HueStepFX, + RGBBlinkFX ] diff --git a/picofx/colour/blink.py b/picofx/colour/blink.py new file mode 100644 index 0000000..2688e15 --- /dev/null +++ b/picofx/colour/blink.py @@ -0,0 +1,48 @@ +# SPDX-FileCopyrightText: 2024 Christopher Parrott for Pimoroni Ltd +# +# SPDX-License-Identifier: MIT + +from picofx import CyclingAction + + +# Derived from maltheim's example: https://forums.pimoroni.com/t/rgb-led-kit-for-tiny-fx-tutorial/25293/15 +class RGBBlinkFX(CyclingAction): + """ + Blinks the RGB LED according to the speed, phase and duty cycle. + + The colour argument is a single tuple of the form (R,G,B), or a + list of such tuples. A None colour argument defaults to red. + + :param: colour an RGB tuple as the colour or colours of the blink + :param: speed the speed of the blink, where 1.0 is 1 second, 0.5 is 2 seconds, etc. + :param: phase the phase of the blink + :param: duty the duty cycle of the blink + """ + def __init__(self, colour=None, speed=1, phase=0.0, duty=0.5): + super().__init__(speed) + self.phase = phase + self.duty = duty + self.__colours = [] + self.__index = 0 + if colour is None: + self.__colours.append((255, 0, 0)) + elif isinstance(colour, tuple) and len(colour) == 3: + self.__colours.append(colour) + elif isinstance(colour, list): + self.__colours.extend(colour) + else: + raise TypeError("colour is not a supported type. Expected a tuple of 3 numbers, a list of tuples, or None.") + + def __call__(self): + percent = (self.__offset + self.phase) % 1.0 + if percent < self.duty: + colour = self.__colours[self.__index] + return int(colour[0]), int(colour[1]), int(colour[2]) + else: + return 0, 0, 0 + + def next(self): + self.__index = (self.__index + 1) % len(self.__colours) + + def prev(self): + self.__index = (self.__index - 1) % len(self.__colours)