Merge pull request #795 from pimoroni/patch/stellar-examples

Stellar: tidy examples
pull/803/head
Hel Gibbons 2023-07-04 19:06:17 +01:00 zatwierdzone przez GitHub
commit 25237c54ce
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
38 zmienionych plików z 835 dodań i 1690 usunięć

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -12,6 +12,7 @@
- [Nostalgia Prompt](#nostalgia-prompt)
- [Rainbow](#rainbow)
- [Scrolling Text](#scrolling-text)
- [Thermometer](#thermometer)
- [Today](#today)
- [Wireless Examples](#wireless-examples)
- [Cheerlights History](#cheerlights-history)
@ -19,10 +20,13 @@
- [Exchange Ticker](#exchange-ticker)
- [HTTP Text](#http-text)
- [Weather](#weather)
- [NumPy examples](#numpy-examples)
- [NumPy Examples](#numpy-examples)
- [Other Examples](#other-examples)
- [CO2](#co2)
- [Encoder Wheel](#encoder-wheel)
- [Thermometer (BME280)](#thermometer-bme280)
- [Thermometer (BME68x)](#thermometer-bme68x)
- [Launch (Demo Reel)](#launch-demo-reel)
- [Other Resources](#other-resources)
## About Stellar Unicorn
@ -50,6 +54,8 @@ The easiest way to start displaying cool stuff on Stellar Unicorn is using our S
Clock example with (optional) NTP synchronization. You can adjust the brightness with LUX + and -, and resync the time by pressing A.
This example uses a custom tiny bitmap font, find 3x5.bitmapfont in [fonts](../../common/fonts) and copy it to your Pico W.
### Eighties Super Computer
[eighties_super_computer.py](eighties_super_computer.py)
@ -103,6 +109,12 @@ Some good old fashioned rainbows! You can adjust the cycling speed with A and B,
Display scrolling wisdom, quotes or greetz. You can adjust the brightness with LUX + and -.
### Thermometer
[thermometer_pico.py](thermometer_pico.py)
Shows the temperature (from the Pico W's internal sensor) against an appropriately coloured pulsing blob.
### Today
[today.py](today.py)
@ -153,9 +165,16 @@ Requires `logging.mpy` and `tinyweb` from [micropython/examples/common](../../ex
[weather](weather)
Display current weather data from the [Open-Meteo](https://open-meteo.com/) weather API.
Display current weather data from the [Open-Meteo](https://open-meteo.com/) weather API. Make sure to copy across the `icons` folder to your Unicorn.
## NumPy examples
Buttons:
A - show / hide temperature
B - swap between Celsius and Fahrenheit
C - randomly select a weather icon
D - add rainbows
LUX + and - adjust brightness
## NumPy Examples
[numpy](numpy)
@ -163,16 +182,33 @@ The examples in the folder use `numpy`-like array functions contained in the `ul
## Other Examples
These examples use additional hardware.
### CO2
[co2.py](co2.py)
Add a [SCD41 sensor breakout](https://shop.pimoroni.com/products/scd41-co2-sensor-breakout) to make an carbon dioxide detector. Press A, B and C to switch between modes.
This example uses a custom tiny bitmap font, find 3x5.bitmapfont in [fonts](../../common/fonts) and copy it to your Pico W.
### Encoder Wheel
[encoder_wheel.py](encoder_wheel.py)
This example uses [RGB Encoder Wheel breakout](https://shop.pimoroni.com/products/rgb-encoder-wheel-breakout) to make an RGB colour picker. Use the encoder wheel to pick a hue and view the RGB breakdown of that colour on the Unicorn display (you can adjust saturation and brightness using the buttons on the breakout too).
### Thermometer (BME280)
[thermometer_bme280.py](thermometer_bme280.py)
Shows temperature, humidity and pressure (from a [BME280 sensor breakout](https://shop.pimoroni.com/products/bme280-breakout)) against an appropriately coloured pulsing blob.
### Thermometer (BME68x)
[thermometer_bme68x.py](thermometer_bme68x.py)
Shows temperature, humidity and pressure (from a [BME680](https://shop.pimoroni.com/products/bme680-breakout) or [BME688](https://shop.pimoroni.com/products/bme688-breakout) sensor breakout) against an appropriately coloured pulsing blob.
### Launch (Demo Reel)
[launch](launch)
If you want to get the demo reel that Stellar Unicorn ships with back, copy the contents of this `launch` folder to your Pico W.
## Other Resources
Here are some cool Stellar Unicorn community projects and resources that you might find useful / inspirational! Note that code at the links below has not been tested by us and we're not able to offer support with it.
- :link: [Green Energy Display with Stellar Unicorn](https://www.hackster.io/andreas-motzek/clock-and-green-energy-display-with-stellar-unicorn-641dcb)
- :link: [stellar-emoji-react - paint emojis from a computer, phone or tablet](https://github.com/chriscareycode/stellar-unicorn/tree/main/stellar-emoji-react)
- :link: [stellar-paste - paste images from the clipboard to Stellar Unicorn](https://github.com/chriscareycode/stellar-unicorn/tree/main/stellar-paste)

Wyświetl plik

@ -8,6 +8,8 @@
# WIFI_PASSWORD = "Your WiFi password"
#
# Clock synchronizes time on start, and resynchronizes if you press the A button
#
# This example uses a custom tiny font - find 3x5.bitmapfont in pimoroni-pico/fonts
import time
import math
@ -193,7 +195,7 @@ def redraw_display_if_reqd():
gradient_background(hue, sat, val,
hue + HUE_OFFSET, sat, val)
clock = "{:02}:{:02}:{:02}".format(hour, minute, second)
clock = "{:02} {:02}".format(hour, minute)
# calculate text position so that it is centred
w = graphics.measure_text(clock, 1)
@ -206,7 +208,7 @@ def redraw_display_if_reqd():
# set the font
graphics.set_font("bitmap6")
graphics.set_font(open("3x5.bitmapfont", "rb").read())
su.set_brightness(0.5)
sync_time()

Wyświetl plik

@ -0,0 +1,104 @@
# Add a SCD41 sensor breakout to your Stellar Unicorn to make a handy CO2 detector!
# https://shop.pimoroni.com/products/scd41-co2-sensor-breakout
# Press A for CO2, B for temperature and C for humidity
# This example uses a custom tiny font - find 3x5.bitmapfont in pimoroni-pico/fonts
from stellar import StellarUnicorn
from picographics import PicoGraphics, DISPLAY_STELLAR_UNICORN as DISPLAY
import breakout_scd41
from pimoroni_i2c import PimoroniI2C
from pimoroni import BREAKOUT_GARDEN_I2C_PINS
su = StellarUnicorn()
graphics = PicoGraphics(DISPLAY)
i2c = PimoroniI2C(**BREAKOUT_GARDEN_I2C_PINS)
# 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
# some pen colours to use
BLACK = graphics.create_pen(0, 0, 0)
WHITE = graphics.create_pen(255, 255, 255)
# some other variables to keep track of stuff
mode = "co2"
flashy_light = False
# sets up a handy function we can call to clear the screen
def clear():
graphics.set_pen(BLACK)
graphics.clear()
# set up
breakout_scd41.init(i2c)
breakout_scd41.start()
graphics.set_font(open("3x5.bitmapfont", "rb").read())
graphics.set_pen(WHITE)
graphics.text("WAIT", 0, 0, scale=1)
su.update(graphics)
while True:
if su.is_pressed(StellarUnicorn.SWITCH_A):
mode = "co2"
if su.is_pressed(StellarUnicorn.SWITCH_B):
mode = "temp"
if su.is_pressed(StellarUnicorn.SWITCH_C):
mode = "humidity"
if breakout_scd41.ready():
clear()
# read the sensor
co2, temperature, humidity = breakout_scd41.measure()
# calculate a colour from the co2 reading
hue = max(0, HUE_START + ((co2 - MIN) * (HUE_END - HUE_START) / (MAX - MIN)))
# draw the border and background
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 1.0, 0.8))
graphics.clear()
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 1.0, 0.2))
graphics.rectangle(1, 1, 14, 14)
graphics.set_pen(WHITE)
if mode == "co2":
# draw the co2 level
co2_string = str(co2)
if co2 < 1000:
graphics.text(f"{co2:.0f}", 2, 2, scale=1, fixed_width=True)
else:
graphics.text(f"{co2_string[0]}", 1, 2, scale=1, fixed_width=True)
graphics.text(f"{co2_string[1]}K", 7, 2, scale=1, fixed_width=True)
graphics.pixel(5, 6)
graphics.text("PPM", 3, 9, scale=1)
if mode == "temp":
# draw the temperature
graphics.text("T:", 2, 2, scale=1)
graphics.text(f"{temperature:.0f}°", 2, 8, scale=1, fixed_width=True)
if mode == "humidity":
# draw the temperature
graphics.text("H:", 2, 2, scale=1)
graphics.text(f"{humidity:.0f}%", 2, 8, scale=1, fixed_width=True)
# flash the top right pixel to show the sensor's been read
if flashy_light is False:
graphics.pixel(15, 0)
flashy_light = True
else:
flashy_light = False
su.update(graphics)

Wyświetl plik

@ -0,0 +1,168 @@
import time
from pimoroni_i2c import PimoroniI2C
from pimoroni import BREAKOUT_GARDEN_I2C_PINS
from breakout_encoder_wheel import BreakoutEncoderWheel, UP, DOWN, LEFT, RIGHT, CENTRE, NUM_LEDS
from stellar import StellarUnicorn
from picographics import PicoGraphics, DISPLAY_STELLAR_UNICORN
"""
Create a colour wheel on the Encoder Wheel's LED ring, and use all functions of the wheel to interact with it.
Draw bars on the Unicorn to represent the currently selected RGB value
Rotate the wheel to select a Hue
Press the up direction to increase Brightness
Press the down direction to decrease Brightness
Press the left direction to decrease Saturation
Press the right direction to increase Saturation
Press the centre to hide the selection marker
Press Ctrl+C to stop the program.
"""
# Constants
BRIGHTNESS_STEP = 0.01 # How much to increase or decrease the brightness each update
SATURATION_STEP = 0.01 # How much to increase or decrease the saturation each update
UPDATES = 50 # How many times to update the LEDs per second
UPDATE_RATE_US = 1000000 // UPDATES
# Create a new BreakoutEncoderWheel
i2c = PimoroniI2C(**BREAKOUT_GARDEN_I2C_PINS)
wheel = BreakoutEncoderWheel(i2c)
# Set up the Unicron
su = StellarUnicorn()
su.set_brightness(1.0)
graphics = PicoGraphics(DISPLAY_STELLAR_UNICORN)
# Variables
brightness = 1.0
saturation = 1.0
position = 0
changed = True
last_centre_pressed = False
# From CPython Lib/colorsys.py
def hsv_to_rgb(h, s, v):
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
# Simple function to clamp a value between 0.0 and 1.0
def clamp01(value):
return max(min(value, 1.0), 0.0)
# Sleep until a specific time in the future. Use this instead of time.sleep() to correct for
# inconsistent timings when dealing with complex operations or external communication
def sleep_until(end_time):
time_to_sleep = time.ticks_diff(end_time, time.ticks_us())
if time_to_sleep > 0:
time.sleep_us(time_to_sleep)
while True:
# Record the start time of this loop
start_time = time.ticks_us()
# If up is pressed, increase the brightness
if wheel.pressed(UP):
brightness += BRIGHTNESS_STEP
changed = True # Trigger a change
# If down is pressed, decrease the brightness
if wheel.pressed(DOWN):
brightness -= BRIGHTNESS_STEP
changed = True # Trigger a change
# If right is pressed, increase the saturation
if wheel.pressed(RIGHT):
saturation += SATURATION_STEP
changed = True # Trigger a change
# If left is pressed, decrease the saturation
if wheel.pressed(LEFT):
saturation -= SATURATION_STEP
changed = True # Trigger a change
# Limit the brightness and saturation between 0.0 and 1.0
brightness = clamp01(brightness)
saturation = clamp01(saturation)
# Check if the encoder has been turned
if wheel.delta() != 0:
# Update the position based on the count change
position = wheel.step()
changed = True # Trigger a change
# If centre is pressed, trigger a change
centre_pressed = wheel.pressed(CENTRE)
if centre_pressed != last_centre_pressed:
changed = True
last_centre_pressed = centre_pressed
# Was a change triggered?
if changed:
# Print the colour at the current hue, saturation, and brightness
r, g, b = [int(c * 255) for c in hsv_to_rgb(position / NUM_LEDS, saturation, brightness)]
# Set the LED at the current position to either the actual colour,
# or an inverted version to show a "selection marker"
if centre_pressed:
wheel.set_rgb(position, r, g, b)
else:
wheel.set_rgb(position, 255, 255, 255)
# Set the LEDs below the current position
for i in range(0, position):
wheel.set_hsv(i, i / NUM_LEDS, saturation, brightness)
# Set the LEDs after the current position
for i in range(position + 1, NUM_LEDS):
wheel.set_hsv(i, i / NUM_LEDS, saturation, brightness)
wheel.show()
changed = False
# set unicron
graphics.set_pen(graphics.create_pen(0, 0, 0))
graphics.clear()
# draw background
graphics.set_pen(graphics.create_pen(30, 30, 30))
graphics.rectangle(0, 1, 16, 4)
graphics.rectangle(0, 6, 16, 4)
graphics.rectangle(0, 11, 16, 4)
# draw bars
graphics.set_pen(graphics.create_pen(r, g, b))
graphics.rectangle(0, 1, int(r / 255 * 16), 4)
graphics.rectangle(0, 6, int(g / 255 * 16), 4)
graphics.rectangle(0, 11, int(b / 255 * 16), 4)
# draw labels
graphics.set_pen(graphics.create_pen(255, 0, 0))
graphics.rectangle(0, 1, 1, 4)
graphics.set_pen(graphics.create_pen(0, 255, 0))
graphics.rectangle(0, 6, 1, 4)
graphics.set_pen(graphics.create_pen(0, 0, 255))
graphics.rectangle(0, 11, 1, 4)
su.update(graphics)
# Sleep until the next update, accounting for how long the above operations took to perform
sleep_until(time.ticks_add(start_time, UPDATE_RATE_US))

Wyświetl plik

@ -25,13 +25,13 @@ currency_rate = ""
rate_keys = []
# display options
line_1_line = -2
line_2_line = 9
line_3_line = 20
line_1_line = -1
line_2_line = 4
line_3_line = 9
ref_currency_index = 0
cycles_per_sequence = 120
cycles_per_sequence = 200
su = StellarUnicorn()
graphics = PicoGraphics(DISPLAY)
@ -61,8 +61,8 @@ def get_data(currency_selected):
graphics.set_pen(graphics.create_pen(20, 20, 20))
graphics.clear()
graphics.set_pen(graphics.create_pen(100, 100, 100))
graphics.text("Get", 0, 10, scale=1, spacing=1)
graphics.text("data", 8, 16, scale=1, spacing=1)
graphics.text("Get", 0, 0, scale=1)
graphics.text("data", 0, 7, scale=1)
su.update(graphics)
gc.collect()
# open the json file
@ -88,14 +88,11 @@ def update_display(cycle):
graphics.set_pen(graphics.create_pen(20, 20, 20))
graphics.clear()
graphics.set_pen(graphics.create_pen(100, 0, 0))
graphics.text(ref_currency_name, calculate_xpos((len(ref_currency_name)), cycle), line_1_line, scale=2, spacing=1)
graphics.text(ref_currency_name, calculate_xpos((len(ref_currency_name)), cycle), line_1_line, scale=1)
graphics.set_pen(graphics.create_pen(100, 100, 0))
if len(currency_symbol) > 3:
graphics.text(currency_symbol, calculate_xpos((len(currency_symbol)), cycle), line_2_line, scale=2, spacing=1)
else:
graphics.text(currency_symbol, 0, line_2_line, scale=2, spacing=1)
graphics.text(currency_symbol, calculate_xpos((len(currency_symbol)), cycle), line_2_line, scale=1)
graphics.set_pen(graphics.create_pen(0, 100, 100))
graphics.text(currency_rate, calculate_xpos((len(currency_rate)), cycle), line_3_line, scale=2, spacing=1)
graphics.text(currency_rate, calculate_xpos((len(currency_rate)), cycle), line_3_line, scale=1)
def update_base_currency(index):

Wyświetl plik

@ -173,7 +173,7 @@ async def message_update():
graphics.set_pen(graphics.create_pen(int(BACKGROUND_COLOUR[0]), int(BACKGROUND_COLOUR[1]), int(BACKGROUND_COLOUR[2])))
graphics.clear()
outline_text(MESSAGE, x=PADDING - shift, y=11)
outline_text(MESSAGE, x=PADDING - shift, y=4)
# update the display
su.update(graphics)

Wyświetl plik

@ -13,7 +13,7 @@ You can adjust the brightness with LUX + and -.
su = StellarUnicorn()
graphics = PicoGraphics(DISPLAY)
blob_count = 10
blob_count = 5
class Blob():

Wyświetl plik

@ -0,0 +1,134 @@
import time
from stellar import StellarUnicorn
from picographics import PicoGraphics, DISPLAY_STELLAR_UNICORN
from pimoroni_i2c import PimoroniI2C
from pimoroni import BREAKOUT_GARDEN_I2C_PINS
from breakout_bme280 import BreakoutBME280
"""
Reads the temperature from a BME280
... and displays an appropriately coloured pulsing blob.
Buttons:
A - Show temperature
B - Show humidity
C - Show pressure
"""
# 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
# rainbow party mode
rainbow_orb = False
# set up the Unicron
su = StellarUnicorn()
graphics = PicoGraphics(DISPLAY_STELLAR_UNICORN)
# set up the sensor
i2c = PimoroniI2C(**BREAKOUT_GARDEN_I2C_PINS)
bme = BreakoutBME280(i2c)
# set up constants and variables for drawing
WIDTH, HEIGHT = graphics.get_bounds()
BLACK = graphics.create_pen(0, 0, 0)
WHITE = graphics.create_pen(255, 255, 255)
forward = True
orb_brightness = 0.5
hue = 0.0
mode = "temperature"
graphics.set_font("bitmap8")
while True:
if su.is_pressed(StellarUnicorn.SWITCH_A):
mode = "temperature"
print(f"mode = {mode}")
elif su.is_pressed(StellarUnicorn.SWITCH_B):
mode = "humidity"
print(f"mode = {mode}")
elif su.is_pressed(StellarUnicorn.SWITCH_C):
mode = "pressure"
print(f"mode = {mode}")
# read the onboard sensor
# the following two lines do some maths to convert the number from the temp sensor into celsius
temperature, pressure, humidity = bme.read()
print(f"""
Temperature: {temperature:.2f} °C
Humidity: {humidity:.2f} %
Pressure: {pressure/100:.2f} hPa
""")
# fills the screen with black
graphics.set_pen(BLACK)
graphics.clear()
# draw a weird orb:
# three overlapping circles with varying saturations
if rainbow_orb is True:
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 0.5, orb_brightness))
graphics.circle(8, 8, 7)
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 0.7, orb_brightness))
graphics.circle(7, 7, 7)
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 1.0, orb_brightness))
graphics.circle(7, 7, 5)
hue += 0.01 * 360
else:
# calculate a colour from the temperature
hue = max(0, HUE_START + ((temperature - MIN) * (HUE_END - HUE_START) / (MAX - MIN)))
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 0.6, orb_brightness))
graphics.circle(8, 8, 7)
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 0.8, orb_brightness))
graphics.circle(7, 7, 7)
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 1.0, orb_brightness))
graphics.circle(7, 7, 5)
# pulse the orb!
if forward is True:
orb_brightness += 0.01
if orb_brightness >= 0.7:
orb_brightness = 0.7
forward = False
if forward is False:
orb_brightness -= 0.01
if orb_brightness <= 0.3:
orb_brightness = 0.3
forward = True
# select a pen colour for the text
# try BLACK for a funky negative space effect
graphics.set_pen(WHITE)
if mode == "temperature":
graphics.text(f"{temperature:.0f}°", 2, 5, scale=1)
# or uncomment these lines if you'd prefer it in Freedom Units
# fahrenheit = (temperature * 9 / 5) + 32
# graphics.text(f"{fahrenheit:.0f}°", 2, 5, scale=1)
if mode == "humidity":
graphics.text(f"{humidity:.0f}%", 1, 5, scale=1)
if mode == "pressure":
if pressure / 100 < 1000:
graphics.text(f"{pressure / 100:.0f} hPa", 1, 0, WIDTH, scale=1)
else:
pressure_string = str(pressure / 100)
graphics.text(f"{pressure_string[0]}.{pressure_string[1]}k hPa", 0, 0, WIDTH, scale=1)
# time to update the display
su.update(graphics)
time.sleep(0.1)

Wyświetl plik

@ -0,0 +1,134 @@
import time
from stellar import StellarUnicorn
from picographics import PicoGraphics, DISPLAY_STELLAR_UNICORN
from pimoroni_i2c import PimoroniI2C
from pimoroni import BREAKOUT_GARDEN_I2C_PINS
from breakout_bme68x import BreakoutBME68X
"""
Reads the temperature from a BME680 or BME688
... and displays an appropriately coloured pulsing blob.
Buttons:
A - Show temperature
B - Show humidity
C - Show pressure
"""
# 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
# rainbow party mode
rainbow_orb = False
# set up the Unicron
su = StellarUnicorn()
graphics = PicoGraphics(DISPLAY_STELLAR_UNICORN)
# set up the sensor
i2c = PimoroniI2C(**BREAKOUT_GARDEN_I2C_PINS)
bme = BreakoutBME68X(i2c)
# set up constants and variables for drawing
WIDTH, HEIGHT = graphics.get_bounds()
BLACK = graphics.create_pen(0, 0, 0)
WHITE = graphics.create_pen(255, 255, 255)
forward = True
orb_brightness = 0.5
hue = 0.0
mode = "temperature"
graphics.set_font("bitmap8")
while True:
if su.is_pressed(StellarUnicorn.SWITCH_A):
mode = "temperature"
print(f"mode = {mode}")
elif su.is_pressed(StellarUnicorn.SWITCH_B):
mode = "humidity"
print(f"mode = {mode}")
elif su.is_pressed(StellarUnicorn.SWITCH_C):
mode = "pressure"
print(f"mode = {mode}")
# read the onboard sensor
# the following two lines do some maths to convert the number from the temp sensor into celsius
temperature, pressure, humidity, gas, status, _, _ = bme.read()
print(f"""
Temperature: {temperature:.2f} °C
Humidity: {humidity:.2f} %
Pressure: {pressure/100:.2f} hPa
""")
# fills the screen with black
graphics.set_pen(BLACK)
graphics.clear()
# draw a weird orb:
# three overlapping circles with varying saturations
if rainbow_orb is True:
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 0.5, orb_brightness))
graphics.circle(8, 8, 7)
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 0.7, orb_brightness))
graphics.circle(7, 7, 7)
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 1.0, orb_brightness))
graphics.circle(7, 7, 5)
hue += 0.01 * 360
else:
# calculate a colour from the temperature
hue = max(0, HUE_START + ((temperature - MIN) * (HUE_END - HUE_START) / (MAX - MIN)))
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 0.6, orb_brightness))
graphics.circle(8, 8, 7)
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 0.8, orb_brightness))
graphics.circle(7, 7, 7)
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 1.0, orb_brightness))
graphics.circle(7, 7, 5)
# pulse the orb!
if forward is True:
orb_brightness += 0.01
if orb_brightness >= 0.7:
orb_brightness = 0.7
forward = False
if forward is False:
orb_brightness -= 0.01
if orb_brightness <= 0.3:
orb_brightness = 0.3
forward = True
# select a pen colour for the text
# try BLACK for a funky negative space effect
graphics.set_pen(WHITE)
if mode == "temperature":
graphics.text(f"{temperature:.0f}°", 2, 5, scale=1)
# or uncomment these lines if you'd prefer it in Freedom Units
# fahrenheit = (temperature * 9 / 5) + 32
# graphics.text(f"{fahrenheit:.0f}°", 2, 5, scale=1)
if mode == "humidity":
graphics.text(f"{humidity:.0f}%", 1, 5, scale=1)
if mode == "pressure":
if pressure / 100 < 1000:
graphics.text(f"{pressure / 100:.0f} hPa", 1, 0, WIDTH, scale=1)
else:
pressure_string = str(pressure / 100)
graphics.text(f"{pressure_string[0]}.{pressure_string[1]}k hPa", 0, 0, WIDTH, scale=1)
# time to update the display
su.update(graphics)
time.sleep(0.1)

Wyświetl plik

@ -0,0 +1,103 @@
from machine import ADC
import time
from stellar import StellarUnicorn
from picographics import PicoGraphics, DISPLAY_STELLAR_UNICORN
"""
Reads the internal temperature sensor on the Pico W...
... and displays an appropriately coloured pulsing blob.
"""
# The range of readings that we want to map to colours
MIN = 15
MAX = 35
# 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
# rainbow party mode
rainbow_orb = False
# set up the Unicron
su = StellarUnicorn()
graphics = PicoGraphics(DISPLAY_STELLAR_UNICORN)
# set up the ADC
sensor_temp = ADC(ADC.CORE_TEMP)
conversion_factor = 3.3 / 65535 # used for calculating a temperature from the raw sensor reading
# set up constants and variables for drawing
WIDTH, HEIGHT = graphics.get_bounds()
BLACK = graphics.create_pen(0, 0, 0)
WHITE = graphics.create_pen(255, 255, 255)
forward = True
orb_brightness = 0.5
hue = 0.0
graphics.set_font("bitmap8")
while True:
# read the onboard 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
print(f"""
Temperature: {temperature:.2f} °C
""")
# fills the screen with black
graphics.set_pen(BLACK)
graphics.clear()
# draw a weird orb:
# three overlapping circles with varying saturations
if rainbow_orb is True:
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 0.5, orb_brightness))
graphics.circle(8, 8, 7)
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 0.7, orb_brightness))
graphics.circle(7, 7, 7)
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 1.0, orb_brightness))
graphics.circle(7, 7, 5)
hue += 0.01 * 360
else:
# calculate a colour from the temperature
hue = max(0, HUE_START + ((temperature - MIN) * (HUE_END - HUE_START) / (MAX - MIN)))
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 0.6, orb_brightness))
graphics.circle(8, 8, 7)
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 0.8, orb_brightness))
graphics.circle(7, 7, 7)
graphics.set_pen(graphics.create_pen_hsv((hue / 360), 1.0, orb_brightness))
graphics.circle(7, 7, 5)
# pulse the orb!
if forward is True:
orb_brightness += 0.01
if orb_brightness >= 0.7:
orb_brightness = 0.7
forward = False
if forward is False:
orb_brightness -= 0.01
if orb_brightness <= 0.3:
orb_brightness = 0.3
forward = True
# draw the temperature
# try BLACK for a funky negative space effect
graphics.set_pen(WHITE)
graphics.text(f"{temperature:.0f}°", 2, 5, scale=1)
# or uncomment these lines if you'd prefer it in Freedom Units
# graphics.set_pen(WHITE)
# fahrenheit = (temperature * 9 / 5) + 32
# graphics.text(f"{fahrenheit:.0f}°", 2, 5, scale=1)
# time to update the display
su.update(graphics)
time.sleep(0.1)

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 776 B

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.1 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.5 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.6 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.6 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 895 B

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.0 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.1 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.0 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.0 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 1.0 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.1 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.1 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.2 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.1 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 909 B

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.3 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.7 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.8 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.7 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 991 B

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.2 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.1 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.2 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.1 KiB

Plik diff jest za duży Load Diff

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 81 KiB

Wyświetl plik

@ -3,9 +3,24 @@ from stellar import StellarUnicorn
from picographics import PicoGraphics, DISPLAY_STELLAR_UNICORN as DISPLAY
import WIFI_CONFIG
from network_manager import NetworkManager
import uasyncio as asyncio
import uasyncio
import urequests
import jpegdec
from random import choice
"""
This example connects to Open Meteo to access the current weather conditions.
It then displays an appropriate weather icon on Stellar Unicorn.
Find out more about the Open Meteo API at https://open-meteo.com
Buttons:
A - show / hide temperature
B - swap between Celsius and Fahrenheit
C - randomly select a weather icon
D - add rainbows
LUX + and - adjust brightness
"""
# Set your latitude/longitude here (find yours by right clicking in Google Maps!)
LAT = 53.38609085276884
@ -13,18 +28,18 @@ LNG = -1.4239983439328177
TIMEZONE = "auto" # determines time zone from lat/long
URL = "http://api.open-meteo.com/v1/forecast?latitude=" + str(LAT) + "&longitude=" + str(LNG) + "&current_weather=true&timezone=" + TIMEZONE
WEATHER_TEXT = ''
user_icon = None
# how often to poll the API, in minutes
UPDATE_INTERVAL = 5
def get_data():
global WEATHER_TEXT, temperature, weathercode
global temperature, weathercode
print(f"Requesting URL: {URL}")
r = urequests.get(URL)
# open the json data
j = r.json()
print("Data obtained!")
print(j)
# parse relevant data from JSON
current = j["current_weather"]
@ -33,8 +48,7 @@ def get_data():
winddirection = calculate_bearing(current["winddirection"])
weathercode = current["weathercode"]
date, now = current["time"].split("T")
WEATHER_TEXT = f"Temp: {temperature}°C Wind Speed: {windspeed}kmph Wind Direction: {winddirection} As of: {date}, {now}"
print(WEATHER_TEXT)
print(f"Temp: {temperature}°C Wind Speed: {windspeed}kmph Wind Direction: {winddirection} As of: {date}, {now}")
r.close()
@ -46,108 +60,138 @@ def calculate_bearing(d):
def status_handler(mode, status, ip):
global MESSAGE
print("Network: {}".format(WIFI_CONFIG.SSID))
# reports wifi connection status
print(mode, status, ip)
print('Connecting to wifi...')
if status is not None:
if status:
print('Wifi connection successful!')
else:
print('Wifi connection failed!')
# create galactic object and graphics surface for drawing
# create objects and picographics surface for drawing
su = StellarUnicorn()
display = PicoGraphics(DISPLAY)
jpeg = jpegdec.JPEG(display)
# some useful constants
WIDTH = StellarUnicorn.WIDTH
HEIGHT = StellarUnicorn.HEIGHT
jpeg = jpegdec.JPEG(display)
TEXT_COLOUR = display.create_pen(200, 0, 200)
BLACK = display.create_pen(0, 0, 0)
RED = display.create_pen(255, 0, 0)
ORANGE = display.create_pen(246, 138, 30)
YELLOW = display.create_pen(255, 216, 0)
GREEN = display.create_pen(0, 121, 64)
BLUE = display.create_pen(0, 0, 255)
INDIGO = display.create_pen(36, 64, 142)
VIOLET = display.create_pen(115, 41, 130)
WHITE = display.create_pen(255, 255, 255)
show_temperature = True
show_fahrenheit = False
show_rainbow = False
def run():
# Setup wifi
# timer variable to keep track of how often to poll the api
timer = UPDATE_INTERVAL * 60.0
su.set_brightness(0.8)
# set up wifi
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}')
# Connect to Wifi network
asyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK))
while (not network_manager.isconnected()):
while True:
# adjust brightness with LUX + and -
if su.is_pressed(StellarUnicorn.SWITCH_BRIGHTNESS_UP):
su.adjust_brightness(+0.05)
print(f"Brightness set to {su.get_brightness()}")
if su.is_pressed(StellarUnicorn.SWITCH_BRIGHTNESS_DOWN):
su.adjust_brightness(-0.05)
print(f"Brightness set to {su.get_brightness()}")
if su.is_pressed(StellarUnicorn.SWITCH_A):
show_temperature = not show_temperature
print(f"Show temperature = {show_temperature}")
# debounce
time.sleep(0.1)
if su.is_pressed(StellarUnicorn.SWITCH_B):
show_fahrenheit = not show_fahrenheit
print(f"Show fahrenheit = {show_fahrenheit}")
# debounce
time.sleep(0.1)
su.set_brightness(1)
run() # Sets up Wifi connection
# I hate this weather, give me another
if su.is_pressed(StellarUnicorn.SWITCH_C):
weathercode = choice([71, 51, 1, 0, 95])
print("Weather icon randomised!")
# debounce
time.sleep(0.1)
# brighten up boring weather with a rainbow
if su.is_pressed(StellarUnicorn.SWITCH_D):
show_rainbow = not show_rainbow
print(f"Show rainbow = {show_rainbow}")
# debounce
time.sleep(0.1)
def outline_text(text, x, y):
display.set_pen(BLACK)
display.text(text, x - 1, y - 1, -1, 1)
display.text(text, x, y - 1, -1, 1)
display.text(text, x + 1, y - 1, -1, 1)
display.text(text, x - 1, y, -1, 1)
display.text(text, x + 1, y, -1, 1)
display.text(text, x - 1, y + 1, -1, 1)
display.text(text, x, y + 1, -1, 1)
display.text(text, x + 1, y + 1, -1, 1)
# we only need to ping the api for data every UPDATE_INTERVAL
if timer >= UPDATE_INTERVAL * 60:
get_data()
timer = 0.0
display.set_pen(WHITE)
display.text(text, x, y, -1, 1)
def draw_page(cycle):
global user_icon
text_cycle = cycle % 1000
cycle = cycle % 4
# Clear the display
display.set_pen(15)
display.clear()
# Draw the page header
display.set_font("bitmap6")
if temperature is not None:
if weathercode is not None:
# Choose an appropriate icon based on the weather code
# Weather codes from https://open-meteo.com/en/docs
if user_icon is not None:
icons = ["icons/snow{0}.jpg".format(cycle + 1), "icons/rain{0}.jpg".format(cycle + 1), "icons/cloud{0}.jpg".format(cycle + 1), "icons/sun{0}.jpg".format(cycle + 1), "icons/storm{0}.jpg".format(cycle + 1)]
jpeg.open_file(icons[user_icon])
else:
if weathercode in [71, 73, 75, 77, 85, 86]: # codes for snow
jpeg.open_file("icons/snow{0}.jpg".format(cycle + 1))
elif weathercode in [51, 53, 55, 56, 57, 61, 63, 65, 66, 67, 80, 81, 82]: # codes for rain
jpeg.open_file("icons/rain{0}.jpg".format(cycle + 1))
elif weathercode in [1, 2, 3, 45, 48]: # codes for cloud
jpeg.open_file("icons/cloud{0}.jpg".format(cycle + 1))
elif weathercode in [0]: # codes for sun
jpeg.open_file("icons/sun{0}.jpg".format(cycle + 1))
elif weathercode in [95, 96, 99]: # codes for storm
jpeg.open_file("icons/storm{0}.jpg".format(cycle + 1))
if weathercode in [71, 73, 75, 77, 85, 86]: # codes for snow
jpeg.open_file("icons/snow.jpg")
elif weathercode in [51, 53, 55, 56, 57, 61, 63, 65, 66, 67, 80, 81, 82]: # codes for rain
jpeg.open_file("icons/rain.jpg")
elif weathercode in [1, 2, 3, 45, 48]: # codes for cloud
jpeg.open_file("icons/cloud.jpg")
elif weathercode in [0]: # codes for sun
jpeg.open_file("icons/sun.jpg")
elif weathercode in [95, 96, 99]: # codes for storm
jpeg.open_file("icons/storm.jpg")
jpeg.decode(0, 0, jpegdec.JPEG_SCALE_FULL)
display.set_pen(TEXT_COLOUR)
outline_text(WEATHER_TEXT, 16 - text_cycle, 0)
if show_rainbow is True:
display.set_pen(VIOLET)
display.circle(WIDTH - 1, HEIGHT - 1, 6)
display.set_pen(BLUE)
display.circle(WIDTH - 1, HEIGHT - 1, 5)
display.set_pen(GREEN)
display.circle(WIDTH - 1, HEIGHT - 1, 4)
display.set_pen(YELLOW)
display.circle(WIDTH - 1, HEIGHT - 1, 3)
display.set_pen(ORANGE)
display.circle(WIDTH - 1, HEIGHT - 1, 2)
display.set_pen(RED)
display.circle(WIDTH - 1, HEIGHT - 1, 1)
# draw the temperature text
if show_temperature is True:
display.set_pen(RED)
if show_fahrenheit is True:
fahrenheit = (temperature * 9 / 5) + 32
# measure the text so we can right align it
text_width = display.measure_text(f"{fahrenheit:.0f}°", scale=1)
display.text(f"{fahrenheit:.0f}°", WIDTH - text_width, 4, WIDTH, scale=1)
else:
# measure the text so we can right align it
text_width = display.measure_text(f"{temperature:.0f}°", scale=1)
display.text(f"{temperature:.0f}°", WIDTH - text_width, 4, WIDTH, scale=1)
else:
display.set_pen(0)
display.set_pen(15)
display.text("Unable to display weather! Check your network settings in WIFI_CONFIG.py", 5, 65, WIDTH, 1)
display.set_pen(RED)
display.text("ERR", 0, 0, WIDTH, 1)
su.update(display)
while 1:
get_data()
for count in range(500):
if su.is_pressed(StellarUnicorn.SWITCH_A):
user_icon = 0
if su.is_pressed(StellarUnicorn.SWITCH_B):
user_icon = 1
if su.is_pressed(StellarUnicorn.SWITCH_C):
user_icon = 2
if su.is_pressed(StellarUnicorn.SWITCH_D):
user_icon = 3
if su.is_pressed(StellarUnicorn.SWITCH_BRIGHTNESS_UP):
user_icon = 4
if su.is_pressed(StellarUnicorn.SWITCH_BRIGHTNESS_DOWN):
user_icon = None
draw_page(count)
time.sleep(0.2)
timer += 0.1
time.sleep(0.1)