From 7f88ab9f022557e7be68a5ffa88c71a0de4d1912 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Tue, 12 Jul 2022 18:33:46 +0100 Subject: [PATCH 1/4] Add cheerlights example --- examples/pico_explorer/README.md | 51 +++++++++ .../examples/pico_explorer/WIFI_CONFIG.py | 2 + .../examples/pico_explorer/cheerlights.py | 101 ++++++++++++++++++ .../examples/pico_explorer/network_manager.py | 85 +++++++++++++++ 4 files changed, 239 insertions(+) create mode 100644 examples/pico_explorer/README.md create mode 100644 micropython/examples/pico_explorer/WIFI_CONFIG.py create mode 100644 micropython/examples/pico_explorer/cheerlights.py create mode 100644 micropython/examples/pico_explorer/network_manager.py diff --git a/examples/pico_explorer/README.md b/examples/pico_explorer/README.md new file mode 100644 index 00000000..1c3d25e5 --- /dev/null +++ b/examples/pico_explorer/README.md @@ -0,0 +1,51 @@ +# Pico Explorer MicroPython Examples + +## 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 + +Simple LCD demo showing 100 bouncy balls! + +### Button Test + +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 + +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 + +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 + +This example borrows a CircuitPython hsv to rgb function to cycle through some rainbows on Pico Explorer's screen. + +### Thermometer + +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) + +Plug a BME280 breakout into your Pico Explorer and make a little indoor weather station, with barometer style descriptions. + +### Weather Station (BME68x) + +Plug a BME680 or BME688 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 + +This Pico W example sets your Pico Explorer's screen to the current #cheerlights colour. \ No newline at end of file diff --git a/micropython/examples/pico_explorer/WIFI_CONFIG.py b/micropython/examples/pico_explorer/WIFI_CONFIG.py new file mode 100644 index 00000000..b54d8867 --- /dev/null +++ b/micropython/examples/pico_explorer/WIFI_CONFIG.py @@ -0,0 +1,2 @@ +SSID = "" +PSK = "" diff --git a/micropython/examples/pico_explorer/cheerlights.py b/micropython/examples/pico_explorer/cheerlights.py new file mode 100644 index 00000000..cc0c35f5 --- /dev/null +++ b/micropython/examples/pico_explorer/cheerlights.py @@ -0,0 +1,101 @@ +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(f"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) + diff --git a/micropython/examples/pico_explorer/network_manager.py b/micropython/examples/pico_explorer/network_manager.py new file mode 100644 index 00000000..74026363 --- /dev/null +++ b/micropython/examples/pico_explorer/network_manager.py @@ -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") From 07ef40bc2becd1425e53b78aa2224e84a8c85618 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Tue, 12 Jul 2022 18:36:01 +0100 Subject: [PATCH 2/4] Add Pico Explorer examples readme --- {examples => micropython/examples}/pico_explorer/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {examples => micropython/examples}/pico_explorer/README.md (100%) diff --git a/examples/pico_explorer/README.md b/micropython/examples/pico_explorer/README.md similarity index 100% rename from examples/pico_explorer/README.md rename to micropython/examples/pico_explorer/README.md From 32455e60920fe89b46ee450adfa1feab2a9d6492 Mon Sep 17 00:00:00 2001 From: helgibbons <50950368+helgibbons@users.noreply.github.com> Date: Tue, 12 Jul 2022 19:43:51 +0100 Subject: [PATCH 3/4] linting cheerlights example and examples readme --- micropython/examples/pico_explorer/README.md | 34 +++++++++++++++---- .../examples/pico_explorer/cheerlights.py | 11 +++--- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/micropython/examples/pico_explorer/README.md b/micropython/examples/pico_explorer/README.md index 1c3d25e5..76bc5db9 100644 --- a/micropython/examples/pico_explorer/README.md +++ b/micropython/examples/pico_explorer/README.md @@ -1,44 +1,64 @@ # Pico Explorer MicroPython Examples +- - [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) -Simple LCD demo showing 100 bouncy balls! +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 into your Pico Explorer and make a little indoor weather station, with barometer style descriptions. +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) +### Weather Station (BME68X) +[weatherstation_BME68X.py](weatherstation_BME68X.py) -Plug a BME680 or BME688 breakout into your Pico Explorer to make a little indoor weather station, with barometer style descriptions. +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 @@ -47,5 +67,7 @@ The wireless examples need `network_manager.py` and `WIFI_CONFIG.py` to be saved 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. -This Pico W example sets your Pico Explorer's screen to the current #cheerlights colour. \ No newline at end of file diff --git a/micropython/examples/pico_explorer/cheerlights.py b/micropython/examples/pico_explorer/cheerlights.py index cc0c35f5..4b078416 100644 --- a/micropython/examples/pico_explorer/cheerlights.py +++ b/micropython/examples/pico_explorer/cheerlights.py @@ -42,7 +42,7 @@ def status_handler(mode, status, ip): 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)) + r, g, b = (int(h[i:i + 2], 16) for i in (0, 2, 4)) return r, g, b @@ -66,17 +66,17 @@ 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(f"Data obtained!") + print("Data obtained!") # extract hex colour from the data hex = data['field2'] - + # and convert it to RGB r, g, b = hex_to_rgb(hex) @@ -93,9 +93,8 @@ while True: # 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) - From d712913f367da24ab5ec0207b392168474130f79 Mon Sep 17 00:00:00 2001 From: Hel Gibbons <50950368+helgibbons@users.noreply.github.com> Date: Tue, 12 Jul 2022 19:50:32 +0100 Subject: [PATCH 4/4] lint readme --- micropython/examples/pico_explorer/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/micropython/examples/pico_explorer/README.md b/micropython/examples/pico_explorer/README.md index 76bc5db9..5d13fbdf 100644 --- a/micropython/examples/pico_explorer/README.md +++ b/micropython/examples/pico_explorer/README.md @@ -1,6 +1,6 @@ # Pico Explorer MicroPython Examples -- - [PicoGraphics](#picographics) +- [PicoGraphics](#picographics) - [Non-Wireless Examples](#non-wireless-examples) - [Balls Demo](#balls-demo) - [Button Test](#button-test)