From dd6d0a23ea5262fa98e224744e01623f1c804d48 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Tue, 4 Oct 2022 19:17:09 +0100 Subject: [PATCH 01/23] add examples --- .../examples/plasma_stick/cheerlights.py | 79 ++++++ micropython/examples/plasma_stick/encoder.py | 81 ++++++ .../examples/plasma_stick/thermometer.py | 47 ++++ micropython/examples/plasma_stick/weather.py | 237 ++++++++++++++++++ 4 files changed, 444 insertions(+) create mode 100644 micropython/examples/plasma_stick/cheerlights.py create mode 100644 micropython/examples/plasma_stick/encoder.py create mode 100644 micropython/examples/plasma_stick/thermometer.py create mode 100644 micropython/examples/plasma_stick/weather.py diff --git a/micropython/examples/plasma_stick/cheerlights.py b/micropython/examples/plasma_stick/cheerlights.py new file mode 100644 index 00000000..b25183e5 --- /dev/null +++ b/micropython/examples/plasma_stick/cheerlights.py @@ -0,0 +1,79 @@ +import WIFI_CONFIG +from network_manager import NetworkManager +import uasyncio +from urequests import get +import time +import ujson +import plasma +from plasma import plasma2040 + +""" +This Plasma Stick example sets your LED strip to the current #cheerlights colour. +Find out more about the Cheerlights API at https://cheerlights.com/ +""" + +URL = 'http://api.thingspeak.com/channels/1417/field/2/last.json' +UPDATE_INTERVAL = 120 # refresh interval in secs. Be nice to free APIs! + +# Set how many LEDs you have +NUM_LEDS = 50 + + +def status_handler(mode, status, ip): + # reports wifi connection status + print(mode, status, ip) + print('Connecting to wifi...') + # flash while connecting + for i in range(NUM_LEDS): + led_strip.set_rgb(i, 255, 255, 255) + time.sleep(0.02) + for i in range(NUM_LEDS): + led_strip.set_rgb(i, 0, 0, 0) + if status is not None: + if status: + print('Connection successful!') + else: + print('Connection failed!') + # light up red if connection fails + for i in range(NUM_LEDS): + led_strip.set_rgb(i, 255, 0, 0) + + +def hex_to_rgb(hex): + # converts a hex colour code into RGB + h = hex.lstrip('#') + r, g, b = (int(h[i:i + 2], 16) for i in (0, 2, 4)) + return r, g, b + + +# set up the WS2812 / NeoPixel™ LEDs +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) + +# start updating the LED strip +led_strip.start() + +# set up wifi +network_manager = NetworkManager(WIFI_CONFIG.COUNTRY, status_handler=status_handler) +uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK)) + +while True: + # open the json file + print(f"Requesting URL: {URL}") + data = get(URL).json() + print("Data obtained!") + + # extract hex colour from the data + hex = data['field2'] + + # and convert it to RGB + r, g, b = hex_to_rgb(hex) + + # light up the LEDs + for i in range(NUM_LEDS): + led_strip.set_rgb(i, r, g, b) + print(f"LEDs set to {hex}") + + # sleep + print(f"""Sleeping for {UPDATE_INTERVAL} seconds. + """) + time.sleep(UPDATE_INTERVAL) \ No newline at end of file diff --git a/micropython/examples/plasma_stick/encoder.py b/micropython/examples/plasma_stick/encoder.py new file mode 100644 index 00000000..00552c8e --- /dev/null +++ b/micropython/examples/plasma_stick/encoder.py @@ -0,0 +1,81 @@ +from pimoroni_i2c import PimoroniI2C +from breakout_encoder import BreakoutEncoder +import plasma +from plasma import plasma2040 + +""" +Change the colour of your LEDs easily by hooking up an RGB Encoder Breakout! +""" + +# set how many LEDs you have +NUM_LEDS = 50 + +# make this number bigger for more precise colour adjustments +STEPS_PER_REV = 24 + +PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5} + +i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN) +enc = BreakoutEncoder(i2c) + +enc.set_brightness(1.0) +# enc.set_direction(BreakoutEncoder.DIRECTION_CCW) # Uncomment this to flip the direction + + +def hsv_to_rgb(h, s, v): + # From CPython Lib/colorsys.py + if s == 0.0: + return v, v, v + i = int(h * 6.0) + f = (h * 6.0) - i + p = v * (1.0 - s) + q = v * (1.0 - s * f) + t = v * (1.0 - s * (1.0 - f)) + i = i % 6 + if i == 0: + return v, t, p + if i == 1: + return q, v, p + if i == 2: + return p, v, t + if i == 3: + return p, q, v + if i == 4: + return t, p, v + if i == 5: + return v, p, q + + +def count_changed(count): + print("Count: ", count, sep="") + h = ((count % STEPS_PER_REV) * 360.0) / STEPS_PER_REV # Convert the count to a colour hue + r, g, b = [int(255 * c) for c in hsv_to_rgb(h / 360.0, 1.0, 1.0)] # rainbow magic + # set the encoder LED colour + enc.set_led(r, g, b) + # set the led strip to match + for i in range(NUM_LEDS): + led_strip.set_rgb(i, r, g, b) + + +# WS2812 / NeoPixel™ LEDs +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) + +# Start updating the LED strip +led_strip.start() + +count = 0 + +count_changed(count) + +enc.clear_interrupt_flag() + +while True: + if enc.get_interrupt_flag(): + count = enc.read() + enc.clear_interrupt_flag() + + while count < 0: + count += STEPS_PER_REV + + count_changed(count) + \ No newline at end of file diff --git a/micropython/examples/plasma_stick/thermometer.py b/micropython/examples/plasma_stick/thermometer.py new file mode 100644 index 00000000..18287144 --- /dev/null +++ b/micropython/examples/plasma_stick/thermometer.py @@ -0,0 +1,47 @@ +import plasma +from plasma import plasma2040 +from pimoroni import RGBLED +from pimoroni_i2c import PimoroniI2C +import machine +import time + +""" +Reads the internal temperature sensor on the Pico and changes the LED strip an appropriate colour. +""" + +# Set how many LEDs you have +NUM_LEDS = 50 + +BRIGHTNESS = 1.0 + +MIN = 15 +MAX = 30 + +# What you want your MIN colour to be - a hue between 0 and 360 degrees. +# Green is 120! +START_HUE = 120 + +# WS2812 / NeoPixel™ LEDs +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT, rgbw=False) + +# Start updating the LED strip +led_strip.start() + +sensor_temp = machine.ADC(4) +conversion_factor = 3.3 / (65535) # used for calculating a temperature from the raw sensor reading + +while True: + + # the following two lines do some maths to convert the number from the temp sensor into celsius + reading = sensor_temp.read_u16() * conversion_factor + temperature = 27 - (reading - 0.706) / 0.001721 + print(f""" + Temperature: {temperature:0.2f} * C + """) + + # calculates a colour + hue = max(0, START_HUE / 360 * (1 - (temperature - MIN) / MAX)) + for i in range(NUM_LEDS): + led_strip.set_hsv(i, hue, 1.0, BRIGHTNESS) + + time.sleep(0.5) diff --git a/micropython/examples/plasma_stick/weather.py b/micropython/examples/plasma_stick/weather.py new file mode 100644 index 00000000..e8b9f96e --- /dev/null +++ b/micropython/examples/plasma_stick/weather.py @@ -0,0 +1,237 @@ +import WIFI_CONFIG +from network_manager import NetworkManager +import uasyncio +from urequests import get +import time +import ujson +import plasma +from plasma import plasma2040 +# Random functions! randrange is for picking integers from a range, and uniform is for floats. +from random import randrange, uniform +from machine import Timer +import gc + +""" +Weather in a bottle! +This Plasma Stick example connects to Open Meteo to access the current weather conditions. +It then does some cool weather appropriate stuff with LEDs. +Find out more about the Open Meteo API at https://open-meteo.com +Based on original code by AxWax <3 https://github.com/axwax/Open-Meteo-Inky-Pack +""" + +# Set how many LEDs you have +NUM_LEDS = 50 + +# Set your latitude/longitude here (find yours by right clicking in Google Maps!) +LAT = 53.38609085276884 +LNG = -1.4239983439328177 +TIMEZONE = "auto" # determines time zone from lat/long + +URL = "https://api.open-meteo.com/v1/forecast?latitude=" + str(LAT) + "&longitude=" + str(LNG) + "¤t_weather=true&timezone=" + TIMEZONE +UPDATE_INTERVAL = 500 # refresh interval in secs. Be nice to free APIs! + +# Weather codes from https://open-meteo.com/en/docs#:~:text=WMO%20Weather%20interpretation%20codes%20(WW) +WEATHERCODES = { + 0: 'clear sky', + 1: 'mostly clear', + 2: 'partly cloudy', + 3: 'cloudy', + 45: 'fog and depositing rime', + 48: 'fog', + 51: 'light drizzle', + 53: 'moderate drizzle', + 55: 'dense drizzle', + 56: 'light freezing drizzle', + 57: 'dense freezing drizzle', + 61: 'slight rain', + 63: 'moderate rain', + 65: 'heavy rain', + 66: 'light freezing rain', + 67: 'heavy freezing rain', + 71: 'slight snow', + 73: 'moderate snow', + 75: 'heavy snow', + 77: 'snow grains', + 80: 'slight rain showers', + 81: 'moderate rain showers', + 82: 'violent rain showers', + 85: 'slight snow showers', + 86: 'heavy snow showers', + 95: 'thunderstorm', + 96: 'thunderstorm with slight hail', + 99: 'thunderstorm with heavy hail' +} + + +def status_handler(mode, status, ip): + # reports wifi connection status + print(mode, status, ip) + print('Connecting to wifi...') + # flash while connecting + for i in range(NUM_LEDS): + led_strip.set_rgb(i, 255, 255, 255) + time.sleep(0.02) + for i in range(NUM_LEDS): + led_strip.set_rgb(i, 0, 0, 0) + if status is not None: + if status: + print('Connection successful!') + else: + print('Connection failed!') + # light up red if connection fails + for i in range(NUM_LEDS): + led_strip.set_rgb(i, 255, 0, 0) + +def get_data(): + global weathercode + # open the json file + print(f"Requesting URL: {URL}") + j = get(URL).json() + print("Data obtained!") + + # parse relevant data from JSON + current= j["current_weather"] + temperature = current["temperature"] + weathercode = current["weathercode"] + datetime_arr = current["time"].split("T") + + print(f""" + Temperature = {temperature}°C + Conditions = {WEATHERCODES[weathercode]} + Last Open-Meteo update: {datetime_arr[0]}, {datetime_arr[1]} + """) + + gc.collect() + +# the rest of our functions are for animations! +def display_current(): + # paint our current LED colours to the strip + for i in range(NUM_LEDS): + led_strip.set_rgb(i, current_leds[i][0], current_leds[i][1], current_leds[i][2]) + +def move_to_target(): + # nudge our current colours closer to the target colours + for i in range(NUM_LEDS): + for c in range(3): # 3 times, for R, G & B channels + if current_leds[i][c] < target_leds[i][c]: + current_leds[i][c] = min(current_leds[i][c] + ANIMATION_SPEED, target_leds[i][c]) # increase current, up to a maximum of target + elif current_leds[i][c] > target_leds[i][c]: + current_leds[i][c] = max(current_leds[i][c] - ANIMATION_SPEED, target_leds[i][c]) # reduce current, down to a minimum of target + +def clear(): + # nice sunny yellow + for i in range(NUM_LEDS): + target_leds[i] = [242, 237,80] + +def clouds(): + # base colours: + if weathercode == 2: + cloud_colour = [165, 168, 138] # partly cloudy + if weathercode == 3: + cloud_colour = [93, 94, 83] # cloudy + if weathercode in (45, 48): + cloud_colour = [186, 185, 182] # foggy + + # add highlights and lowlights + for i in range(NUM_LEDS): + if uniform(0, 1) < 0.001: # highlight + target_leds[i] = [x+20 for x in cloud_colour] + elif uniform(0, 1) < 0.001: # lowlight + target_leds[i] = [x-20 for x in cloud_colour] + elif uniform(0, 1) < 0.005: # normal + target_leds[i] = cloud_colour + +def storm(): + # heavy rain, with lightning! + raindrop_chance = 0.01 + + for i in range(NUM_LEDS): + if raindrop_chance > uniform(0, 1): + # paint a raindrop (use current rather than target, for an abrupt change to the drop colour) + current_leds[i] = [randrange(0, 50), randrange(20, 100), randrange(50, 255)] + else: + # paint backdrop + target_leds[i] = [0, 15, 60] + + lightning_chance = 0.001 + if lightning_chance > uniform(0, 1): + for i in range(NUM_LEDS): + current_leds[i] = [255, 255, 255] + +def rain(): + # splodgy blues + # first, work out how many raindrops: + if weathercode in (51, 56, 61, 66, 80): # light rain + raindrop_chance = 0.001 + elif weathercode in (53, 63, 81): #moderate rain + raindrop_chance = 0.005 + else: #heavy rain + raindrop_chance = 0.01 + + for i in range(NUM_LEDS): + if raindrop_chance > uniform(0,1): + # paint a raindrop (use current rather than target, for an abrupt change to the drop colour) + current_leds[i] = [randrange(0, 50), randrange(20, 100), randrange(50, 255)] + else: + # paint backdrop + target_leds[i] = [0, 15, 60] + +def snow(): + # splodgy whites + # first, work out how many snowflakes: + if weathercode in (71, 85): # light snow + snowflake_chance = 0.001 + elif weathercode in (73, 77): # moderate snow + snowflake_chance = 0.005 + else: #heavy snow + snowflake_chance = 0.01 + + for i in range(NUM_LEDS): + if snowflake_chance > uniform(0, 1): + # paint a snowflake (use current rather than target, for an abrupt change to the drop colour) + current_leds[i] = [227, 227, 227] + else: + # paint backdrop + target_leds[i] = [54, 54, 54] + +# some variables we'll use for animations +ANIMATION_SPEED = 2 # higher number gets from current to target colour faster + +current_leds = [ [0] * 3 for i in range(NUM_LEDS)] # Create an list of [r, g, b] values that will hold current LED colours, for display +target_leds = [ [0] * 3 for i in range(NUM_LEDS)] # Create an list of [r, g, b] values that will hold target LED colours, to move towards + +# set up the WS2812 / NeoPixel™ LEDs +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) + +# start updating the LED strip +led_strip.start() + +# set up wifi +network_manager = NetworkManager(WIFI_CONFIG.COUNTRY, status_handler=status_handler) +uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK)) + +# get the first lot of data +get_data() + +# start timer (the timer will update our data every UPDATE_INTERVAL) +timer = Timer(-1) +timer.init(period=UPDATE_INTERVAL*1000, mode=Timer.PERIODIC, callback=lambda t:get_data()) + +while True: + # do some fancy stuff with the LEDs based on the weather code + if 0 <= weathercode <= 1: + clear() + elif 2 <= weathercode <= 48: + clouds() + elif 51 <= weathercode <= 67 or 80 <= weathercode <= 82: + rain() + elif 71 <= weathercode <= 77 or 85 <= weathercode <= 86: + snow() + elif 95 <= weathercode <= 99: + storm() + else: + print("Unknown weather code :(") + + move_to_target() # nudge our current colours closer to the target colours + display_current() # display current colours to strip + \ No newline at end of file From 9653dcaabd613f8fe4efc75fa3863f75add07969 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Wed, 5 Oct 2022 12:17:00 +0100 Subject: [PATCH 02/23] linting --- .../examples/plasma_stick/cheerlights.py | 16 +-- micropython/examples/plasma_stick/encoder.py | 1 - .../examples/plasma_stick/thermometer.py | 47 -------- micropython/examples/plasma_stick/weather.py | 100 ++++++++++-------- 4 files changed, 66 insertions(+), 98 deletions(-) delete mode 100644 micropython/examples/plasma_stick/thermometer.py diff --git a/micropython/examples/plasma_stick/cheerlights.py b/micropython/examples/plasma_stick/cheerlights.py index b25183e5..ff0cc1ae 100644 --- a/micropython/examples/plasma_stick/cheerlights.py +++ b/micropython/examples/plasma_stick/cheerlights.py @@ -1,9 +1,8 @@ import WIFI_CONFIG from network_manager import NetworkManager import uasyncio -from urequests import get +import urequests import time -import ujson import plasma from plasma import plasma2040 @@ -37,7 +36,7 @@ def status_handler(mode, status, ip): # light up red if connection fails for i in range(NUM_LEDS): led_strip.set_rgb(i, 255, 0, 0) - + def hex_to_rgb(hex): # converts a hex colour code into RGB @@ -59,15 +58,18 @@ uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG. while True: # open the json file print(f"Requesting URL: {URL}") - data = get(URL).json() + r = urequests.get(URL) + # open the json data + j = r.json() print("Data obtained!") + r.close() # extract hex colour from the data - hex = data['field2'] + hex = j["field2"] # and convert it to RGB r, g, b = hex_to_rgb(hex) - + # light up the LEDs for i in range(NUM_LEDS): led_strip.set_rgb(i, r, g, b) @@ -76,4 +78,4 @@ while True: # sleep print(f"""Sleeping for {UPDATE_INTERVAL} seconds. """) - time.sleep(UPDATE_INTERVAL) \ No newline at end of file + time.sleep(UPDATE_INTERVAL) diff --git a/micropython/examples/plasma_stick/encoder.py b/micropython/examples/plasma_stick/encoder.py index 00552c8e..ad1b4dbf 100644 --- a/micropython/examples/plasma_stick/encoder.py +++ b/micropython/examples/plasma_stick/encoder.py @@ -78,4 +78,3 @@ while True: count += STEPS_PER_REV count_changed(count) - \ No newline at end of file diff --git a/micropython/examples/plasma_stick/thermometer.py b/micropython/examples/plasma_stick/thermometer.py deleted file mode 100644 index 18287144..00000000 --- a/micropython/examples/plasma_stick/thermometer.py +++ /dev/null @@ -1,47 +0,0 @@ -import plasma -from plasma import plasma2040 -from pimoroni import RGBLED -from pimoroni_i2c import PimoroniI2C -import machine -import time - -""" -Reads the internal temperature sensor on the Pico and changes the LED strip an appropriate colour. -""" - -# Set how many LEDs you have -NUM_LEDS = 50 - -BRIGHTNESS = 1.0 - -MIN = 15 -MAX = 30 - -# What you want your MIN colour to be - a hue between 0 and 360 degrees. -# Green is 120! -START_HUE = 120 - -# WS2812 / NeoPixel™ LEDs -led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT, rgbw=False) - -# Start updating the LED strip -led_strip.start() - -sensor_temp = machine.ADC(4) -conversion_factor = 3.3 / (65535) # used for calculating a temperature from the raw sensor reading - -while True: - - # the following two lines do some maths to convert the number from the temp sensor into celsius - reading = sensor_temp.read_u16() * conversion_factor - temperature = 27 - (reading - 0.706) / 0.001721 - print(f""" - Temperature: {temperature:0.2f} * C - """) - - # calculates a colour - hue = max(0, START_HUE / 360 * (1 - (temperature - MIN) / MAX)) - for i in range(NUM_LEDS): - led_strip.set_hsv(i, hue, 1.0, BRIGHTNESS) - - time.sleep(0.5) diff --git a/micropython/examples/plasma_stick/weather.py b/micropython/examples/plasma_stick/weather.py index e8b9f96e..753dedef 100644 --- a/micropython/examples/plasma_stick/weather.py +++ b/micropython/examples/plasma_stick/weather.py @@ -1,9 +1,8 @@ import WIFI_CONFIG from network_manager import NetworkManager import uasyncio -from urequests import get +import urequests import time -import ujson import plasma from plasma import plasma2040 # Random functions! randrange is for picking integers from a range, and uniform is for floats. @@ -28,7 +27,7 @@ LNG = -1.4239983439328177 TIMEZONE = "auto" # determines time zone from lat/long URL = "https://api.open-meteo.com/v1/forecast?latitude=" + str(LAT) + "&longitude=" + str(LNG) + "¤t_weather=true&timezone=" + TIMEZONE -UPDATE_INTERVAL = 500 # refresh interval in secs. Be nice to free APIs! +UPDATE_INTERVAL = 300 # refresh interval in secs. Be nice to free APIs! # Weather codes from https://open-meteo.com/en/docs#:~:text=WMO%20Weather%20interpretation%20codes%20(WW) WEATHERCODES = { @@ -82,54 +81,60 @@ def status_handler(mode, status, ip): for i in range(NUM_LEDS): led_strip.set_rgb(i, 255, 0, 0) + def get_data(): global weathercode - # open the json file print(f"Requesting URL: {URL}") - j = get(URL).json() + r = urequests.get(URL) + # open the json data + j = r.json() print("Data obtained!") - + r.close() + gc.collect() # protecc the RAM + # parse relevant data from JSON - current= j["current_weather"] + current = j["current_weather"] temperature = current["temperature"] weathercode = current["weathercode"] datetime_arr = current["time"].split("T") - + print(f""" Temperature = {temperature}°C Conditions = {WEATHERCODES[weathercode]} Last Open-Meteo update: {datetime_arr[0]}, {datetime_arr[1]} """) - - gc.collect() + # the rest of our functions are for animations! def display_current(): # paint our current LED colours to the strip for i in range(NUM_LEDS): led_strip.set_rgb(i, current_leds[i][0], current_leds[i][1], current_leds[i][2]) - + + def move_to_target(): - # nudge our current colours closer to the target colours + # nudge our current colours closer to the target colours for i in range(NUM_LEDS): - for c in range(3): # 3 times, for R, G & B channels + for c in range(3): # 3 times, for R, G & B channels if current_leds[i][c] < target_leds[i][c]: - current_leds[i][c] = min(current_leds[i][c] + ANIMATION_SPEED, target_leds[i][c]) # increase current, up to a maximum of target + current_leds[i][c] = min(current_leds[i][c] + ANIMATION_SPEED, target_leds[i][c]) # increase current, up to a maximum of target elif current_leds[i][c] > target_leds[i][c]: - current_leds[i][c] = max(current_leds[i][c] - ANIMATION_SPEED, target_leds[i][c]) # reduce current, down to a minimum of target - + current_leds[i][c] = max(current_leds[i][c] - ANIMATION_SPEED, target_leds[i][c]) # reduce current, down to a minimum of target + + def clear(): # nice sunny yellow for i in range(NUM_LEDS): - target_leds[i] = [242, 237,80] - + target_leds[i] = [242, 237, 80] + + def clouds(): # base colours: - if weathercode == 2: + if weathercode == 2: cloud_colour = [165, 168, 138] # partly cloudy - if weathercode == 3: + if weathercode == 3: cloud_colour = [93, 94, 83] # cloudy - if weathercode in (45, 48): + if weathercode in (45, 48): cloud_colour = [186, 185, 182] # foggy # add highlights and lowlights @@ -137,14 +142,15 @@ def clouds(): if uniform(0, 1) < 0.001: # highlight target_leds[i] = [x+20 for x in cloud_colour] elif uniform(0, 1) < 0.001: # lowlight - target_leds[i] = [x-20 for x in cloud_colour] + target_leds[i] = [x-20 for x in cloud_colour] elif uniform(0, 1) < 0.005: # normal target_leds[i] = cloud_colour - + + def storm(): # heavy rain, with lightning! raindrop_chance = 0.01 - + for i in range(NUM_LEDS): if raindrop_chance > uniform(0, 1): # paint a raindrop (use current rather than target, for an abrupt change to the drop colour) @@ -152,40 +158,44 @@ def storm(): else: # paint backdrop target_leds[i] = [0, 15, 60] - + lightning_chance = 0.001 if lightning_chance > uniform(0, 1): for i in range(NUM_LEDS): current_leds[i] = [255, 255, 255] + def rain(): # splodgy blues # first, work out how many raindrops: if weathercode in (51, 56, 61, 66, 80): # light rain raindrop_chance = 0.001 - elif weathercode in (53, 63, 81): #moderate rain + elif weathercode in (53, 63, 81): # moderate rain raindrop_chance = 0.005 - else: #heavy rain + else: + # heavy rain raindrop_chance = 0.01 - + for i in range(NUM_LEDS): - if raindrop_chance > uniform(0,1): + if raindrop_chance > uniform(0, 1): # paint a raindrop (use current rather than target, for an abrupt change to the drop colour) current_leds[i] = [randrange(0, 50), randrange(20, 100), randrange(50, 255)] else: # paint backdrop target_leds[i] = [0, 15, 60] - + + def snow(): # splodgy whites # first, work out how many snowflakes: if weathercode in (71, 85): # light snow snowflake_chance = 0.001 - elif weathercode in (73, 77): # moderate snow - snowflake_chance = 0.005 - else: #heavy snow + elif weathercode in (73, 77): # moderate snow + snowflake_chance = 0.005 + else: + # heavy snow snowflake_chance = 0.01 - + for i in range(NUM_LEDS): if snowflake_chance > uniform(0, 1): # paint a snowflake (use current rather than target, for an abrupt change to the drop colour) @@ -193,12 +203,15 @@ def snow(): else: # paint backdrop target_leds[i] = [54, 54, 54] - + + # some variables we'll use for animations ANIMATION_SPEED = 2 # higher number gets from current to target colour faster -current_leds = [ [0] * 3 for i in range(NUM_LEDS)] # Create an list of [r, g, b] values that will hold current LED colours, for display -target_leds = [ [0] * 3 for i in range(NUM_LEDS)] # Create an list of [r, g, b] values that will hold target LED colours, to move towards +# Create an list of [r, g, b] values that will hold current LED colours, for display +current_leds = [[0] * 3 for i in range(NUM_LEDS)] +# Create an list of [r, g, b] values that will hold target LED colours, to move towards +target_leds = [[0] * 3 for i in range(NUM_LEDS)] # set up the WS2812 / NeoPixel™ LEDs led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) @@ -215,15 +228,15 @@ get_data() # start timer (the timer will update our data every UPDATE_INTERVAL) timer = Timer(-1) -timer.init(period=UPDATE_INTERVAL*1000, mode=Timer.PERIODIC, callback=lambda t:get_data()) +timer.init(period=UPDATE_INTERVAL*1000, mode=Timer.PERIODIC, callback=lambda t: get_data()) while True: # do some fancy stuff with the LEDs based on the weather code - if 0 <= weathercode <= 1: + if 0 <= weathercode <= 1: clear() - elif 2 <= weathercode <= 48: + elif 2 <= weathercode <= 48: clouds() - elif 51 <= weathercode <= 67 or 80 <= weathercode <= 82: + elif 51 <= weathercode <= 67 or 80 <= weathercode <= 82: rain() elif 71 <= weathercode <= 77 or 85 <= weathercode <= 86: snow() @@ -231,7 +244,8 @@ while True: storm() else: print("Unknown weather code :(") - + move_to_target() # nudge our current colours closer to the target colours display_current() # display current colours to strip - \ No newline at end of file + + gc.collect() # try and conserve RAM From 283986b53185eab0bb8a12d9feaf6427619f8807 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Wed, 5 Oct 2022 12:20:20 +0100 Subject: [PATCH 03/23] more weather linting --- micropython/examples/plasma_stick/weather.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/micropython/examples/plasma_stick/weather.py b/micropython/examples/plasma_stick/weather.py index 753dedef..5d985c46 100644 --- a/micropython/examples/plasma_stick/weather.py +++ b/micropython/examples/plasma_stick/weather.py @@ -140,9 +140,9 @@ def clouds(): # add highlights and lowlights for i in range(NUM_LEDS): if uniform(0, 1) < 0.001: # highlight - target_leds[i] = [x+20 for x in cloud_colour] + target_leds[i] = [x + 20 for x in cloud_colour] elif uniform(0, 1) < 0.001: # lowlight - target_leds[i] = [x-20 for x in cloud_colour] + target_leds[i] = [x - 20 for x in cloud_colour] elif uniform(0, 1) < 0.005: # normal target_leds[i] = cloud_colour @@ -228,7 +228,7 @@ get_data() # start timer (the timer will update our data every UPDATE_INTERVAL) timer = Timer(-1) -timer.init(period=UPDATE_INTERVAL*1000, mode=Timer.PERIODIC, callback=lambda t: get_data()) +timer.init(period=UPDATE_INTERVAL * 1000, mode=Timer.PERIODIC, callback=lambda t: get_data()) while True: # do some fancy stuff with the LEDs based on the weather code From 1886c4c3d2127229f5ff8de3c5dcd0aff53709ff Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Wed, 5 Oct 2022 15:00:59 +0100 Subject: [PATCH 04/23] add rainbows and blinkies --- .../plasma_stick/alternating-blinkies.py | 42 +++++++++++++++++++ micropython/examples/plasma_stick/rainbows.py | 36 ++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 micropython/examples/plasma_stick/alternating-blinkies.py create mode 100644 micropython/examples/plasma_stick/rainbows.py diff --git a/micropython/examples/plasma_stick/alternating-blinkies.py b/micropython/examples/plasma_stick/alternating-blinkies.py new file mode 100644 index 00000000..10010122 --- /dev/null +++ b/micropython/examples/plasma_stick/alternating-blinkies.py @@ -0,0 +1,42 @@ +import plasma +from plasma import plasma2040 +import time + +""" +This super simple example sets up two alternating colours, great for festive lights! +""" + +# Set how many LEDs you have +NUM_LEDS = 50 + +# Pick two hues from the colour wheel (from 0-360°, try https://www.cssscript.com/demo/hsv-hsl-color-wheel-picker-reinvented/ ) +HUE_1 = 40 +HUE_2 = 285 + +# Set up brightness (between 0 and 1) +BRIGHTNESS = 0.5 + +# Set up speed (wait time between colour changes, in seconds) +SPEED = 1 + +# WS2812 / NeoPixel™ LEDs +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) + +# Start updating the LED strip +led_strip.start() + +while True: + for i in range(NUM_LEDS): + # the if statements below use a modulo operation to identify the even and odd numbered LEDs + if (i % 2) == 0: + led_strip.set_hsv(i, HUE_1 / 360, 1.0, BRIGHTNESS) + else: + led_strip.set_hsv(i, HUE_2 / 360, 1.0, BRIGHTNESS) + time.sleep(SPEED) + + for i in range(NUM_LEDS): + if (i % 2) == 0: + led_strip.set_hsv(i, HUE_2 / 360, 1.0, BRIGHTNESS) + else: + led_strip.set_hsv(i, HUE_1 / 360, 1.0, BRIGHTNESS) + time.sleep(SPEED) diff --git a/micropython/examples/plasma_stick/rainbows.py b/micropython/examples/plasma_stick/rainbows.py new file mode 100644 index 00000000..2665bbc4 --- /dev/null +++ b/micropython/examples/plasma_stick/rainbows.py @@ -0,0 +1,36 @@ +import plasma +from plasma import plasma2040 +import time + +""" +Make some rainbows! +""" + +# Set how many LEDs you have +NUM_LEDS = 50 + +# The SPEED that the LEDs cycle at (1 - 255) +SPEED = 20 + +# How many times the LEDs will be updated per second +UPDATES = 60 + +# WS2812 / NeoPixel™ LEDs +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) + +# Start updating the LED strip +led_strip.start() + +offset = 0.0 + +# Make rainbows +while True: + + SPEED = min(255, max(1, SPEED)) + offset += float(SPEED) / 2000.0 + + for i in range(NUM_LEDS): + hue = float(i) / NUM_LEDS + led_strip.set_hsv(i, hue + offset, 1.0, 1.0) + + time.sleep(1.0 / UPDATES) From f6cd2839cc2d01b45b58dca991d1ddcb578ff2ad Mon Sep 17 00:00:00 2001 From: Hel Gibbons Date: Mon, 10 Oct 2022 15:17:25 +0100 Subject: [PATCH 05/23] Update weather.py --- micropython/examples/plasma_stick/weather.py | 22 ++++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/micropython/examples/plasma_stick/weather.py b/micropython/examples/plasma_stick/weather.py index 5d985c46..c61c12d4 100644 --- a/micropython/examples/plasma_stick/weather.py +++ b/micropython/examples/plasma_stick/weather.py @@ -27,7 +27,7 @@ LNG = -1.4239983439328177 TIMEZONE = "auto" # determines time zone from lat/long URL = "https://api.open-meteo.com/v1/forecast?latitude=" + str(LAT) + "&longitude=" + str(LNG) + "¤t_weather=true&timezone=" + TIMEZONE -UPDATE_INTERVAL = 300 # refresh interval in secs. Be nice to free APIs! +UPDATE_INTERVAL = 900 # refresh interval in secs. Be nice to free APIs! # Weather codes from https://open-meteo.com/en/docs#:~:text=WMO%20Weather%20interpretation%20codes%20(WW) WEATHERCODES = { @@ -98,10 +98,9 @@ def get_data(): weathercode = current["weathercode"] datetime_arr = current["time"].split("T") - print(f""" - Temperature = {temperature}°C - Conditions = {WEATHERCODES[weathercode]} - Last Open-Meteo update: {datetime_arr[0]}, {datetime_arr[1]} + print(f"""Temperature = {temperature}°C +Conditions = {WEATHERCODES[weathercode]} +Last Open-Meteo update: {datetime_arr[0]}, {datetime_arr[1]} """) @@ -123,9 +122,14 @@ def move_to_target(): def clear(): - # nice sunny yellow - for i in range(NUM_LEDS): - target_leds[i] = [242, 237, 80] + if weathercode == 0: # clear + # nice sunny yellow + for i in range(NUM_LEDS): + target_leds[i] = [randrange(220, 260), randrange(220, 260), randrange(60, 100)] + if weathercode == 1: # mostly clear + # sky blues + for i in range(NUM_LEDS): + target_leds[i] = [randrange(0, 40), randrange(150, 190), randrange(180, 220)] def clouds(): @@ -206,7 +210,7 @@ def snow(): # some variables we'll use for animations -ANIMATION_SPEED = 2 # higher number gets from current to target colour faster +ANIMATION_SPEED = 1 # higher number gets from current to target colour faster # Create an list of [r, g, b] values that will hold current LED colours, for display current_leds = [[0] * 3 for i in range(NUM_LEDS)] From b22c536dcc18e68ee89c11238a43375d5e86e6ea Mon Sep 17 00:00:00 2001 From: Hel Gibbons Date: Mon, 10 Oct 2022 17:17:03 +0100 Subject: [PATCH 06/23] add PIR example --- micropython/examples/plasma_stick/pir.py | 102 +++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 micropython/examples/plasma_stick/pir.py diff --git a/micropython/examples/plasma_stick/pir.py b/micropython/examples/plasma_stick/pir.py new file mode 100644 index 00000000..70ddbd80 --- /dev/null +++ b/micropython/examples/plasma_stick/pir.py @@ -0,0 +1,102 @@ +import plasma +from plasma import plasma2040 +from machine import Pin +import time +from random import random, uniform, choice + +""" +This example uses a PIR sensor to trigger some spooky effects. +We connected ours up to our QW/ST connector. +""" + +# Set how many LEDs you have +NUM_LEDS = 50 + +BRIGHTNESS = 0.8 + +HUE = 0.8 + +# randomly pick a different colour every time an effect fires +RANDOM = True + + +def spooky_flash(): + for i in range(NUM_LEDS): + led_strip.set_hsv(i, HUE, 1.0, BRIGHTNESS / 2) + time.sleep(0.1) + for i in range(NUM_LEDS): + led_strip.set_hsv(i, HUE, 1.0, 0.0) + time.sleep(0.1) + for i in range(NUM_LEDS): + led_strip.set_hsv(i, HUE, 1.0, BRIGHTNESS / 2) + time.sleep(0.1) + for i in range(NUM_LEDS): + led_strip.set_hsv(i, HUE, 1.0, 0.0) + time.sleep(0.1) + for i in range(NUM_LEDS): + led_strip.set_hsv(i, HUE, 1.0, BRIGHTNESS / 2) + time.sleep(0.1) + for i in range(NUM_LEDS): + led_strip.set_hsv(i, HUE, 1.0, 0.0) + time.sleep(0.1) + for i in range(NUM_LEDS): + led_strip.set_hsv(i, HUE, 1.0, BRIGHTNESS) + time.sleep(3) + for i in range(NUM_LEDS): + led_strip.set_hsv(i, HUE, 1.0, BRIGHTNESS / 2) + time.sleep(0.1) + for i in range(NUM_LEDS): + led_strip.set_hsv(i, HUE, 1.0, 0.0) + time.sleep(0.1) + # uncomment next line to increase tension + # time.sleep(randrange(0, 15)) + + +def fire(): + while pir.value() == 1: + # fire effect! Random red/orange hue, full saturation, random brightness + for i in range(NUM_LEDS): + led_strip.set_hsv(i, uniform(0.0, 50 / 360), 1.0, random()) + time.sleep(0.1) + + +def all_on(): + while pir.value == 1: + # light up a solid colour while movement is detected + for i in range(NUM_LEDS): + led_strip.set_hsv(i, HUE, 1.0, BRIGHTNESS) + time.sleep(0.1) + + +# set up the hardware +# WS2812 / NeoPixel™ LEDs +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) + +# the pin the signal line of our PIR sensor is connected to +# if you're using one of our qw/st > DuPont cables the blue wire is GP4 and the yellow wire is GP5 +pir = Pin(5, Pin.IN, Pin.PULL_UP) + +# Start updating the LED strip +led_strip.start() + +while True: + # on movement + if pir.value() == 1: + print("Movement detected!") + # pick a random colour + if RANDOM is True: + HUE = random() + + # pick a random effect + effects = [spooky_flash, fire, all_on] + choice(effects)() + + # if you want a specific effect, comment the lines above and uncomment one of these: + # spooky_flash() + # fire() + # all_on() + + else: + for i in range(NUM_LEDS): + led_strip.set_hsv(i, 1.0, 1.0, 0.0) + time.sleep(0.1) From 97abbb7af8f6638bb92c41b33a4aeb97d111d232 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Wed, 12 Oct 2022 12:06:41 +0100 Subject: [PATCH 07/23] add spoooky mooon example --- micropython/examples/plasma_stick/moon.py | 56 +++++++++++++ micropython/examples/plasma_stick/moon_rtc.py | 84 +++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 micropython/examples/plasma_stick/moon.py create mode 100644 micropython/examples/plasma_stick/moon_rtc.py diff --git a/micropython/examples/plasma_stick/moon.py b/micropython/examples/plasma_stick/moon.py new file mode 100644 index 00000000..4359bf8d --- /dev/null +++ b/micropython/examples/plasma_stick/moon.py @@ -0,0 +1,56 @@ +import time +import plasma +from plasma import plasma2040 +from machine import RTC + +""" +Spooky moon simulator! +The LEDs will get brighter as midnight approaches! +It won't do much in the day... +Needs to be run from Thonny to get the right time. +""" + +# Set how many LEDs you have +NUM_LEDS = 50 + +# pick a hue (0 - 360° on the colour wheel) +# warm white moon - 60, blue moon - 230 , blood moon - 0 +HUE = 60 +SATURATION = 0.2 # increase this for a more colourful moon (max 1.0) + +# when to start counting down from, in seconds before midnight +# eg from 10pm = 2 hours = 2 * 60 * 60 = 7200 +COUNT_FROM = 14400 + +# set up the WS2812 / NeoPixel™ LEDs +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) + +# start updating the LED strip +led_strip.start() + +while True: + # get the time from Pico RTC + year, month, day, _, hour, minute, second, _ = RTC().datetime() + print(f'Time is {hour:02d}:{minute:02d}') + + # calculate how long to go until midnight + if hour >= 12: + hours_to_go = 23 - hour + minutes_to_go = 59 - minute + seconds_to_go = 59 - second + total_seconds = hours_to_go * 60 * 60 + minutes_to_go * 60 + seconds_to_go + print(f'{total_seconds} seconds until midnight') + # or, if it's after midnight + else: + hours_since = 0 + hour + minutes_since = 0 + minute + seconds_since = 0 + second + total_seconds = hours_since * 60 * 60 + minutes_since * 60 + seconds_since + print(f'{total_seconds} seconds since midnight') + + # gets brighter as witching hour approacheth + brightness = max(0, (COUNT_FROM - total_seconds) / COUNT_FROM) + for i in range(NUM_LEDS): + led_strip.set_hsv(i, HUE/365.0, SATURATION, brightness) + print(f'Brightness - {brightness * 100} %') + time.sleep(10.0) diff --git a/micropython/examples/plasma_stick/moon_rtc.py b/micropython/examples/plasma_stick/moon_rtc.py new file mode 100644 index 00000000..7dc955fa --- /dev/null +++ b/micropython/examples/plasma_stick/moon_rtc.py @@ -0,0 +1,84 @@ +import time +import plasma +from plasma import plasma2040 +from machine import RTC + +""" +Spooky moon simulator! +The LEDs will get brighter as midnight approaches! +It won't do much in the day... +Gets the time from a connected RV3028 RTC breakout: +https://shop.pimoroni.com/products/rv3028-real-time-clock-rtc-breakout +""" + +# Set how many LEDs you have +NUM_LEDS = 50 + +# pick a hue (0 - 360° on the colour wheel) +# warm white moon - 60, blue moon - 230 , blood moon - 0 +HUE = 60 +SATURATION = 0.2 # increase this for a more colourful moon (max 1.0) + +# when to start counting down from, in seconds before midnight +# eg from 10pm = 2 hours = 2 * 60 * 60 = 7200 +COUNT_FROM = 14400 + + +def set_pico_time(): + # the function sets the Pico's RTC from a RV3028 RTC breakout + # to setup breakout (and set the time) run this first: + # https://github.com/pimoroni/pimoroni-pico/blob/main/micropython/examples/breakout_rtc/set-time.py + from pimoroni_i2c import PimoroniI2C + from breakout_rtc import BreakoutRTC + from machine import RTC + + # set up I2C + PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5} # i2c pins 4, 5 for Breakout Garden + i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN) + + # set up the RTC breakout + RV3028 = BreakoutRTC(i2c) + + # set the Pico's RTC from the RTC breakout + RV3028.update_time() + RTC().datetime([RV3028.get_year(), RV3028.get_month(), RV3028.get_date(), + RV3028.get_weekday(), RV3028.get_hours(), RV3028.get_minutes(), + RV3028.get_seconds(), 0]) + print(f"Pico RTC set to breakout time: {RV3028.string_date()} {RV3028.string_time()}") + + +# set up the WS2812 / NeoPixel™ LEDs +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) + +# start updating the LED strip +led_strip.start() + +# call our function to set the Pico's RTC +set_pico_time() + +while True: + # get the time from Pico RTC + year, month, day, _, hour, minute, second, _ = RTC().datetime() + print(f'Time is {hour:02d}:{minute:02d}') + + # calculate how long to go until midnight + if hour >= 12: + hours_to_go = 23 - hour + minutes_to_go = 59 - minute + seconds_to_go = 59 - second + total_seconds = hours_to_go * 60 * 60 + minutes_to_go * 60 + seconds_to_go + print(f'{total_seconds} seconds until midnight') + # or, if it's after midnight + else: + hours_since = 0 + hour + minutes_since = 0 + minute + seconds_since = 0 + second + total_seconds = hours_since * 60 * 60 + minutes_since * 60 + seconds_since + print(f'{total_seconds} seconds since midnight') + + # gets brighter as witching hour approacheth + brightness = max(0, (COUNT_FROM - total_seconds) / COUNT_FROM) + for i in range(NUM_LEDS): + led_strip.set_hsv(i, HUE/365.0, SATURATION, brightness) + print(f'Brightness - {brightness * 100} %') + time.sleep(10.0) From 2c71351ef7bb19bde193d5c61867b1b3774d78be Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Wed, 12 Oct 2022 12:21:13 +0100 Subject: [PATCH 08/23] add RV3028 function example --- .../examples/breakout_rtc/set-pico-time.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 micropython/examples/breakout_rtc/set-pico-time.py diff --git a/micropython/examples/breakout_rtc/set-pico-time.py b/micropython/examples/breakout_rtc/set-pico-time.py new file mode 100644 index 00000000..d47ee67f --- /dev/null +++ b/micropython/examples/breakout_rtc/set-pico-time.py @@ -0,0 +1,35 @@ +""" +Drop this function into your code to set your board's time/date from your RV3028 RTC breakout! +""" + + +def set_pico_time(): + # the function sets the Pico's RTC from a RV3028 RTC breakout + # to setup breakout (and set the time) run this first: + # https://github.com/pimoroni/pimoroni-pico/blob/main/micropython/examples/breakout_rtc/set-time.py + from pimoroni_i2c import PimoroniI2C + from breakout_rtc import BreakoutRTC + from machine import RTC + + # set up I2C + PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5} # i2c pins 4, 5 for Breakout Garden + # for boards that use the alternate I2C pins use the line below instead + # PINS_PICO_EXPLORER = {"sda": 20, "scl": 21} # Default i2c pins for Pico Explorer + + i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN) + # for boards that use the alternate I2C pins use the line below instead + # i2c = PimoroniI2C(**PINS_PICO_EXPLORER) + + # set up the RTC breakout + RV3028 = BreakoutRTC(i2c) + + # set the Pico's RTC from the RTC breakout + RV3028.update_time() + RTC().datetime([RV3028.get_year(), RV3028.get_month(), RV3028.get_date(), + RV3028.get_weekday(), RV3028.get_hours(), RV3028.get_minutes(), + RV3028.get_seconds(), 0]) + print(f"Pico RTC set to breakout time: {RV3028.string_date()} {RV3028.string_time()}") + + +# call the function +set_pico_time() From db170a7b7639c69ccc45a8970500b856b5fccf0e Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Wed, 12 Oct 2022 12:25:38 +0100 Subject: [PATCH 09/23] linting --- micropython/examples/plasma_stick/moon.py | 2 +- micropython/examples/plasma_stick/moon_rtc.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/micropython/examples/plasma_stick/moon.py b/micropython/examples/plasma_stick/moon.py index 4359bf8d..fd1d8b81 100644 --- a/micropython/examples/plasma_stick/moon.py +++ b/micropython/examples/plasma_stick/moon.py @@ -51,6 +51,6 @@ while True: # gets brighter as witching hour approacheth brightness = max(0, (COUNT_FROM - total_seconds) / COUNT_FROM) for i in range(NUM_LEDS): - led_strip.set_hsv(i, HUE/365.0, SATURATION, brightness) + led_strip.set_hsv(i, HUE / 360.0, SATURATION, brightness) print(f'Brightness - {brightness * 100} %') time.sleep(10.0) diff --git a/micropython/examples/plasma_stick/moon_rtc.py b/micropython/examples/plasma_stick/moon_rtc.py index 7dc955fa..325ad61f 100644 --- a/micropython/examples/plasma_stick/moon_rtc.py +++ b/micropython/examples/plasma_stick/moon_rtc.py @@ -79,6 +79,6 @@ while True: # gets brighter as witching hour approacheth brightness = max(0, (COUNT_FROM - total_seconds) / COUNT_FROM) for i in range(NUM_LEDS): - led_strip.set_hsv(i, HUE/365.0, SATURATION, brightness) + led_strip.set_hsv(i, HUE / 360.0, SATURATION, brightness) print(f'Brightness - {brightness * 100} %') time.sleep(10.0) From 7014bcb7494b52c329a077bd6aaab0329d227886 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Wed, 12 Oct 2022 16:54:48 +0100 Subject: [PATCH 10/23] add sensor examples --- micropython/examples/plasma_stick/co2.py | 56 ++++++++++++++++ .../plasma_stick/thermometer_bme280.py | 55 ++++++++++++++++ .../examples/plasma_stick/thermometer_pico.py | 64 +++++++++++++++++++ 3 files changed, 175 insertions(+) create mode 100644 micropython/examples/plasma_stick/co2.py create mode 100644 micropython/examples/plasma_stick/thermometer_bme280.py create mode 100644 micropython/examples/plasma_stick/thermometer_pico.py diff --git a/micropython/examples/plasma_stick/co2.py b/micropython/examples/plasma_stick/co2.py new file mode 100644 index 00000000..2f1bafd4 --- /dev/null +++ b/micropython/examples/plasma_stick/co2.py @@ -0,0 +1,56 @@ +import plasma +from plasma import plasma2040 +import breakout_scd41 as scd +from pimoroni_i2c import PimoroniI2C + +""" +Reads CO2 level from an SCD41 breakout... +... and changes the LED strip an appropriate colour. +https://shop.pimoroni.com/products/scd41-co2-sensor-breakout +""" + +# set how many LEDs you have +NUM_LEDS = 50 + +BRIGHTNESS = 1.0 + +# the range of readings to map to colours +# https://www.kane.co.uk/knowledge-centre/what-are-safe-levels-of-co-and-co2-in-rooms +MIN = 400 +MAX = 2000 + +# pick what bits of the colour wheel to use (from 0-360°) +# https://www.cssscript.com/demo/hsv-hsl-color-wheel-picker-reinvented/ +HUE_START = 100 # green +HUE_END = 0 # red + +# WS2812 / NeoPixel™ LEDs +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) + +# Start updating the LED strip +led_strip.start() + +# set up I2C +PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5} +i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN) + +# set up SCD41 breakout +scd.init(i2c) +scd.start() + +print("Waiting for SCD41 to be ready") + +while True: + if scd.ready(): + co2, temperature, humidity = scd.measure() + print(f""" +CO2: {co2} ppm +Temperature: {temperature:.2f} °C +Humidity: {humidity:.2f} %""") + + # calculates a colour + hue = HUE_START + ((co2 - MIN) * (HUE_END - HUE_START) / (MAX - MIN)) + + # set the leds + for i in range(NUM_LEDS): + led_strip.set_hsv(i, hue / 360, 1.0, BRIGHTNESS) diff --git a/micropython/examples/plasma_stick/thermometer_bme280.py b/micropython/examples/plasma_stick/thermometer_bme280.py new file mode 100644 index 00000000..52dd21a9 --- /dev/null +++ b/micropython/examples/plasma_stick/thermometer_bme280.py @@ -0,0 +1,55 @@ +import plasma +from plasma import plasma2040 +import time +from breakout_bme280 import BreakoutBME280 +from pimoroni_i2c import PimoroniI2C + +""" +Reads the temperature from a BME280 breakout... +...and changes the LED strip an appropriate colour. +https://shop.pimoroni.com/products/bme280-breakout +""" + +# Set how many LEDs you have +NUM_LEDS = 50 + +BRIGHTNESS = 1.0 + +# The range of readings that we want to map to colours +MIN = 10 +MAX = 30 + +# pick what bits of the colour wheel to use (from 0-360°) +# https://www.cssscript.com/demo/hsv-hsl-color-wheel-picker-reinvented/ +HUE_START = 230 # blue +HUE_END = 359 # red + +# WS2812 / NeoPixel™ LEDs +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) + +# Start updating the LED strip +led_strip.start() + +# set up I2C +PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5} +i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN) + +# set up BME280 breakout +bme = BreakoutBME280(i2c) + +while True: + temperature, pressure, humidity = bme.read() + print(f""" +Temperature: {temperature:.2f} °C +Humidity: {humidity:.2f} % +Pressure: {pressure / 100:.2f} hPa + """) + + # calculates a colour + hue = HUE_START + ((temperature - MIN) * (HUE_END - HUE_START) / (MAX - MIN)) + + # set the leds + for i in range(NUM_LEDS): + led_strip.set_hsv(i, hue / 360, 1.0, BRIGHTNESS) + + time.sleep(0.5) diff --git a/micropython/examples/plasma_stick/thermometer_pico.py b/micropython/examples/plasma_stick/thermometer_pico.py new file mode 100644 index 00000000..c5b7009f --- /dev/null +++ b/micropython/examples/plasma_stick/thermometer_pico.py @@ -0,0 +1,64 @@ +import plasma +from plasma import plasma2040 +import machine +import time + +""" +Reads the internal temperature sensor on the Pico W... +... and changes the LED strip an appropriate colour. +""" + +# Set how many LEDs you have +NUM_LEDS = 50 + +BRIGHTNESS = 1.0 + +# The range of readings that we want to map to colours +MIN = 10 +MAX = 30 + +# pick what bits of the colour wheel to use (from 0-360°) +# https://www.cssscript.com/demo/hsv-hsl-color-wheel-picker-reinvented/ +HUE_START = 230 # blue +HUE_END = 359 # red + +# WS2812 / NeoPixel™ LEDs +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) + +# Start updating the LED strip +led_strip.start() + +sensor_temp = machine.ADC(4) +conversion_factor = 3.3 / (65535) # used for calculating a temperature from the raw sensor reading + +# The Pico's temperature sensor is not super accurate and readings jump around +# lets do some averaging to avoid annoying flashing +n = 0 +temperature = 20 # a dummy value to fill the array +temperature_array = [temperature] * 10 # average over 10 readings (5 secs) + +while True: + # read the sensor + # the following two lines do some maths to convert the number from the temp sensor into celsius + reading = sensor_temp.read_u16() * conversion_factor + temperature = 27 - (reading - 0.706) / 0.001721 + + # add the most recent reading to the array + if n >= len(temperature_array): + n = 0 + temperature_array[n] = temperature + n += 1 + + temperature_average = sum(temperature_array)/len(temperature_array) + print(f""" + Average temperature: {temperature_average:.2f} °C + """) + + # calculates a colour + hue = HUE_START + ((temperature_average - MIN) * (HUE_END - HUE_START) / (MAX - MIN)) + + # set the leds + for i in range(NUM_LEDS): + led_strip.set_hsv(i, hue / 360, 1.0, BRIGHTNESS) + + time.sleep(0.5) From bdc22af6e572d452cf6c5ff9395c0bc9efd33e17 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Wed, 12 Oct 2022 18:20:32 +0100 Subject: [PATCH 11/23] add fire example --- micropython/examples/plasma_stick/fire.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 micropython/examples/plasma_stick/fire.py diff --git a/micropython/examples/plasma_stick/fire.py b/micropython/examples/plasma_stick/fire.py new file mode 100644 index 00000000..ce9868ff --- /dev/null +++ b/micropython/examples/plasma_stick/fire.py @@ -0,0 +1,23 @@ +import plasma +from plasma import plasma2040 +import time +from random import random, uniform + +""" +A basic fire effect. +""" + +# Set how many LEDs you have +NUM_LEDS = 50 + +# WS2812 / NeoPixel™ LEDs +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) + +# Start updating the LED strip +led_strip.start() + +while True: + # fire effect! Random red/orange hue, full saturation, random brightness + for i in range(NUM_LEDS): + led_strip.set_hsv(i, uniform(0.0, 50 / 360), 1.0, random()) + time.sleep(0.1) From 6e93e4d5bf1ead5853857574e5cd2090e01bef59 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Wed, 12 Oct 2022 18:23:24 +0100 Subject: [PATCH 12/23] add readme --- micropython/examples/plasma_stick/README.md | 137 ++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 micropython/examples/plasma_stick/README.md diff --git a/micropython/examples/plasma_stick/README.md b/micropython/examples/plasma_stick/README.md new file mode 100644 index 00000000..60cc3d67 --- /dev/null +++ b/micropython/examples/plasma_stick/README.md @@ -0,0 +1,137 @@ +# Plasma Stick MicroPython Examples + +- [About Plasma Stick](#about-plasma-stick) +- [Plasma](#plasma) +- [Using Breakouts](#using-breakouts) +- [Basic Examples](#basic-examples) + - [Alternating Blinkies](#alternating-blinkies) + - [Fire](#fire) + - [Moon](#moon) + - [Rainbows](#rainbows) + - [Thermometer](#thermometer) +- [Advanced Examples](#advanced-examples) + - [CO2](#co2) + - [Encoder](#encoder) + - [Moon (RTC)](#moon-rtc) + - [PIR](#pir) + - [Thermometer (BME280)](#thermometer-bme280) +- [Wireless Examples](#wireless-examples) + - [Cheerlights](#cheerlights) + - [Weather](#weather) + +## About Plasma Stick + +Plasma Stick 2040 W is a compact little controller for WS2812 strip, powered by Raspberry Pi Pico W and perfect for easy, seasonal lighting. It has built in ✨wireless connectivity✨, courtesy of the Pico W. [store link coming soon] + +If you're after buttons, current sensing, APA102 support or USB-C, you might prefer Plasma 2040 - [[store link]](https://shop.pimoroni.com/products/plasma-2040) + +Plasma Stick ships without firmware, you'll need to download the latest `pimoroni-picow` build from the link below. + +- [MicroPython releases](https://github.com/pimoroni/pimoroni-pico/releases) + +## Plasma + +We recommend using our MicroPython Plasma library for controlling your WS2812 / NeoPixel™ strip: + +- [PicoGraphics MicroPython function reference](../../modules/plasma) + +## Using Breakouts + +Plasma Stick has a Qw/ST (Qwiic/STEMMA QT) connector for plugging in I2C breakouts. Breakouts with QW/ST connectors, can be plugged straight in with a [JST-SH to JST-SH cable](https://shop.pimoroni.com/products/jst-sh-cable-qwiic-stemma-qt-compatible?variant=31910609813587). You can also connect any I2C Breakout Garden breakout using a JST-SH to JST-SH cable coupled with a [Qw/ST to Breakout Garden adaptor](https://shop.pimoroni.com/products/stemma-qt-qwiic-to-breakout-garden-adapter?variant=39308432703571). + +- [Breakouts currently supported in our C++/MicroPython build](https://github.com/pimoroni/pimoroni-pico#breakouts) + +Plasma Stick uses GP4 and GP5 for its I2C interface. You can use the constants in the shared `pimoroni` module to set up the I2C interface: + +```python +from pimoroni_i2c import PimoroniI2C +from pimoroni import PINS_BREAKOUT_GARDEN + +i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN) +``` + +Alternatively, you can specify the pin numbers directly: + +```python +from pimoroni_i2c import PimoroniI2C + +i2c = PimoroniI2C(sda=(4), scl=(5)) +``` + +## Basic Examples + +### Alternating Blinkies +[alternating-blinkies.py](alternating-blinkies.py) + +A simple example with two alternating colours, great for festive lights! + +### Fire +[fire.py](fire.py) + +A simple fire effect example. 🔥🤘 + +### Moon +[moon.py](moon.py) + +Spooky moon simulator - the LEDs will get brighter as midnight approaches! +Needs to be run from Thonny to get the correct time. + +### Rainbows +[rainbows.py](rainbows.py) + +Some good old fashioned rainbows! + +### Thermometer +[thermometer_pico.py](thermometer_pico.py) + +Reads the temperature from the Pico W's internal temperature sensor and changes the LED strip an appropriate colour. + +## Advanced Examples + +These examples require additional hardware. + +### CO2 +[co2.py](co2.py) + +Reads CO2 level from an [SCD41 CO2 breakout](https://shop.pimoroni.com/products/scd41-co2-sensor-breakout) and turns the LED strip an appropriate colour. + +### Encoder +[encoder.py](encoder.py) + +Change the colour of your LEDs easily with an [RGB Encoder breakout](https://shop.pimoroni.com/products/rgb-encoder-breakout?variant=32236590399571). + +### Moon (RTC) +[moon_rtc.py](moon_rtc.py) + +Spooky moon simulator - the LEDs will get brighter as midnight approaches! +Gets the time from a [RV3028 RTC breakout](https://shop.pimoroni.com/products/rv3028-real-time-clock-rtc-breakout) + +### PIR +[pir.py](pir.py) + +Connect a PIR motion sensor and trigger some ominous effects. We like [these ones](https://shop.pimoroni.com/products/micro-pir-motion-sensor-2-pcs) - we connected ours to the QwST connector using [this cable](https://shop.pimoroni.com/products/jst-sh-cable-qwiic-stemma-qt-compatible?variant=31910609846355) and some [socket to socket](https://shop.pimoroni.com/products/jumper-jerky-junior?variant=1076482185) jumper jerky. + +### Thermometer (BME280) +[thermometer_bme280.py](thermometer_bme280.py) + +Reads the temperature from a [BME280 breakout](https://shop.pimoroni.com/products/bme280-breakout) and changes the LED strip an appropriate colour. + +## Wireless Examples + +The wireless examples need `network_manager.py` and `WIFI_CONFIG.py` from the `common` directory to be saved to your Pico W. Open up `WIFI_CONFIG.py` in Thonny to add your wifi details (and save it when you're done). + +- [micropython/examples/common](../../examples/common) + +### Cheerlights +[cheerlights.py](cheerlights.py) + +Sets your LED strip to the current #cheerlights colour. +Find out more about the Cheerlights API at https://cheerlights.com/ + +### Weather +[weather.py](weather.py) + +This Plasma Stick example connects to Open Meteo to access the current weather conditions. +It then does some cool weather appropriate stuff with LEDs. +Find out more about the Open Meteo API at https://open-meteo.com + From 76c6e36e597f28b126d94f50e5d638276b21ac33 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Wed, 12 Oct 2022 18:32:00 +0100 Subject: [PATCH 13/23] tweak readme --- micropython/examples/plasma_stick/README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/micropython/examples/plasma_stick/README.md b/micropython/examples/plasma_stick/README.md index 60cc3d67..5d62cd93 100644 --- a/micropython/examples/plasma_stick/README.md +++ b/micropython/examples/plasma_stick/README.md @@ -21,25 +21,25 @@ ## About Plasma Stick -Plasma Stick 2040 W is a compact little controller for WS2812 strip, powered by Raspberry Pi Pico W and perfect for easy, seasonal lighting. It has built in ✨wireless connectivity✨, courtesy of the Pico W. [store link coming soon] +Plasma Stick 2040 W is a compact little controller for WS2812 strip, powered by Raspberry Pi Pico W and perfect for easy, seasonal lighting. It has built in ✨wireless connectivity✨, courtesy of the onboard Pico W. [store link coming soon] -If you're after buttons, current sensing, APA102 support or USB-C, you might prefer Plasma 2040 - [[store link]](https://shop.pimoroni.com/products/plasma-2040) +If you're after buttons, current sensing, APA102 support or USB-C, you might prefer [Plasma 2040](https://shop.pimoroni.com/products/plasma-2040) -Plasma Stick ships without firmware, you'll need to download the latest `pimoroni-picow` build from the link below. +Plasma Stick ships without firmware, so you'll need to download the latest `pimoroni-picow` build from the link below. - [MicroPython releases](https://github.com/pimoroni/pimoroni-pico/releases) ## Plasma -We recommend using our MicroPython Plasma library for controlling your WS2812 / NeoPixel™ strip: +You can control your WS2812 / NeoPixel™ strip using our MicroPython Plasma library. - [PicoGraphics MicroPython function reference](../../modules/plasma) ## Using Breakouts -Plasma Stick has a Qw/ST (Qwiic/STEMMA QT) connector for plugging in I2C breakouts. Breakouts with QW/ST connectors, can be plugged straight in with a [JST-SH to JST-SH cable](https://shop.pimoroni.com/products/jst-sh-cable-qwiic-stemma-qt-compatible?variant=31910609813587). You can also connect any I2C Breakout Garden breakout using a JST-SH to JST-SH cable coupled with a [Qw/ST to Breakout Garden adaptor](https://shop.pimoroni.com/products/stemma-qt-qwiic-to-breakout-garden-adapter?variant=39308432703571). +Plasma Stick has a Qw/ST (Qwiic/STEMMA QT) connector. Breakouts with Qw/ST connectors, can be plugged straight in with a [JST-SH to JST-SH cable](https://shop.pimoroni.com/products/jst-sh-cable-qwiic-stemma-qt-compatible?variant=31910609813587). You can also connect any I2C Breakout Garden breakout using a [JST-SH to JST-SH cable](https://shop.pimoroni.com/products/jst-sh-cable-qwiic-stemma-qt-compatible?variant=31910609813587) coupled with a [Qw/ST to Breakout Garden adaptor](https://shop.pimoroni.com/products/stemma-qt-qwiic-to-breakout-garden-adapter). -- [Breakouts currently supported in our C++/MicroPython build](https://github.com/pimoroni/pimoroni-pico#breakouts) +- [List of breakouts currently supported in our C++/MicroPython build](https://github.com/pimoroni/pimoroni-pico#breakouts) Plasma Stick uses GP4 and GP5 for its I2C interface. You can use the constants in the shared `pimoroni` module to set up the I2C interface: @@ -68,7 +68,7 @@ A simple example with two alternating colours, great for festive lights! ### Fire [fire.py](fire.py) -A simple fire effect example. 🔥🤘 +A simple 🔥 fire effect example 🤘 (warning, flashy). ### Moon [moon.py](moon.py) @@ -93,18 +93,18 @@ These examples require additional hardware. ### CO2 [co2.py](co2.py) -Reads CO2 level from an [SCD41 CO2 breakout](https://shop.pimoroni.com/products/scd41-co2-sensor-breakout) and turns the LED strip an appropriate colour. +Reads CO2 level from a [SCD41 CO2 breakout](https://shop.pimoroni.com/products/scd41-co2-sensor-breakout) and turns the LED strip an appropriate colour. ### Encoder [encoder.py](encoder.py) -Change the colour of your LEDs easily with an [RGB Encoder breakout](https://shop.pimoroni.com/products/rgb-encoder-breakout?variant=32236590399571). +Adjust the colour of your LEDs easily with an [RGB Encoder breakout](https://shop.pimoroni.com/products/rgb-encoder-breakout?variant=32236590399571). ### Moon (RTC) [moon_rtc.py](moon_rtc.py) Spooky moon simulator - the LEDs will get brighter as midnight approaches! -Gets the time from a [RV3028 RTC breakout](https://shop.pimoroni.com/products/rv3028-real-time-clock-rtc-breakout) +Gets the time from a [RV3028 RTC breakout](https://shop.pimoroni.com/products/rv3028-real-time-clock-rtc-breakout). ### PIR [pir.py](pir.py) From 8b19a9b314bcef5791f6945d13a7ae678ef4afb8 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Wed, 12 Oct 2022 18:32:45 +0100 Subject: [PATCH 14/23] linting --- micropython/examples/plasma_stick/thermometer_pico.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/micropython/examples/plasma_stick/thermometer_pico.py b/micropython/examples/plasma_stick/thermometer_pico.py index c5b7009f..6b9972fb 100644 --- a/micropython/examples/plasma_stick/thermometer_pico.py +++ b/micropython/examples/plasma_stick/thermometer_pico.py @@ -49,7 +49,7 @@ while True: temperature_array[n] = temperature n += 1 - temperature_average = sum(temperature_array)/len(temperature_array) + temperature_average = sum(temperature_array) / len(temperature_array) print(f""" Average temperature: {temperature_average:.2f} °C """) From d7f85c116060d8bd3492683e58d4772e6f9b81f0 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Wed, 12 Oct 2022 18:38:14 +0100 Subject: [PATCH 15/23] tweak readme --- micropython/examples/plasma_stick/README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/micropython/examples/plasma_stick/README.md b/micropython/examples/plasma_stick/README.md index 5d62cd93..72c3edfe 100644 --- a/micropython/examples/plasma_stick/README.md +++ b/micropython/examples/plasma_stick/README.md @@ -1,7 +1,7 @@ # Plasma Stick MicroPython Examples - [About Plasma Stick](#about-plasma-stick) -- [Plasma](#plasma) +- [Plasma Library](#plasma-library) - [Using Breakouts](#using-breakouts) - [Basic Examples](#basic-examples) - [Alternating Blinkies](#alternating-blinkies) @@ -21,15 +21,17 @@ ## About Plasma Stick -Plasma Stick 2040 W is a compact little controller for WS2812 strip, powered by Raspberry Pi Pico W and perfect for easy, seasonal lighting. It has built in ✨wireless connectivity✨, courtesy of the onboard Pico W. [store link coming soon] +Plasma Stick 2040 W is a compact little controller for WS2812 strip, powered by Raspberry Pi Pico W and perfect for easy, seasonal lighting. It has built in ✨wireless connectivity✨, courtesy of the onboard Pico W. -If you're after buttons, current sensing, APA102 support or USB-C, you might prefer [Plasma 2040](https://shop.pimoroni.com/products/plasma-2040) +[store link coming soon] + +If you're after buttons, current sensing, APA102 support or USB-C, you might prefer [Plasma 2040](https://shop.pimoroni.com/products/plasma-2040). Plasma Stick ships without firmware, so you'll need to download the latest `pimoroni-picow` build from the link below. - [MicroPython releases](https://github.com/pimoroni/pimoroni-pico/releases) -## Plasma +## Plasma Library You can control your WS2812 / NeoPixel™ strip using our MicroPython Plasma library. @@ -126,12 +128,12 @@ The wireless examples need `network_manager.py` and `WIFI_CONFIG.py` from the `c [cheerlights.py](cheerlights.py) Sets your LED strip to the current #cheerlights colour. -Find out more about the Cheerlights API at https://cheerlights.com/ +Find out more about the Cheerlights API at [https://cheerlights.com/]. ### Weather [weather.py](weather.py) This Plasma Stick example connects to Open Meteo to access the current weather conditions. It then does some cool weather appropriate stuff with LEDs. -Find out more about the Open Meteo API at https://open-meteo.com +Find out more about the Open Meteo API at [https://open-meteo.com]. From e986832414b6969962877fca4879d33856f1a389 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Thu, 13 Oct 2022 18:15:35 +0100 Subject: [PATCH 16/23] add spooky rainbows for @guru --- .../examples/plasma_stick/cheerlights.py | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/micropython/examples/plasma_stick/cheerlights.py b/micropython/examples/plasma_stick/cheerlights.py index ff0cc1ae..36269894 100644 --- a/micropython/examples/plasma_stick/cheerlights.py +++ b/micropython/examples/plasma_stick/cheerlights.py @@ -33,9 +33,34 @@ def status_handler(mode, status, ip): print('Connection successful!') else: print('Connection failed!') - # light up red if connection fails - for i in range(NUM_LEDS): - led_strip.set_rgb(i, 255, 0, 0) + # if no wifi connection, you get spooky rainbows. Bwahahaha! + spooky_rainbows() + + +def spooky_rainbows(): + print("SPOOKY RAINBOWS!") + HUE_START = 30 # orange + HUE_END = 140 # green + SPEED = 0.3 # bigger = faster (harder, stronger) + + distance = 0.0 + direction = SPEED + while True: + for i in range(NUM_LEDS): + # generate a triangle wave that moves up and down the LEDs + j = max(0, 1 - abs(distance - i) / (NUM_LEDS / 3)) + hue = HUE_START + j * (HUE_END - HUE_START) + + led_strip.set_hsv(i, hue / 360, 1.0, 0.8) + + # reverse direction at the end of colour segment to avoid an abrupt change + distance += direction + if distance > NUM_LEDS: + direction = - SPEED + if distance < 0: + direction = SPEED + + time.sleep(0.01) def hex_to_rgb(hex): From 5d45f9aa06e984b87093d25a8d1447120023d1b0 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Thu, 13 Oct 2022 19:01:02 +0100 Subject: [PATCH 17/23] add error handling --- .../examples/plasma_stick/cheerlights.py | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/micropython/examples/plasma_stick/cheerlights.py b/micropython/examples/plasma_stick/cheerlights.py index 36269894..07fdd84a 100644 --- a/micropython/examples/plasma_stick/cheerlights.py +++ b/micropython/examples/plasma_stick/cheerlights.py @@ -6,10 +6,10 @@ import time import plasma from plasma import plasma2040 -""" +''' This Plasma Stick example sets your LED strip to the current #cheerlights colour. Find out more about the Cheerlights API at https://cheerlights.com/ -""" +''' URL = 'http://api.thingspeak.com/channels/1417/field/2/last.json' UPDATE_INTERVAL = 120 # refresh interval in secs. Be nice to free APIs! @@ -30,15 +30,15 @@ def status_handler(mode, status, ip): led_strip.set_rgb(i, 0, 0, 0) if status is not None: if status: - print('Connection successful!') + print('Wifi connection successful!') else: - print('Connection failed!') + print('Wifi connection failed!') # if no wifi connection, you get spooky rainbows. Bwahahaha! spooky_rainbows() def spooky_rainbows(): - print("SPOOKY RAINBOWS!") + print('SPOOKY RAINBOWS!') HUE_START = 30 # orange HUE_END = 140 # green SPEED = 0.3 # bigger = faster (harder, stronger) @@ -77,20 +77,25 @@ led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) led_strip.start() # set up wifi -network_manager = NetworkManager(WIFI_CONFIG.COUNTRY, status_handler=status_handler) -uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK)) +try: + network_manager = NetworkManager(WIFI_CONFIG.COUNTRY, status_handler=status_handler) + uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK)) +except Exception as e: + print(f'Wifi connection failed! {e}') + # if no wifi, then you get... + spooky_rainbows() while True: # open the json file - print(f"Requesting URL: {URL}") + print(f'Requesting URL: {URL}') r = urequests.get(URL) # open the json data j = r.json() - print("Data obtained!") + print('Data obtained!') r.close() # extract hex colour from the data - hex = j["field2"] + hex = j['field2'] # and convert it to RGB r, g, b = hex_to_rgb(hex) @@ -98,9 +103,8 @@ while True: # light up the LEDs for i in range(NUM_LEDS): led_strip.set_rgb(i, r, g, b) - print(f"LEDs set to {hex}") + print(f'LEDs set to {hex}') # sleep - print(f"""Sleeping for {UPDATE_INTERVAL} seconds. - """) + print(f'Sleeping for {UPDATE_INTERVAL} seconds.') time.sleep(UPDATE_INTERVAL) From 41225090efb442ac9803a0a20f166d1536adafb6 Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Mon, 17 Oct 2022 16:15:02 +0100 Subject: [PATCH 18/23] Added some C specific examples for Plasma Stick --- common/pimoroni_common.hpp | 4 +- common/pimoroni_i2c.hpp | 6 ++ examples/CMakeLists.txt | 1 + examples/plasma_stick/CMakeLists.txt | 5 + .../plasma_stick_alternating_blinkies.cmake | 12 +++ .../plasma_stick_alternating_blinkies.cpp | 54 +++++++++++ .../plasma_stick/plasma_stick_encoder.cmake | 14 +++ .../plasma_stick/plasma_stick_encoder.cpp | 92 +++++++++++++++++++ examples/plasma_stick/plasma_stick_fire.cmake | 12 +++ examples/plasma_stick/plasma_stick_fire.cpp | 38 ++++++++ .../plasma_stick/plasma_stick_rainbows.cmake | 12 +++ .../plasma_stick/plasma_stick_rainbows.cpp | 45 +++++++++ .../plasma_stick_temperature_bme280.cmake | 14 +++ .../plasma_stick_temperature_bme280.cpp | 64 +++++++++++++ libraries/CMakeLists.txt | 1 + libraries/plasma_stick/CMakeLists.txt | 1 + libraries/plasma_stick/plasma_stick.cmake | 6 ++ libraries/plasma_stick/plasma_stick.hpp | 10 ++ 18 files changed, 390 insertions(+), 1 deletion(-) create mode 100644 examples/plasma_stick/CMakeLists.txt create mode 100644 examples/plasma_stick/plasma_stick_alternating_blinkies.cmake create mode 100644 examples/plasma_stick/plasma_stick_alternating_blinkies.cpp create mode 100644 examples/plasma_stick/plasma_stick_encoder.cmake create mode 100644 examples/plasma_stick/plasma_stick_encoder.cpp create mode 100644 examples/plasma_stick/plasma_stick_fire.cmake create mode 100644 examples/plasma_stick/plasma_stick_fire.cpp create mode 100644 examples/plasma_stick/plasma_stick_rainbows.cmake create mode 100644 examples/plasma_stick/plasma_stick_rainbows.cpp create mode 100644 examples/plasma_stick/plasma_stick_temperature_bme280.cmake create mode 100644 examples/plasma_stick/plasma_stick_temperature_bme280.cpp create mode 100644 libraries/plasma_stick/CMakeLists.txt create mode 100644 libraries/plasma_stick/plasma_stick.cmake create mode 100644 libraries/plasma_stick/plasma_stick.hpp diff --git a/common/pimoroni_common.hpp b/common/pimoroni_common.hpp index 3ee36022..1f61712a 100644 --- a/common/pimoroni_common.hpp +++ b/common/pimoroni_common.hpp @@ -50,9 +50,11 @@ namespace pimoroni { enum BOARD { BREAKOUT_GARDEN, PICO_EXPLORER, + PLASMA_STICK, PLASMA_2040, INTERSTATE_75, - SERVO_2040 + SERVO_2040, + MOTOR_2040 }; enum Rotation { diff --git a/common/pimoroni_i2c.hpp b/common/pimoroni_i2c.hpp index ea43be40..3c0ceb19 100644 --- a/common/pimoroni_i2c.hpp +++ b/common/pimoroni_i2c.hpp @@ -29,9 +29,15 @@ namespace pimoroni { scl = I2C_DEFAULT_SCL; interrupt = I2C_DEFAULT_INT; break; + case PLASMA_STICK: + sda = I2C_BG_SDA; + scl = I2C_BG_SCL; + interrupt = PIN_UNUSED; + break; case PLASMA_2040: case INTERSTATE_75: case SERVO_2040: + case MOTOR_2040: sda = I2C_HEADER_SDA; scl = I2C_HEADER_SCL; interrupt = I2C_HEADER_INT; diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c7de23d1..01a422ba 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -47,6 +47,7 @@ add_subdirectory(inky_pack) add_subdirectory(inky_frame) add_subdirectory(automation2040w) +add_subdirectory(plasma_stick) add_subdirectory(plasma2040) add_subdirectory(badger2040) add_subdirectory(tufty2040) diff --git a/examples/plasma_stick/CMakeLists.txt b/examples/plasma_stick/CMakeLists.txt new file mode 100644 index 00000000..32b43d0e --- /dev/null +++ b/examples/plasma_stick/CMakeLists.txt @@ -0,0 +1,5 @@ +include(plasma_stick_alternating_blinkies.cmake) +include(plasma_stick_encoder.cmake) +include(plasma_stick_fire.cmake) +include(plasma_stick_rainbows.cmake) +include(plasma_stick_temperature_bme280.cmake) \ No newline at end of file diff --git a/examples/plasma_stick/plasma_stick_alternating_blinkies.cmake b/examples/plasma_stick/plasma_stick_alternating_blinkies.cmake new file mode 100644 index 00000000..e84779c9 --- /dev/null +++ b/examples/plasma_stick/plasma_stick_alternating_blinkies.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME plasma_stick_alternating_blinkies) +add_executable(${OUTPUT_NAME} plasma_stick_alternating_blinkies.cpp) + +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + plasma_stick + ) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/plasma_stick/plasma_stick_alternating_blinkies.cpp b/examples/plasma_stick/plasma_stick_alternating_blinkies.cpp new file mode 100644 index 00000000..f239cb14 --- /dev/null +++ b/examples/plasma_stick/plasma_stick_alternating_blinkies.cpp @@ -0,0 +1,54 @@ +#include "pico/stdlib.h" +#include "plasma_stick.hpp" +#include "common/pimoroni_common.hpp" + +/* +This super simple example sets up two alternating colours, great for festive lights! +*/ + +using namespace pimoroni; +using namespace plasma; + +// Set how many LEDs you have +const uint NUM_LEDS = 50; + +// Pick two hues from the colour wheel (from 0-360°, try https://www.cssscript.com/demo/hsv-hsl-color-wheel-picker-reinvented/ ) +constexpr float HUE_1 = 40.0f; +constexpr float HUE_2 = 285.0f; + +// Set up brightness (between 0 and 1) +constexpr float BRIGHTNESS = 0.5f; + +// Set up speed (wait time between colour changes, in seconds) +constexpr float SPEED = 1.0f; + +// WS2812 / NeoPixel™ LEDs +WS2812 led_strip(NUM_LEDS, pio0, 0, plasma_stick::DAT); + + +int main() { + stdio_init_all(); + + // Start updating the LED strip + led_strip.start(); + + while(true) { + + for(auto i = 0u; i < NUM_LEDS; i++) { + // the if statements below use a modulo operation to identify the even and odd numbered LEDs + if((i % 2) == 0) + led_strip.set_hsv(i, HUE_1 / 360, 1.0, BRIGHTNESS); + else + led_strip.set_hsv(i, HUE_2 / 360, 1.0, BRIGHTNESS); + } + sleep_ms(SPEED * 1000.0f); + + for(auto i = 0u; i < NUM_LEDS; i++) { + if((i % 2) == 0) + led_strip.set_hsv(i, HUE_2 / 360, 1.0, BRIGHTNESS); + else + led_strip.set_hsv(i, HUE_1 / 360, 1.0, BRIGHTNESS); + } + sleep_ms(SPEED * 1000.0f); + } +} diff --git a/examples/plasma_stick/plasma_stick_encoder.cmake b/examples/plasma_stick/plasma_stick_encoder.cmake new file mode 100644 index 00000000..ba4ed048 --- /dev/null +++ b/examples/plasma_stick/plasma_stick_encoder.cmake @@ -0,0 +1,14 @@ +set(OUTPUT_NAME plasma_stick_encoder) +add_executable(${OUTPUT_NAME} plasma_stick_encoder.cpp) + +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + plasma_stick + breakout_encoder + pimoroni_i2c + ) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/plasma_stick/plasma_stick_encoder.cpp b/examples/plasma_stick/plasma_stick_encoder.cpp new file mode 100644 index 00000000..eebdcd3d --- /dev/null +++ b/examples/plasma_stick/plasma_stick_encoder.cpp @@ -0,0 +1,92 @@ +#include +#include "pico/stdlib.h" +#include "plasma_stick.hpp" +#include "common/pimoroni_common.hpp" +#include "breakout_encoder.hpp" + +/* +Change the colour of your LEDs easily by hooking up an RGB Encoder Breakout! +*/ + +using namespace pimoroni; +using namespace plasma; + +// Set how many LEDs you have +const uint NUM_LEDS = 50; + +// Make this number bigger for more precise colour adjustments +const uint STEPS_PER_REV = 24; + +// WS28X-style LEDs with a single signal line. AKA NeoPixel +WS2812 led_strip(NUM_LEDS, pio0, 0, plasma_stick::DAT); + +I2C i2c(BOARD::PLASMA_STICK); +BreakoutEncoder enc(&i2c); + +// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel +// Outputs are rgb in the range 0-255 for each channel +void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { + float i = floor(h * 6.0f); + float f = h * 6.0f - i; + v *= 255.0f; + uint8_t p = v * (1.0f - s); + uint8_t q = v * (1.0f - f * s); + uint8_t t = v * (1.0f - (1.0f - f) * s); + + switch (int(i) % 6) { + case 0: r = v; g = t; b = p; break; + case 1: r = q; g = v; b = p; break; + case 2: r = p; g = v; b = t; break; + case 3: r = p; g = q; b = v; break; + case 4: r = t; g = p; b = v; break; + case 5: r = v; g = p; b = q; break; + } +} + +void count_changed(int16_t count) { + printf("Count: %d\n", count); + float h = (count % STEPS_PER_REV) / (float)STEPS_PER_REV; + uint8_t r = 0, g = 0, b = 0; + from_hsv(h, 1.0f, 1.0f, r, g, b); + + // set the encoder LED colour + enc.set_led(r, g, b); + + for(auto i = 0u; i < NUM_LEDS; i++) { + led_strip.set_rgb(i, r, g, b); + } +} + +int main() { + stdio_init_all(); + + led_strip.start(); + + if(enc.init()) { + printf("Encoder found...\n"); + + enc.set_brightness(1.0f); + //enc.set_direction(BreakoutEncoder::DIRECTION_CCW); // Uncomment this to flip the direction + + count_changed(0); + enc.clear_interrupt_flag(); + + while(true) { + if(enc.get_interrupt_flag()) { + int16_t count = enc.read(); + enc.clear_interrupt_flag(); + + while(count < 0) { + count += STEPS_PER_REV; + } + + count_changed(count); + } + } + } + else { + printf("Encoder not found :'(\n"); + } + + return 0; +} diff --git a/examples/plasma_stick/plasma_stick_fire.cmake b/examples/plasma_stick/plasma_stick_fire.cmake new file mode 100644 index 00000000..90c70e67 --- /dev/null +++ b/examples/plasma_stick/plasma_stick_fire.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME plasma_stick_fire) +add_executable(${OUTPUT_NAME} plasma_stick_fire.cpp) + +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + plasma_stick + ) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/plasma_stick/plasma_stick_fire.cpp b/examples/plasma_stick/plasma_stick_fire.cpp new file mode 100644 index 00000000..d965e9ab --- /dev/null +++ b/examples/plasma_stick/plasma_stick_fire.cpp @@ -0,0 +1,38 @@ +#include "pico/stdlib.h" +#include "plasma_stick.hpp" +#include "common/pimoroni_common.hpp" + +/* +A basic fire effect. +*/ + +using namespace pimoroni; +using namespace plasma; + +// Set how many LEDs you have +const uint NUM_LEDS = 50; + +// WS2812 / NeoPixel™ LEDs +WS2812 led_strip(NUM_LEDS, pio0, 0, plasma_stick::DAT); + +// Maps a value from one range to another +float map(float x, float in_min, float in_max, float out_min, float out_max) { + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +int main() { + stdio_init_all(); + + // Start updating the LED strip + led_strip.start(); + + while(true) { + // fire effect! Random red/orange hue, full saturation, random brightness + for(auto i = 0u; i < NUM_LEDS; ++i) { + float hue = map((float)rand(), 0.0f, (float)RAND_MAX, 0.0, 50.0f / 360.0f); + float brightness = map((float)rand(), 0.0f, (float)RAND_MAX, 0.0, 1.0f); + led_strip.set_hsv(i, hue, 1.0, brightness); + } + sleep_ms(100); + } +} diff --git a/examples/plasma_stick/plasma_stick_rainbows.cmake b/examples/plasma_stick/plasma_stick_rainbows.cmake new file mode 100644 index 00000000..e463b924 --- /dev/null +++ b/examples/plasma_stick/plasma_stick_rainbows.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME plasma_stick_rainbows) +add_executable(${OUTPUT_NAME} plasma_stick_rainbows.cpp) + +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + plasma_stick + ) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/plasma_stick/plasma_stick_rainbows.cpp b/examples/plasma_stick/plasma_stick_rainbows.cpp new file mode 100644 index 00000000..41abcf62 --- /dev/null +++ b/examples/plasma_stick/plasma_stick_rainbows.cpp @@ -0,0 +1,45 @@ +#include "pico/stdlib.h" +#include "plasma_stick.hpp" +#include "common/pimoroni_common.hpp" + +/* +Make some rainbows! +*/ + +using namespace pimoroni; +using namespace plasma; + +// Set how many LEDs you have +const uint NUM_LEDS = 50; + +// The SPEED that the LEDs cycle at (1 - 255) +const uint SPEED = 20; + +// How many times the LEDs will be updated per second +const uint UPDATES = 60; + +// WS2812 / NeoPixel™ LEDs +WS2812 led_strip(NUM_LEDS, pio0, 0, plasma_stick::DAT); + + +int main() { + stdio_init_all(); + + // Start updating the LED strip + led_strip.start(UPDATES); + + float offset = 0.0f; + + // Make rainbows + while(true) { + + offset += float(SPEED) / 2000.0f; + + for(auto i = 0u; i < NUM_LEDS; ++i) { + float hue = float(i) / NUM_LEDS; + led_strip.set_hsv(i, hue + offset, 1.0f, 1.0f); + } + + sleep_ms(1000 / UPDATES); + } +} diff --git a/examples/plasma_stick/plasma_stick_temperature_bme280.cmake b/examples/plasma_stick/plasma_stick_temperature_bme280.cmake new file mode 100644 index 00000000..8bec6c2e --- /dev/null +++ b/examples/plasma_stick/plasma_stick_temperature_bme280.cmake @@ -0,0 +1,14 @@ +set(OUTPUT_NAME plasma_stick_temperature_bme280) +add_executable(${OUTPUT_NAME} plasma_stick_temperature_bme280.cpp) + +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + plasma_stick + bme280 + pimoroni_i2c + ) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/plasma_stick/plasma_stick_temperature_bme280.cpp b/examples/plasma_stick/plasma_stick_temperature_bme280.cpp new file mode 100644 index 00000000..a6316800 --- /dev/null +++ b/examples/plasma_stick/plasma_stick_temperature_bme280.cpp @@ -0,0 +1,64 @@ +#include +#include "pico/stdlib.h" +#include "plasma_stick.hpp" +#include "common/pimoroni_common.hpp" +#include "bme280.hpp" + +/* +Reads the temperature from a BME280 breakout... +...and changes the LED strip an appropriate colour. +https://shop.pimoroni.com/products/bme280-breakout +*/ + +using namespace pimoroni; +using namespace plasma; + +// Set how many LEDs you have +const uint NUM_LEDS = 50; + +// Set up brightness (between 0 and 1) +constexpr float BRIGHTNESS = 1.0f; + +// The range of readings that we want to map to colours +const uint MIN = 10; +const uint MAX = 30; + +// Pick what bits of the colour wheel to use (from 0-360°) +// https://www.cssscript.com/demo/hsv-hsl-color-wheel-picker-reinvented/ +const uint HUE_START = 230; // blue +const uint HUE_END = 359; // red + +// WS28X-style LEDs with a single signal line. AKA NeoPixel +WS2812 led_strip(NUM_LEDS, pio0, 0, plasma_stick::DAT); + +I2C i2c(BOARD::PLASMA_STICK); +BME280 bme(&i2c); + + +int main() { + stdio_init_all(); + + led_strip.start(); + + if(bme.init()) { + printf("BME280 found...\n"); + + while(true) { + BME280::bme280_reading result = bme.read_forced(); + printf("%s %0.2lf deg C, %0.2lf hPa, %0.2lf%%\n", result.status == BME280_OK ? "OK" : "ER", result.temperature, result.pressure, result.humidity); + + // calculates a colour + float hue = HUE_START + ((float)(result.temperature - MIN) * (float)(HUE_END - HUE_START) / (float)(MAX - MIN)); + + // set the leds + for(auto i = 0u; i < NUM_LEDS; i++) { + led_strip.set_hsv(i, hue / 360.0f, 1.0, BRIGHTNESS); + } + } + } + else { + printf("BME280 not found :'(\n"); + } + + return 0; +} diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index b7fa264f..8c192f00 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -26,6 +26,7 @@ add_subdirectory(pico_motor_shim) add_subdirectory(pico_rgb_keypad) add_subdirectory(pico_wireless) add_subdirectory(automation2040w) +add_subdirectory(plasma_stick) add_subdirectory(plasma2040) add_subdirectory(badger2040) add_subdirectory(tufty2040) diff --git a/libraries/plasma_stick/CMakeLists.txt b/libraries/plasma_stick/CMakeLists.txt new file mode 100644 index 00000000..18b91ca9 --- /dev/null +++ b/libraries/plasma_stick/CMakeLists.txt @@ -0,0 +1 @@ +include(plasma_stick.cmake) \ No newline at end of file diff --git a/libraries/plasma_stick/plasma_stick.cmake b/libraries/plasma_stick/plasma_stick.cmake new file mode 100644 index 00000000..dbf1900f --- /dev/null +++ b/libraries/plasma_stick/plasma_stick.cmake @@ -0,0 +1,6 @@ +add_library(plasma_stick INTERFACE) + +target_include_directories(plasma_stick INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +# Pull in pico libraries that we need +target_link_libraries(plasma_stick INTERFACE pico_stdlib plasma) \ No newline at end of file diff --git a/libraries/plasma_stick/plasma_stick.hpp b/libraries/plasma_stick/plasma_stick.hpp new file mode 100644 index 00000000..edf5b8e8 --- /dev/null +++ b/libraries/plasma_stick/plasma_stick.hpp @@ -0,0 +1,10 @@ +#pragma once +#include "pico/stdlib.h" + +#include "ws2812.hpp" + +namespace plasma { + namespace plasma_stick { + const uint DAT = 15; // Used for WS2812 + } +} \ No newline at end of file From a7dd4b3baf32b0707bcf87acd7ff05354163c90a Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Tue, 18 Oct 2022 13:13:57 +0100 Subject: [PATCH 19/23] Updated MP examples with plasma_stick defs --- .../examples/plasma_stick/alternating-blinkies.py | 4 ++-- micropython/examples/plasma_stick/cheerlights.py | 4 ++-- micropython/examples/plasma_stick/co2.py | 7 +++---- micropython/examples/plasma_stick/encoder.py | 8 +++----- micropython/examples/plasma_stick/fire.py | 4 ++-- micropython/examples/plasma_stick/moon.py | 4 ++-- micropython/examples/plasma_stick/moon_rtc.py | 7 +++---- micropython/examples/plasma_stick/pir.py | 8 ++++---- micropython/examples/plasma_stick/rainbows.py | 4 ++-- .../examples/plasma_stick/thermometer_bme280.py | 7 +++---- .../examples/plasma_stick/thermometer_pico.py | 4 ++-- micropython/examples/plasma_stick/weather.py | 4 ++-- micropython/modules/plasma/plasma.c | 14 ++++++++++++++ 13 files changed, 44 insertions(+), 35 deletions(-) diff --git a/micropython/examples/plasma_stick/alternating-blinkies.py b/micropython/examples/plasma_stick/alternating-blinkies.py index 10010122..3733045e 100644 --- a/micropython/examples/plasma_stick/alternating-blinkies.py +++ b/micropython/examples/plasma_stick/alternating-blinkies.py @@ -1,5 +1,5 @@ import plasma -from plasma import plasma2040 +from plasma import plasma_stick import time """ @@ -20,7 +20,7 @@ BRIGHTNESS = 0.5 SPEED = 1 # WS2812 / NeoPixel™ LEDs -led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma_stick.DAT) # Start updating the LED strip led_strip.start() diff --git a/micropython/examples/plasma_stick/cheerlights.py b/micropython/examples/plasma_stick/cheerlights.py index 07fdd84a..eb1d6b2a 100644 --- a/micropython/examples/plasma_stick/cheerlights.py +++ b/micropython/examples/plasma_stick/cheerlights.py @@ -4,7 +4,7 @@ import uasyncio import urequests import time import plasma -from plasma import plasma2040 +from plasma import plasma_stick ''' This Plasma Stick example sets your LED strip to the current #cheerlights colour. @@ -71,7 +71,7 @@ def hex_to_rgb(hex): # set up the WS2812 / NeoPixel™ LEDs -led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma_stick.DAT) # start updating the LED strip led_strip.start() diff --git a/micropython/examples/plasma_stick/co2.py b/micropython/examples/plasma_stick/co2.py index 2f1bafd4..2e82f419 100644 --- a/micropython/examples/plasma_stick/co2.py +++ b/micropython/examples/plasma_stick/co2.py @@ -1,5 +1,5 @@ import plasma -from plasma import plasma2040 +from plasma import plasma_stick import breakout_scd41 as scd from pimoroni_i2c import PimoroniI2C @@ -25,14 +25,13 @@ HUE_START = 100 # green HUE_END = 0 # red # WS2812 / NeoPixel™ LEDs -led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma_stick.DAT) # Start updating the LED strip led_strip.start() # set up I2C -PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5} -i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN) +i2c = PimoroniI2C(plasma_stick.SDA, plasma_stick.SCL) # set up SCD41 breakout scd.init(i2c) diff --git a/micropython/examples/plasma_stick/encoder.py b/micropython/examples/plasma_stick/encoder.py index ad1b4dbf..a03f31ff 100644 --- a/micropython/examples/plasma_stick/encoder.py +++ b/micropython/examples/plasma_stick/encoder.py @@ -1,7 +1,7 @@ from pimoroni_i2c import PimoroniI2C from breakout_encoder import BreakoutEncoder import plasma -from plasma import plasma2040 +from plasma import plasma_stick """ Change the colour of your LEDs easily by hooking up an RGB Encoder Breakout! @@ -13,9 +13,7 @@ NUM_LEDS = 50 # make this number bigger for more precise colour adjustments STEPS_PER_REV = 24 -PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5} - -i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN) +i2c = PimoroniI2C(plasma_stick.SDA, plasma_stick.SCL) enc = BreakoutEncoder(i2c) enc.set_brightness(1.0) @@ -58,7 +56,7 @@ def count_changed(count): # WS2812 / NeoPixel™ LEDs -led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma_stick.DAT) # Start updating the LED strip led_strip.start() diff --git a/micropython/examples/plasma_stick/fire.py b/micropython/examples/plasma_stick/fire.py index ce9868ff..69c6ffe4 100644 --- a/micropython/examples/plasma_stick/fire.py +++ b/micropython/examples/plasma_stick/fire.py @@ -1,5 +1,5 @@ import plasma -from plasma import plasma2040 +from plasma import plasma_stick import time from random import random, uniform @@ -11,7 +11,7 @@ A basic fire effect. NUM_LEDS = 50 # WS2812 / NeoPixel™ LEDs -led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma_stick.DAT) # Start updating the LED strip led_strip.start() diff --git a/micropython/examples/plasma_stick/moon.py b/micropython/examples/plasma_stick/moon.py index fd1d8b81..df3b5beb 100644 --- a/micropython/examples/plasma_stick/moon.py +++ b/micropython/examples/plasma_stick/moon.py @@ -1,6 +1,6 @@ import time import plasma -from plasma import plasma2040 +from plasma import plasma_stick from machine import RTC """ @@ -23,7 +23,7 @@ SATURATION = 0.2 # increase this for a more colourful moon (max 1.0) COUNT_FROM = 14400 # set up the WS2812 / NeoPixel™ LEDs -led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma_stick.DAT) # start updating the LED strip led_strip.start() diff --git a/micropython/examples/plasma_stick/moon_rtc.py b/micropython/examples/plasma_stick/moon_rtc.py index 325ad61f..b49d4cf2 100644 --- a/micropython/examples/plasma_stick/moon_rtc.py +++ b/micropython/examples/plasma_stick/moon_rtc.py @@ -1,6 +1,6 @@ import time import plasma -from plasma import plasma2040 +from plasma import plasma_stick from machine import RTC """ @@ -33,8 +33,7 @@ def set_pico_time(): from machine import RTC # set up I2C - PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5} # i2c pins 4, 5 for Breakout Garden - i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN) + i2c = PimoroniI2C(plasma_stick.SDA, plasma_stick.SCL) # set up the RTC breakout RV3028 = BreakoutRTC(i2c) @@ -48,7 +47,7 @@ def set_pico_time(): # set up the WS2812 / NeoPixel™ LEDs -led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma_stick.DAT) # start updating the LED strip led_strip.start() diff --git a/micropython/examples/plasma_stick/pir.py b/micropython/examples/plasma_stick/pir.py index 70ddbd80..24254ae5 100644 --- a/micropython/examples/plasma_stick/pir.py +++ b/micropython/examples/plasma_stick/pir.py @@ -1,5 +1,5 @@ import plasma -from plasma import plasma2040 +from plasma import plasma_stick from machine import Pin import time from random import random, uniform, choice @@ -70,11 +70,11 @@ def all_on(): # set up the hardware # WS2812 / NeoPixel™ LEDs -led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma_stick.DAT) # the pin the signal line of our PIR sensor is connected to -# if you're using one of our qw/st > DuPont cables the blue wire is GP4 and the yellow wire is GP5 -pir = Pin(5, Pin.IN, Pin.PULL_UP) +# if you're using one of our qw/st > DuPont cables the blue wire is SDA (GP4) and the yellow wire is SCL (GP5) +pir = Pin(plasma_stick.SCL, Pin.IN, Pin.PULL_UP) # Start updating the LED strip led_strip.start() diff --git a/micropython/examples/plasma_stick/rainbows.py b/micropython/examples/plasma_stick/rainbows.py index 2665bbc4..82207387 100644 --- a/micropython/examples/plasma_stick/rainbows.py +++ b/micropython/examples/plasma_stick/rainbows.py @@ -1,5 +1,5 @@ import plasma -from plasma import plasma2040 +from plasma import plasma_stick import time """ @@ -16,7 +16,7 @@ SPEED = 20 UPDATES = 60 # WS2812 / NeoPixel™ LEDs -led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma_stick.DAT) # Start updating the LED strip led_strip.start() diff --git a/micropython/examples/plasma_stick/thermometer_bme280.py b/micropython/examples/plasma_stick/thermometer_bme280.py index 52dd21a9..ff2f6043 100644 --- a/micropython/examples/plasma_stick/thermometer_bme280.py +++ b/micropython/examples/plasma_stick/thermometer_bme280.py @@ -1,5 +1,5 @@ import plasma -from plasma import plasma2040 +from plasma import plasma_stick import time from breakout_bme280 import BreakoutBME280 from pimoroni_i2c import PimoroniI2C @@ -25,14 +25,13 @@ HUE_START = 230 # blue HUE_END = 359 # red # WS2812 / NeoPixel™ LEDs -led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma_stick.DAT) # Start updating the LED strip led_strip.start() # set up I2C -PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5} -i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN) +i2c = PimoroniI2C(plasma_stick.SDA, plasma_stick.SCL) # set up BME280 breakout bme = BreakoutBME280(i2c) diff --git a/micropython/examples/plasma_stick/thermometer_pico.py b/micropython/examples/plasma_stick/thermometer_pico.py index 6b9972fb..1d2765b8 100644 --- a/micropython/examples/plasma_stick/thermometer_pico.py +++ b/micropython/examples/plasma_stick/thermometer_pico.py @@ -1,5 +1,5 @@ import plasma -from plasma import plasma2040 +from plasma import plasma_stick import machine import time @@ -23,7 +23,7 @@ HUE_START = 230 # blue HUE_END = 359 # red # WS2812 / NeoPixel™ LEDs -led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma_stick.DAT) # Start updating the LED strip led_strip.start() diff --git a/micropython/examples/plasma_stick/weather.py b/micropython/examples/plasma_stick/weather.py index c61c12d4..190cd1e3 100644 --- a/micropython/examples/plasma_stick/weather.py +++ b/micropython/examples/plasma_stick/weather.py @@ -4,7 +4,7 @@ import uasyncio import urequests import time import plasma -from plasma import plasma2040 +from plasma import plasma_stick # Random functions! randrange is for picking integers from a range, and uniform is for floats. from random import randrange, uniform from machine import Timer @@ -218,7 +218,7 @@ current_leds = [[0] * 3 for i in range(NUM_LEDS)] target_leds = [[0] * 3 for i in range(NUM_LEDS)] # set up the WS2812 / NeoPixel™ LEDs -led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT) +led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma_stick.DAT) # start updating the LED strip led_strip.start() diff --git a/micropython/modules/plasma/plasma.c b/micropython/modules/plasma/plasma.c index 80d94c2a..2413428f 100644 --- a/micropython/modules/plasma/plasma.c +++ b/micropython/modules/plasma/plasma.c @@ -86,16 +86,30 @@ STATIC const mp_map_elem_t plasma2040_globals_table[] = { }; STATIC MP_DEFINE_CONST_DICT(mp_module_plasma2040_globals, plasma2040_globals_table); +STATIC const mp_map_elem_t plasma_stick_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_plasma_stick) }, + { MP_ROM_QSTR(MP_QSTR_DAT), MP_ROM_INT(15) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_INT(4) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_INT(5) }, +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_plasma_stick_globals, plasma_stick_globals_table); + const mp_obj_module_t plasma2040_user_cmodule = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_plasma2040_globals, }; +const mp_obj_module_t plasma_stick_user_cmodule = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_plasma_stick_globals, +}; + STATIC const mp_map_elem_t plasma_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_plasma) }, { MP_OBJ_NEW_QSTR(MP_QSTR_APA102), (mp_obj_t)&PlasmaAPA102_type }, { MP_OBJ_NEW_QSTR(MP_QSTR_WS2812), (mp_obj_t)&PlasmaWS2812_type }, { MP_OBJ_NEW_QSTR(MP_QSTR_plasma2040), (mp_obj_t)&plasma2040_user_cmodule }, + { MP_OBJ_NEW_QSTR(MP_QSTR_plasma_stick), (mp_obj_t)&plasma_stick_user_cmodule }, { MP_ROM_QSTR(MP_QSTR_COLOR_ORDER_RGB), MP_ROM_INT(0x00) }, { MP_ROM_QSTR(MP_QSTR_COLOR_ORDER_RBG), MP_ROM_INT(0x01) }, From ce76ff5ea395f8556d80f7d4d0dc06e008641876 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Tue, 18 Oct 2022 14:25:02 +0100 Subject: [PATCH 20/23] update docs --- micropython/examples/plasma_stick/README.md | 27 +++++++++--- micropython/modules/plasma/README.md | 48 +++++++++++++-------- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/micropython/examples/plasma_stick/README.md b/micropython/examples/plasma_stick/README.md index 72c3edfe..2a2ca311 100644 --- a/micropython/examples/plasma_stick/README.md +++ b/micropython/examples/plasma_stick/README.md @@ -21,25 +21,27 @@ ## About Plasma Stick -Plasma Stick 2040 W is a compact little controller for WS2812 strip, powered by Raspberry Pi Pico W and perfect for easy, seasonal lighting. It has built in ✨wireless connectivity✨, courtesy of the onboard Pico W. +Plasma Stick 2040 W is a compact controller for WS2812 strip, powered by Raspberry Pi Pico W and perfect for easy, seasonal lighting. It has built in ✨wireless connectivity✨, courtesy of the onboard Pico W. -[store link coming soon] +You can buy one on its own or in a kit: -If you're after buttons, current sensing, APA102 support or USB-C, you might prefer [Plasma 2040](https://shop.pimoroni.com/products/plasma-2040). +- [Plasma Stick 2040 W](https://shop.pimoroni.com/products/plasma-stick-2040-w) -Plasma Stick ships without firmware, so you'll need to download the latest `pimoroni-picow` build from the link below. +- [Wireless Plasma Kit](https://shop.pimoroni.com/products/wireless-plasma-kit) + +Plasma Stick ships with MicroPython firmware pre-loaded, but you can download the most recent version at the link below (you'll want the `pimoroni-picow` image). - [MicroPython releases](https://github.com/pimoroni/pimoroni-pico/releases) ## Plasma Library -You can control your WS2812 / NeoPixel™ strip using our MicroPython Plasma library. +You can control your WS2812 / NeoPixel™ strip using our handy MicroPython Plasma library. - [PicoGraphics MicroPython function reference](../../modules/plasma) ## Using Breakouts -Plasma Stick has a Qw/ST (Qwiic/STEMMA QT) connector. Breakouts with Qw/ST connectors, can be plugged straight in with a [JST-SH to JST-SH cable](https://shop.pimoroni.com/products/jst-sh-cable-qwiic-stemma-qt-compatible?variant=31910609813587). You can also connect any I2C Breakout Garden breakout using a [JST-SH to JST-SH cable](https://shop.pimoroni.com/products/jst-sh-cable-qwiic-stemma-qt-compatible?variant=31910609813587) coupled with a [Qw/ST to Breakout Garden adaptor](https://shop.pimoroni.com/products/stemma-qt-qwiic-to-breakout-garden-adapter). +Plasma Stick has a Qw/ST (Qwiic/STEMMA QT) connector. Breakouts with Qw/ST connectors, can be plugged straight in with a [JST-SH to JST-SH cable](https://shop.pimoroni.com/products/jst-sh-cable-qwiic-stemma-qt-compatible?variant=31910609813587). You can connect I2C Breakout Garden breakouts without Qw/ST connectors using a [JST-SH to JST-SH cable](https://shop.pimoroni.com/products/jst-sh-cable-qwiic-stemma-qt-compatible?variant=31910609813587) and a [Qw/ST to Breakout Garden adaptor](https://shop.pimoroni.com/products/stemma-qt-qwiic-to-breakout-garden-adapter). - [List of breakouts currently supported in our C++/MicroPython build](https://github.com/pimoroni/pimoroni-pico#breakouts) @@ -63,27 +65,32 @@ i2c = PimoroniI2C(sda=(4), scl=(5)) ## Basic Examples ### Alternating Blinkies + [alternating-blinkies.py](alternating-blinkies.py) A simple example with two alternating colours, great for festive lights! ### Fire + [fire.py](fire.py) A simple 🔥 fire effect example 🤘 (warning, flashy). ### Moon + [moon.py](moon.py) Spooky moon simulator - the LEDs will get brighter as midnight approaches! Needs to be run from Thonny to get the correct time. ### Rainbows + [rainbows.py](rainbows.py) Some good old fashioned rainbows! ### Thermometer + [thermometer_pico.py](thermometer_pico.py) Reads the temperature from the Pico W's internal temperature sensor and changes the LED strip an appropriate colour. @@ -93,27 +100,32 @@ Reads the temperature from the Pico W's internal temperature sensor and changes These examples require additional hardware. ### CO2 + [co2.py](co2.py) Reads CO2 level from a [SCD41 CO2 breakout](https://shop.pimoroni.com/products/scd41-co2-sensor-breakout) and turns the LED strip an appropriate colour. ### Encoder + [encoder.py](encoder.py) Adjust the colour of your LEDs easily with an [RGB Encoder breakout](https://shop.pimoroni.com/products/rgb-encoder-breakout?variant=32236590399571). ### Moon (RTC) + [moon_rtc.py](moon_rtc.py) Spooky moon simulator - the LEDs will get brighter as midnight approaches! Gets the time from a [RV3028 RTC breakout](https://shop.pimoroni.com/products/rv3028-real-time-clock-rtc-breakout). ### PIR + [pir.py](pir.py) Connect a PIR motion sensor and trigger some ominous effects. We like [these ones](https://shop.pimoroni.com/products/micro-pir-motion-sensor-2-pcs) - we connected ours to the QwST connector using [this cable](https://shop.pimoroni.com/products/jst-sh-cable-qwiic-stemma-qt-compatible?variant=31910609846355) and some [socket to socket](https://shop.pimoroni.com/products/jumper-jerky-junior?variant=1076482185) jumper jerky. ### Thermometer (BME280) + [thermometer_bme280.py](thermometer_bme280.py) Reads the temperature from a [BME280 breakout](https://shop.pimoroni.com/products/bme280-breakout) and changes the LED strip an appropriate colour. @@ -125,15 +137,16 @@ The wireless examples need `network_manager.py` and `WIFI_CONFIG.py` from the `c - [micropython/examples/common](../../examples/common) ### Cheerlights + [cheerlights.py](cheerlights.py) Sets your LED strip to the current #cheerlights colour. Find out more about the Cheerlights API at [https://cheerlights.com/]. ### Weather + [weather.py](weather.py) This Plasma Stick example connects to Open Meteo to access the current weather conditions. It then does some cool weather appropriate stuff with LEDs. Find out more about the Open Meteo API at [https://open-meteo.com]. - diff --git a/micropython/modules/plasma/README.md b/micropython/modules/plasma/README.md index 1b5ab4ab..a45f6e7c 100644 --- a/micropython/modules/plasma/README.md +++ b/micropython/modules/plasma/README.md @@ -1,6 +1,8 @@ # Plasma -The Plasma library is intended to drive APA102 / DotStar™ or WS2812 / NeoPixel™ LEDs on the Plasma 2040 board, though it can be used with your own custom pins/wiring. +The Plasma library is intended to drive APA102 / DotStar™ or WS2812 / NeoPixel™ LEDs on our [Plasma 2040](https://shop.pimoroni.com/products/plasma-2040) board, though it can also be used with your own custom pins/wiring. + +It can also be used to drive WS2812 / NeoPixel™ LEDs from [Plasma Stick](https://shop.pimoroni.com/products/plasma-stick-2040-w). Note that APA102 compatibility, user buttons, RGB LED and current sensing functions are not present on Plasma Stick. - [Notes On PIO Limitations](#notes-on-pio-limitations) - [WS2812](#ws2812) @@ -9,12 +11,12 @@ The Plasma library is intended to drive APA102 / DotStar™ or WS2812 / NeoPixel - [Set An LED](#set-an-led) - [RGB](#rgb) - [HSV](#hsv) - - [Set Brightness](#set-brightness) - [APA102](#apa102) - [Getting Started](#getting-started-1) - [Set An LED](#set-an-led-1) - [RGB](#rgb-1) - [HSV](#hsv-1) + - [Set Brightness](#set-brightness) - [Using the Buttons & RGB LED](#using-the-buttons--rgb-led) - [Buttons](#buttons) - [RGBLED](#rgbled) @@ -33,6 +35,8 @@ In most cases you'll use `0` for PIO and `0` for PIO state-machine, but you shou Construct a new `WS2812` instance, specifying the number of LEDs, PIO, PIO state-machine and GPIO pin. +For Plasma 2040: + ```python import plasma from plasma import plasma2040 @@ -43,6 +47,18 @@ FPS = 60 led_strip = plasma.WS2812(LEDS, 0, 0, plasma2040.DAT) ``` +For Plasma Stick: + +```python +import plasma +from plasma import plasma_stick + +LEDS = 30 +FPS = 60 + +led_strip = plasma.WS2812(LEDS, 0, 0, plasma_stick.DAT) +``` + Start the LED strip by calling `start`. This sets up a timer which tells the RP2040 to DMA the pixel data into the PIO (a fast, asyncronous memory->peripheral copy) at the specified framerate. ```python @@ -54,12 +70,6 @@ led_strip.start(FPS) Some WS2812-style LED strips have varying colour orders and support an additional white element. Two keyword arguments are supplied to configure this: ```python -import plasma -from plasma import plasma2040 - -LEDS = 30 -FPS = 60 - led_strip = plasma.WS2812(LEDS, 0, 0, plasma2040.DAT, rgbw=True, color_order=plasma.COLOR_ORDER_GRB) ``` @@ -92,16 +102,6 @@ Set the first LED - `0` - to Red `0.0`: led_strip.set_hsv(0, 0.0, 1.0, 1.0) ``` -### Set Brightness - -APA102 pixels support global brightness, allowing their brightness to be specified independent of their colour. You can set the overall brightness of your strip by calling: - -```python -led_strip.set_brightness(15) -``` - -You can set brightness from `0` to `31`. This directly maps to the 5-bit brightness value sent to the APA102 LEDs. - ## APA102 ### Getting Started @@ -144,6 +144,16 @@ Set the first LED - `0` - to Red `0.0`: led_strip.set_hsv(0, 0.0, 1.0, 1.0) ``` +### Set Brightness + +APA102 pixels support global brightness, allowing their brightness to be specified independent of their colour. You can set the overall brightness of your strip by calling: + +```python +led_strip.set_brightness(15) +``` + +You can set brightness from `0` to `31`. This directly maps to the 5-bit brightness value sent to the APA102 LEDs. + ## Using the Buttons & RGB LED The `pimoroni` module contains `Button` and `RGBLED` classes to simplify button debounce, auto-repeat and PWM'ing an RGB LED. @@ -212,7 +222,7 @@ led.set_rgb(0, 0, 255) # Full blue ## Measuring LED Strip Current Draw -Plasma 2040 feasures low-side current sensing, letting you measure how much current a strip of LEDs is drawing. This could be used just for monitoring, or as a way to reduce the maximum brightness of a strip to keep its current draw within the range of the USB port or power supply being used. +Plasma 2040 features low-side current sensing, letting you measure how much current a strip of LEDs is drawing. This could be used just for monitoring, or as a way to reduce the maximum brightness of a strip to keep its current draw within the range of the USB port or power supply being used. The `pimoroni` module contains an `Analog` class to simplify the reading of this current draw. From 8f2837d93056a43e1b49de9def3c673fa38a13ca Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Tue, 18 Oct 2022 15:17:10 +0100 Subject: [PATCH 21/23] add a bit of onboard led flashage --- micropython/examples/plasma_stick/cheerlights.py | 9 +++++++++ micropython/examples/plasma_stick/weather.py | 12 ++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/micropython/examples/plasma_stick/cheerlights.py b/micropython/examples/plasma_stick/cheerlights.py index eb1d6b2a..70fcb47d 100644 --- a/micropython/examples/plasma_stick/cheerlights.py +++ b/micropython/examples/plasma_stick/cheerlights.py @@ -5,6 +5,7 @@ import urequests import time import plasma from plasma import plasma_stick +from machine import Pin ''' This Plasma Stick example sets your LED strip to the current #cheerlights colour. @@ -70,6 +71,9 @@ def hex_to_rgb(hex): return r, g, b +# set up the Pico W's onboard LED +pico_led = Pin('LED', Pin.OUT) + # set up the WS2812 / NeoPixel™ LEDs led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma_stick.DAT) @@ -94,6 +98,11 @@ while True: print('Data obtained!') r.close() + # flash the onboard LED after getting data + pico_led.value(True) + time.sleep(0.2) + pico_led.value(False) + # extract hex colour from the data hex = j['field2'] diff --git a/micropython/examples/plasma_stick/weather.py b/micropython/examples/plasma_stick/weather.py index 190cd1e3..934dbc2e 100644 --- a/micropython/examples/plasma_stick/weather.py +++ b/micropython/examples/plasma_stick/weather.py @@ -7,7 +7,7 @@ import plasma from plasma import plasma_stick # Random functions! randrange is for picking integers from a range, and uniform is for floats. from random import randrange, uniform -from machine import Timer +from machine import Timer, Pin import gc """ @@ -15,7 +15,7 @@ Weather in a bottle! This Plasma Stick example connects to Open Meteo to access the current weather conditions. It then does some cool weather appropriate stuff with LEDs. Find out more about the Open Meteo API at https://open-meteo.com -Based on original code by AxWax <3 https://github.com/axwax/Open-Meteo-Inky-Pack +Based on original code by AxWax: https://github.com/axwax/Open-Meteo-Inky-Pack """ # Set how many LEDs you have @@ -103,6 +103,11 @@ Conditions = {WEATHERCODES[weathercode]} Last Open-Meteo update: {datetime_arr[0]}, {datetime_arr[1]} """) + # flash the onboard LED after getting data + pico_led.value(True) + time.sleep(0.2) + pico_led.value(False) + # the rest of our functions are for animations! def display_current(): @@ -217,6 +222,9 @@ current_leds = [[0] * 3 for i in range(NUM_LEDS)] # Create an list of [r, g, b] values that will hold target LED colours, to move towards target_leds = [[0] * 3 for i in range(NUM_LEDS)] +# set up the Pico W's onboard LED +pico_led = Pin('LED', Pin.OUT) + # set up the WS2812 / NeoPixel™ LEDs led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma_stick.DAT) From 490d21f7e086096f6eaa99ad3685626d2496dcb2 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Tue, 18 Oct 2022 15:49:59 +0100 Subject: [PATCH 22/23] seems ok without gc.collect() --- micropython/examples/plasma_stick/weather.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/micropython/examples/plasma_stick/weather.py b/micropython/examples/plasma_stick/weather.py index 934dbc2e..f8d7e169 100644 --- a/micropython/examples/plasma_stick/weather.py +++ b/micropython/examples/plasma_stick/weather.py @@ -8,14 +8,13 @@ from plasma import plasma_stick # Random functions! randrange is for picking integers from a range, and uniform is for floats. from random import randrange, uniform from machine import Timer, Pin -import gc """ Weather in a bottle! This Plasma Stick example connects to Open Meteo to access the current weather conditions. It then does some cool weather appropriate stuff with LEDs. Find out more about the Open Meteo API at https://open-meteo.com -Based on original code by AxWax: https://github.com/axwax/Open-Meteo-Inky-Pack +Based on original code by AxWax <3 https://github.com/axwax/Open-Meteo-Inky-Pack """ # Set how many LEDs you have @@ -90,7 +89,6 @@ def get_data(): j = r.json() print("Data obtained!") r.close() - gc.collect() # protecc the RAM # parse relevant data from JSON current = j["current_weather"] @@ -102,7 +100,7 @@ def get_data(): Conditions = {WEATHERCODES[weathercode]} Last Open-Meteo update: {datetime_arr[0]}, {datetime_arr[1]} """) - + # flash the onboard LED after getting data pico_led.value(True) time.sleep(0.2) @@ -260,4 +258,3 @@ while True: move_to_target() # nudge our current colours closer to the target colours display_current() # display current colours to strip - gc.collect() # try and conserve RAM From f43293adf4bffc4c8d3dfaf599d9dc0a9314dd13 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Tue, 18 Oct 2022 15:53:20 +0100 Subject: [PATCH 23/23] linting --- micropython/examples/plasma_stick/weather.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/micropython/examples/plasma_stick/weather.py b/micropython/examples/plasma_stick/weather.py index f8d7e169..00df89de 100644 --- a/micropython/examples/plasma_stick/weather.py +++ b/micropython/examples/plasma_stick/weather.py @@ -100,7 +100,7 @@ def get_data(): Conditions = {WEATHERCODES[weathercode]} Last Open-Meteo update: {datetime_arr[0]}, {datetime_arr[1]} """) - + # flash the onboard LED after getting data pico_led.value(True) time.sleep(0.2) @@ -257,4 +257,3 @@ while True: move_to_target() # nudge our current colours closer to the target colours display_current() # display current colours to strip -