Skip to content

Instantly share code, notes, and snippets.

@sammachin
Last active April 22, 2024 14:45
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sammachin/b67cc4f395265bccd9b2da5972663e6d to your computer and use it in GitHub Desktop.
Save sammachin/b67cc4f395265bccd9b2da5972663e6d to your computer and use it in GitHub Desktop.
Raspberry Pi PicoW MQTT-GPIO With Node-RED

This will require the umqtt.simple library on the PicoW,

You can install this with upip by running:

import upip
upip.install('umqtt.simple')

If you use a public MQTT broker such as test.mosquitto.org you should change the prefix value in line 8 of the micropython from MYNAME to something unique or you may recieve other peoples commands

Also you will need to update the topics in the flow from MYNAME

You will need to enter the WiFi Details for your network in like 12 of the micropython, change YOUR_WIFI_SSID and YOUR_WIFI_PASSWORD to appropriate values

[{"id":"a1278c3bb2492ac8","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"072eb8be8fa5b953","type":"mqtt out","z":"a1278c3bb2492ac8","name":"","topic":"","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"f59f047b7402cb1e","x":710,"y":120,"wires":[]},{"id":"436051cad470a16e","type":"inject","z":"a1278c3bb2492ac8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"MYNAME/GPIO/15","payload":"1","payloadType":"num","x":180,"y":140,"wires":[["072eb8be8fa5b953"]]},{"id":"91d674ba9493c9cb","type":"mqtt in","z":"a1278c3bb2492ac8","name":"","topic":"MYNAME/pico","qos":"2","datatype":"auto","broker":"f59f047b7402cb1e","nl":false,"rap":true,"rh":0,"inputs":0,"x":120,"y":300,"wires":[["330a1ccd80e08cdc"]]},{"id":"330a1ccd80e08cdc","type":"debug","z":"a1278c3bb2492ac8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":330,"y":300,"wires":[]},{"id":"92c6361a251d3684","type":"inject","z":"a1278c3bb2492ac8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"MYNAME/GPIO/15","payload":"0","payloadType":"num","x":180,"y":180,"wires":[["072eb8be8fa5b953"]]},{"id":"c3f373ccb42e5d2c","type":"inject","z":"a1278c3bb2492ac8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"MYNAME/GPIO/20","payload":"1","payloadType":"num","x":180,"y":60,"wires":[["072eb8be8fa5b953"]]},{"id":"b5a434643a3e22fb","type":"inject","z":"a1278c3bb2492ac8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"MYNAME/GPIO/20","payload":"0","payloadType":"num","x":180,"y":100,"wires":[["072eb8be8fa5b953"]]},{"id":"f59f047b7402cb1e","type":"mqtt-broker","name":"","broker":"test.mosquitto.org","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""}]
import network
import time
from machine import Pin
from umqtt.simple import MQTTClient
prefix = "MYNAME/"
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect('YOUR_WIFI_SSID', 'YOUR_WIFI_PASSWORD')
while not wlan.isconnected() and wlan.status() >= 0:
print("Waiting to connect:")
time.sleep(1)
def callback(topic, msg):
t = topic.decode("utf-8").lstrip(prefix)
print(t)
if t[:5] == 'GPIO/':
p = int(t[5:])
data = int(msg)
led = Pin(p, Pin.OUT)
led.value(data)
client.publish(prefix+'pico', str(p)+"-"+str(data))
def heartbeat(first):
global lastping
if first:
client.ping()
lastping = time.ticks_ms()
if time.ticks_diff(time.ticks_ms(), lastping) >= 300000:
client.ping()
lastping = time.ticks_ms()
return
client = MQTTClient(prefix+"picow", "test.mosquitto.org",user=None, password=None, keepalive=300, ssl=False, ssl_params={})
client.connect()
heartbeat(True)
client.set_callback(callback)
client.subscribe(prefix+"GPIO/#")
while True:
client.check_msg()
heartbeat(False)
import network
import time
from machine import Pin
from umqtt.simple import MQTTClient
prefix = "MYNAME/"
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect('YOUR_WIFI_SSID', 'YOUR_WIFI_PASSWORD')
while not wlan.isconnected() and wlan.status() >= 0:
print("Waiting to connect:")
time.sleep(1)
def callback(topic, msg):
t = topic.decode("utf-8").lstrip(prefix)
print(t)
if t[:5] == 'GPIO/':
p = int(t[5:])
data = int(msg)
led = Pin(p, Pin.OUT)
led.value(data)
client.publish(prefix+'pico', str(p)+"-"+str(data))
client = MQTTClient(prefix+"picow", "test.mosquitto.org",user=None, password=None, keepalive=300, ssl=False, ssl_params={})
client.connect()
client.set_callback(callback)
client.subscribe(prefix+"GPIO/#")
while True:
client.wait_msg()
@sammachin
Copy link
Author

@Dargot-b
Copy link

Hi
Your script is working great. But after about 430 s it gets an error and pico stops working.
Can you help?
I'll just add that I don't know anything about programming.

Traceback (most recent call last):
File "", line 31, in
File "/lib/umqtt/simple.py", line 173, in wait_msg
OSError: -1

@sammachin
Copy link
Author

Hi Your script is working great. But after about 430 s it gets an error and pico stops working. Can you help? I'll just add that I don't know anything about programming.

Traceback (most recent call last): File "", line 31, in File "/lib/umqtt/simple.py", line 173, in wait_msg OSError: -1

Yes this is because there’s no code to send a keep alive ping to the server so if times out after 300s, (the server usually has a buffer over the min timeout)

I’ll post an updated example that adds the ping but it will be a bit more complex, this was juts a simple hello world type demo

@sammachin
Copy link
Author

@Dargot-b try the keepalive version above

@sammachin
Copy link
Author

@ratarchivos In theory yes you could replace the WiFi setup with AP Mode, but you would need to connect to an MQTT broker somewhere so you would have to then connect that as a client to the network and the same for Node-RED. I'm not sure why you would want to do this?

@Dargot-b
Copy link

Hi
Thank you for your work. I connected to MQTT broker in my smart home server (Ampio Smart Home)
which includes Node-red, and everything is working fine.
I plan to do garage door control in my house without installing electrical wires. Looking for a solution similar to: https://youtu.be/bIBQKl_Sots
but use the Ampio application. I don't know how yet but I think I can do it....

@sammachin
Copy link
Author

@ratarchivos using MQTT probabbly isn't the best solution there then, look at something simpler like websockets

@sgbaird
Copy link

sgbaird commented Sep 9, 2022

Can you provide a simple example sending and/or receiving with an external client? Maybe using paho-mqtt

@sammachin
Copy link
Author

Can you provide a simple example sending and/or receiving with an external client? Maybe using paho-mqtt

Node-RED is an external MQTT client, but if you want to know the topics and payloads that you need to publish the topic is MYNAME/GPIO/[PIN] where [PIN] is the GPIO pin number and then the payload is simply a 1 or 0 to turn the pin on or off

@sgbaird
Copy link

sgbaird commented Sep 10, 2022

Thanks @sammachin. I need something that I can control programmatically (closed-loop optimization), and I wasn't sure if Node-RED was the way to go for that. I came up with a solution based on this gist in public_mqtt_sdl_demo with a notebook showing the external client sending commands and receiving data in 4.0-paho-mqtt-colab-sdl-demo.ipynb.

Do you know if Node-RED would be amenable to running things in a closed loop, preferably some Python API, or is the way I approached it above more like what you'd recommend?

@Richard238
Copy link

Spotted a tiny typo in the read-me, like/line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment