Merge pull request #442 from pimoroni/cheerlights
Add Cheerlights example for Pico W / Pico Explorer
This commit is contained in:
commit
e519396876
|
@ -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.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
SSID = ""
|
||||
PSK = ""
|
|
@ -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)
|
|
@ -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")
|
Loading…
Reference in New Issue