I thought I'd briefly document what turned out to be a twisted journey to get MQTT running reliably on a Raspberry Pi Pico W. I was mildly surprised to find the Adafruit documentation in this space to be a little confused (when normally so good), and put this down to the fact that Python-on-a-SoC is a new-and-evolving space.
TL;DR: IDE = Mu; Python = CircuitPython; package/extension management = CircUp (pip3 install circup
).
IDEs
- Mu: works well, despite being relatively feature-poor (e.g. no 'Save As...').
- Thonny: is feature-rich, but is a bit of a mess when it comes to package/extension management (e.g. even the tool and its documentation disagree on whether they're using pip[3], mip, or something else, and PyPI or MicroPython repos).
- VSCode: untested.
Python
- MicroPython (umqtt.simple): unreliable; wait_msg() seems buggy.
- CircuitPython (MiniMQTT): solid, reliable.
- mPython: untested.
Package/Extension Management
- Thonny: seems confused.
- Adafruit CircuitPython Library Bundle (manual): a pathway to dependancy hell - use CircUp to install adafruit_minimqtt.
Sample Code
import adafruit_minimqtt.adafruit_minimqtt as MQTT import microcontroller import os import socketpool import time import wifi def connected(client, userdata, flags, rc): client.subscribe("[XXX topic XXX]") # end connected() def message(client, topic, message): [XXX do stuff XXX] # end message() wifi.radio.connect(os.getenv('CIRCUITPY_WIFI_SSID'), os.getenv('CIRCUITPY_WIFI_PASSWORD')) socket_pool = socketpool.SocketPool(wifi.radio) mqtt_client = MQTT.MQTT( broker="[XXX your broker XXX]", port=1883, socket_pool=socket_pool, socket_timeout=5, client_id="[XXX a logging id for this client XXX]" ) mqtt_client.on_connect = connected mqtt_client.on_message = message try: mqtt_client.connect() except Exception as e: print('E/mqtt_client.connect(): ', e) time.sleep(5) microcontroller.reset() # end try while True: try: mqtt_client.loop(5) except Exception as e: try: mqtt_client.reconnect(True) except Exception as e2: print('E/mqtt_client.reconnect(): ', e2) time.sleep(5) microcontroller.reset() # end try # end try # end while
(Possibly) Useful Links
- https://circuitpython.org/board/raspberry_pi_pico_w/
- https://learn.adafruit.com/pico-w-wifi-with-circuitpython/overview
- https://learn.adafruit.com/mqtt-in-circuitpython/overview
- https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/latest
- https://datasheets.raspberrypi.com/soft/flash_nuke.uf2
¤ Copyright 1999-2024 Chris Molloy ¤ All rights reserved ¤