diff --git a/micropython/examples/pico_explorer/README.md b/micropython/examples/pico_explorer/README.md new file mode 100644 index 00000000..5d13fbdf --- /dev/null +++ b/micropython/examples/pico_explorer/README.md @@ -0,0 +1,73 @@ +# 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) + +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. + 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..4b078416 --- /dev/null +++ b/micropython/examples/pico_explorer/cheerlights.py @@ -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) 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")