Merge pull request #442 from pimoroni/cheerlights

Add Cheerlights example for Pico W / Pico Explorer
This commit is contained in:
Philip Howard 2022-07-14 16:41:32 +01:00 committed by GitHub
commit e519396876
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 260 additions and 0 deletions

View File

@ -0,0 +1,73 @@
# Pico Explorer MicroPython Examples <!-- omit in toc -->
- [PicoGraphics](#picographics)
- [Non-Wireless Examples](#non-wireless-examples)
- [Balls Demo](#balls-demo)
- [Button Test](#button-test)
- [Demo](#demo)
- [Noise](#noise)
- [Rainbow](#rainbow)
- [Thermometer](#thermometer)
- [Weather Station (BME280)](#weather-station-bme280)
- [Weather Station (BME68X)](#weather-station-bme68x)
- [Wireless Examples](#wireless-examples)
- [Cheerlights](#cheerlights)
## PicoGraphics
You can draw on Pico Explorer's display using our tiny PicoGraphics display library.
- [PicoGraphics MicroPython function reference](../../modules/picographics)
## Non-Wireless Examples
### Balls Demo
[balls_demo.py](balls_demo.py)
LCD demo showing 100 bouncy balls!
### Button Test
[button_test.py](button_test.py)
This example shows you a simple, non-interrupt way of reading Pico Explorer's buttons with a loop that checks to see if buttons are pressed.
### Demo
[demo.py](demo.py)
A demo of all Pico Explorer's functions. Connect analog inputs like potentiometers up to ADC0-ADC3 and motors to the motor channels for best results. Connect AUDIO to GP0 with a jumper wire to hear noise.
### Noise
[noise.py](noise.py)
This example shows you how you can use Pico Explorer's onboard buzzer as a speaker to play different notes and string them together into a bleepy tune (you'll need to connect AUDIO to GP0 with a jumper wire to hear noise).
### Rainbow
[rainbow.py](rainbow.py)
This example borrows a CircuitPython hsv to rgb function to cycle through some rainbows on Pico Explorer's screen.
### Thermometer
[thermometer.py](thermometer.py)
This example takes the temperature from the Pico's onboard temperature sensor, and displays it on Pico Explorer, along with a little pixelly graph.
### Weather Station (BME280)
[weatherstation_BME280.py](weatherstation_BME280.py)
Plug a [BME280 breakout](https://shop.pimoroni.com/products/bme280-breakout) into your Pico Explorer and make a little indoor weather station, with barometer style descriptions.
### Weather Station (BME68X)
[weatherstation_BME68X.py](weatherstation_BME68X.py)
Plug a [BME680](https://shop.pimoroni.com/products/bme680-breakout) or [BME688](https://shop.pimoroni.com/products/bme688-breakout) breakout into your Pico Explorer to make a little indoor weather station, with barometer style descriptions.
## Wireless Examples
The wireless examples need `network_manager.py` and `WIFI_CONFIG.py` 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).
You'll also need to install the `micropython-urllib.urequest` library using Thonny's 'Tools' > 'Manage Packages'.
### Cheerlights
[cheerlights.py](cheerlights.py)
This Pico W example sets your Pico Explorer's screen (and optionally, a [RGB LED](https://shop.pimoroni.com/products/led-rgb-clear-common-cathode)) to the current #cheerlights colour.

View File

@ -0,0 +1,2 @@
SSID = ""
PSK = ""

View File

@ -0,0 +1,100 @@
import WIFI_CONFIG
from network_manager import NetworkManager
import uasyncio
from urllib import urequest
from picographics import PicoGraphics, DISPLAY_PICO_EXPLORER
import time
import ujson
from pimoroni import RGBLED
"""
This Pico W example sets your Pico Explorer's screen to the current #cheerlights colour.
Find out more about Cheerlights at https://cheerlights.com/
If you wire up a four legged RGB LED to GP0, GP1 and GP2 (and the long leg to ground)
it will change the colour of that too!
"""
# WIFI settings
WIFI_COUNTRY = "GB" # Changeme!
URL = "http://api.thingspeak.com/channels/1417/field/2/last.json"
UPDATE_INTERVAL = 120 # refresh interval in secs. Be nice to free APIs!
def status_handler(mode, status, ip):
# connect to the internets
display.set_pen(BLACK)
display.clear()
display.set_pen(WHITE)
display.text("Network: {}".format(WIFI_CONFIG.SSID), 10, 10, scale=2)
status_text = "Connecting..."
if status is not None:
if status:
status_text = "Connection successful!"
else:
status_text = "Connection failed!"
display.text(status_text, 10, 30, scale=2)
display.text("IP: {}".format(ip), 10, 60, scale=2)
display.update()
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 wifi
network_manager = NetworkManager(WIFI_COUNTRY, status_handler=status_handler)
# set up the display
display = PicoGraphics(display=DISPLAY_PICO_EXPLORER)
display.set_backlight(1.0)
# some constants we'll use for drawing
WHITE = display.create_pen(255, 255, 255)
BLACK = display.create_pen(0, 0, 0)
WIDTH, HEIGHT = display.get_bounds()
display.set_font("bitmap8")
# set up an old school 4 pin RGB LED connected to GP0, GP1 and GP2
led = RGBLED(0, 1, 2, invert=False)
while True:
# connect to wifi
uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK))
# open the json file
print(f"Requesting URL: {URL}")
socket = urequest.urlopen(URL)
data = ujson.load(socket)
socket.close()
print("Data obtained!")
# extract hex colour from the data
hex = data['field2']
# and convert it to RGB
r, g, b = hex_to_rgb(hex)
# draw stuff on the screen
colour = display.create_pen(r, g, b)
display.set_pen(colour)
display.clear()
display.set_pen(BLACK)
display.text(hex, 10, 10, WIDTH - 10, scale=6)
display.text("Tweet a colour at #cheerlights to change!", 10, 130, WIDTH - 10, scale=3)
display.update()
print(f"Screen set to {hex}")
# light up RGB LED
led.set_rgb(r, g, b)
print(f"RGB LED set to {hex}")
# sleep
print(f"""Sleeping for {UPDATE_INTERVAL} seconds.
""")
time.sleep(UPDATE_INTERVAL)

View File

@ -0,0 +1,85 @@
import rp2
import network
import machine
import uasyncio
class NetworkManager:
_ifname = ("Client", "Access Point")
def __init__(self, country="GB", client_timeout=30, access_point_timeout=5, status_handler=None):
rp2.country(country)
self._ap_if = network.WLAN(network.AP_IF)
self._sta_if = network.WLAN(network.STA_IF)
self._mode = network.STA_IF
self._client_timeout = client_timeout
self._access_point_timeout = access_point_timeout
self._status_handler = status_handler
self.UID = ("{:02X}" * 8).format(*machine.unique_id())
def isconnected(self):
return self._sta_if.isconnected() or self._ap_if.isconnected()
def ifaddress(self):
if self._sta_if.isconnected():
return self._sta_if.ifconfig()[0]
if self._ap_if.isconnected():
return self._ap_if.ifconfig()[0]
return '0.0.0.0'
def disconnect(self):
if self._sta_if.isconnected():
self._sta_if.disconnect()
if self._ap_if.isconnected():
self._ap_if.disconnect()
async def wait(self, mode):
while not self.isconnected():
self._handle_status(mode, None)
await uasyncio.sleep_ms(1000)
def _handle_status(self, mode, status):
if self._status_handler is not None:
self._status_handler(self._ifname[mode], status, self.ifaddress())
async def client(self, ssid, psk):
if self._sta_if.isconnected():
return
self._ap_if.disconnect()
self._ap_if.active(False)
self._ap_if.deinit()
self._sta_if = network.WLAN(network.STA_IF)
self._sta_if.active(True)
self._sta_if.connect(ssid, psk)
try:
await uasyncio.wait_for(self.wait(network.STA_IF), self._client_timeout)
self._handle_status(network.STA_IF, True)
except uasyncio.TimeoutError:
self._sta_if.active(False)
self._handle_status(network.STA_IF, False)
raise RuntimeError("WIFI Client Failed")
async def access_point(self):
if self._ap_if.isconnected():
return
self._sta_if.disconnect()
self._sta_if.active(False)
self._sta_if.deinit()
self._ap_if = network.WLAN(network.AP_IF)
self._ap_if.active(True)
try:
await uasyncio.wait_for(self.wait(network.AP_IF), self._access_point_timeout)
self._handle_status(network.AP_IF, True)
except uasyncio.TimeoutError:
self._sta_if.active(False)
self._handle_status(network.AP_IF, False)
raise RuntimeError("WIFI AP Failed")