Raspberry Pi

Raspberry Pi Pico W MQTT with MicroPython: Publish Sensor Data and Receive Commands

A complete, tested path from a bare Raspberry Pi Pico W to a connected MQTT device. Flash MicroPython, install umqtt.simple, publish the onboard temperature sensor, switch the LED from anywhere and keep the connection alive through Wi-Fi drops.

Raspberry Pi Pico W MQTT project publishing onboard temperature readings to a cloud broker over Wi-Fi
Run this on your own MQTT brokerGet a private, managed MQTT broker on the Free plan and start from ready-made code samples.
Try it free Code samples No card required

Raspberry Pi Pico W MQTT projects are a great first step into connected hardware: the board costs little, MicroPython is easy to read, and MQTT gives you a lightweight way to send readings to the cloud and receive commands back. In this tutorial you will flash MicroPython, install the umqtt.simple library, publish the Pico W's onboard temperature to a broker every ten seconds, switch the onboard LED from your computer, and make the whole thing survive Wi-Fi and broker disconnects.

What You Need

Item Notes
Raspberry Pi Pico W (or Pico WH with headers) The plain Pico has no Wi-Fi; check for the W
Micro-USB data cable Many cheap cables are charge-only and will not show the board
A computer with Thonny or mpremote Thonny is the friendliest option for beginners
2.4 GHz Wi-Fi network The Pico W's CYW43439 radio does not support 5 GHz
An MQTT broker We use broker.connectmq.com for testing

No extra sensor is required. The RP2040 has an internal temperature sensor on ADC channel 4, which is perfect for proving the data path before you attach real hardware. If you are still choosing between boards, our ESP32 vs Raspberry Pi Pico W comparison and Pico W vs Pico 2 W guide cover the trade-offs.

Step 1: Flash MicroPython

  1. Download the latest MicroPython UF2 file for the Raspberry Pi Pico W (board name RPI_PICO_W) from the MicroPython downloads page or the Raspberry Pi MicroPython documentation. The plain Pico build has no Wi-Fi support, so make sure you pick the W variant.
  2. Hold the BOOTSEL button while plugging the board into USB. It appears as a drive called RPI-RP2.
  3. Copy the UF2 file to the drive. The board reboots into MicroPython automatically.
  4. Open Thonny, choose MicroPython (Raspberry Pi Pico) as the interpreter in the bottom-right corner, and you should see the >>> prompt.

Type import network at the prompt. If it works without an error, you have the Wi-Fi build.

Step 2: Install umqtt.simple

MicroPython ships umqtt.simple as a package in micropython-lib rather than in every firmware build. Install it once the board can reach the internet, using mip from the REPL after connecting to Wi-Fi:

import network, time, mip
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("YOUR_WIFI_SSID", "YOUR_WIFI_PASSWORD")
while not wlan.isconnected():
    time.sleep(0.5)
mip.install("umqtt.simple")

Alternatively, from your computer with the board connected over USB:

pip install mpremote
mpremote mip install umqtt.simple

Thonny also has Tools → Manage packages, where you can search for umqtt.simple. Any of the three methods places the library in /lib on the board.

Step 3: Plan Topics and Client ID

Every MQTT client needs a unique, non-empty client ID. The Pico W has a unique board ID we can use, so two boards running the same code never collide. For topics we use a demo prefix with a random string of your choice:

Purpose Topic
Temperature readings connectmq/demo/pw7c3e/pico1/temperature
LED commands connectmq/demo/pw7c3e/pico1/led/set
LED state connectmq/demo/pw7c3e/pico1/led/state
Online/offline status connectmq/demo/pw7c3e/pico1/status

The free public MQTT broker at broker.connectmq.com accepts anonymous connections on port 1883, but everything published there is visible to anyone who subscribes. Use a unique prefix and only send test data.

Step 4: The Complete Raspberry Pi Pico W MQTT Program

Save this as main.py on the board so it runs at boot. Change the Wi-Fi credentials and replace pw7c3e with your own string.

# main.py - Raspberry Pi Pico W MQTT example (MicroPython + umqtt.simple)
import time
import network
import machine
import ubinascii
import rp2
from umqtt.simple import MQTTClient

WIFI_SSID = "YOUR_WIFI_SSID"
WIFI_PASSWORD = "YOUR_WIFI_PASSWORD"
COUNTRY = "GB"                      # your two-letter country code

BROKER = "broker.connectmq.com"
PORT = 1883
PREFIX = "connectmq/demo/pw7c3e/pico1"
CLIENT_ID = "pico-" + ubinascii.hexlify(machine.unique_id()).decode()

PUBLISH_INTERVAL_MS = 10_000
KEEPALIVE_S = 60

led = machine.Pin("LED", machine.Pin.OUT)
sensor = machine.ADC(4)


def read_temperature():
    # RP2040 internal sensor: 27 C at 0.706 V, slope -1.721 mV/C
    voltage = sensor.read_u16() * 3.3 / 65535
    return round(27 - (voltage - 0.706) / 0.001721, 2)


def connect_wifi():
    rp2.country(COUNTRY)
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.config(pm=0xA11140)        # disable power saving for a responsive link
    if not wlan.isconnected():
        wlan.connect(WIFI_SSID, WIFI_PASSWORD)
        for _ in range(30):
            if wlan.isconnected():
                break
            led.toggle()
            time.sleep(0.5)
    if not wlan.isconnected():
        raise OSError("Wi-Fi connection failed, status %d" % wlan.status())
    print("Wi-Fi connected:", wlan.ifconfig()[0])
    led.off()


def on_message(topic, msg):
    topic = topic.decode()
    msg = msg.decode().strip().upper()
    print("Received", topic, msg)
    if topic == PREFIX + "/led/set":
        if msg in ("ON", "1"):
            led.on()
        elif msg in ("OFF", "0"):
            led.off()
        client.publish(PREFIX + "/led/state", "ON" if led.value() else "OFF", retain=True)


def connect_mqtt():
    c = MQTTClient(CLIENT_ID, BROKER, port=PORT, keepalive=KEEPALIVE_S)
    c.set_last_will(PREFIX + "/status", "offline", retain=True, qos=1)
    c.set_callback(on_message)
    c.connect()
    c.publish(PREFIX + "/status", "online", retain=True, qos=1)
    c.subscribe(PREFIX + "/led/set", qos=1)
    print("MQTT connected as", CLIENT_ID)
    return c


client = None


def main():
    global client
    connect_wifi()
    client = connect_mqtt()
    last_publish = time.ticks_ms() - PUBLISH_INTERVAL_MS
    last_ping = time.ticks_ms()

    while True:
        client.check_msg()                         # handle incoming commands
        now = time.ticks_ms()

        if time.ticks_diff(now, last_publish) >= PUBLISH_INTERVAL_MS:
            temp = read_temperature()
            payload = '{"value": %s, "unit": "C"}' % temp
            client.publish(PREFIX + "/temperature", payload)
            print("Published", payload)
            last_publish = now
            last_ping = now

        elif time.ticks_diff(now, last_ping) >= (KEEPALIVE_S // 2) * 1000:
            client.ping()                          # keep the session alive
            last_ping = now

        time.sleep_ms(100)


while True:
    try:
        main()
    except OSError as e:
        print("Connection problem:", e, "- retrying in 5 s")
        try:
            if client:
                client.disconnect()
        except Exception:
            pass
        time.sleep(5)

Click Run in Thonny, or reset the board. The shell should show the Wi-Fi address, the MQTT connection and a publish every ten seconds.

How the program works

  • Unique client ID. machine.unique_id() is read from the flash chip, so every board gets its own ID automatically.
  • Last Will. If the Pico disappears without a clean disconnect, the broker publishes offline to the status topic on its behalf. Combined with the retained online message, any subscriber can see whether the device is up.
  • Non-blocking loop. check_msg() returns immediately when there is nothing to read, so the loop can publish on a timer and still react to LED commands within about a tenth of a second.
  • Keepalive pings. umqtt.simple does not ping automatically. Without the ping() calls, a quiet connection would be closed by the broker after the keepalive interval.
  • Reconnect. Any socket error raises OSError, the outer loop waits five seconds and starts over, including Wi-Fi if needed.

Step 5: Test from Your Computer

Watch everything the Pico publishes:

mosquitto_sub -h broker.connectmq.com -p 1883 -i laptop-pw7c3e -v -t "connectmq/demo/pw7c3e/#"

Switch the LED:

mosquitto_pub -h broker.connectmq.com -p 1883 -i cmd-pw7c3e -t "connectmq/demo/pw7c3e/pico1/led/set" -m "ON"
mosquitto_pub -h broker.connectmq.com -p 1883 -i cmd-pw7c3e -t "connectmq/demo/pw7c3e/pico1/led/set" -m "OFF"

The LED should follow, and the subscriber shows the new state. Unplug the Pico and, after the keepalive period, the subscriber receives offline from the Last Will.

Troubleshooting

Problem Likely cause and fix
ImportError: no module named 'network' You flashed the plain Pico firmware; reflash the RPI_PICO_W build
ImportError: no module named 'umqtt' Library not installed; repeat Step 2 and check /lib
Wi-Fi status -2 or -3 Network not found or wrong password; confirm the 2.4 GHz SSID and the country code
OSError: -2 on connect DNS lookup failed; check that Wi-Fi has an IP and a working DNS server
Connects, then drops after about a minute Missing pings; keep the ping logic, or lower KEEPALIVE_S
Connection refused right after reconnect Another device or session uses the same client ID
Temperature seems high The internal sensor measures the chip, not the room; use an external sensor for ambient readings

The onboard sensor is also sensitive to the exact reference voltage, so readings can be a few degrees off. That is fine for this tutorial; for real measurements, attach a DS18B20, BME280 or SHT31.

From Demo to Production

The public broker is shared and open, so production devices should connect with their own credentials and TLS. On ConnectMQ, create a broker in the portal and copy the generated username, password and client ID. Client IDs are bound to the issued credentials, so use the exact YOUR_CLIENT_ID value from the portal instead of the board-derived ID, and pass user="YOUR_USERNAME" and password="YOUR_PASSWORD" to MQTTClient. Then move to port 8883 with certificate verification, which is covered step by step in Pico W MQTT over TLS. For battery-powered designs, see Pico W battery MQTT.

A hosted MQTT broker such as ConnectMQ also gives you tooling around the device: the portal's in-browser MQTT client and live topic explorer let you check the Pico's topics without installing anything, and threshold alert rules can flag a temperature that goes out of range. For more Raspberry Pi projects, including the full-size boards, start from the Raspberry Pi MQTT tutorial.

Connect Your Pico W to ConnectMQ

Sign up at app.connectmq.com for the free Serverless plan, no credit card required. Create a broker, copy the credentials into main.py, and your Pico W is talking to a private broker in a few minutes. The free plan's 25 connections cover a whole shelf of Pico W boards.

Frequently Asked Questions

Which MQTT library should I use on the Pico W?

umqtt.simple from micropython-lib is the standard choice for MicroPython. It is small, supports QoS 0 and 1, Last Will, retained messages and TLS, and installs with mip.

Does the Raspberry Pi Pico W support MQTT over TLS?

Yes. MicroPython's ssl module works on the Pico W, and umqtt.simple can connect to port 8883 with certificate verification, although the handshake takes noticeably longer than on chips with crypto acceleration.

Why does my Pico W disconnect from the MQTT broker after a minute?

umqtt.simple does not send keepalive pings on its own. Call client.ping() regularly, at least once per keepalive interval, or publish often enough to keep the connection active.

Can I use the Pico W with Arduino instead of MicroPython?

Yes. The Arduino-Pico core supports the Pico W's Wi-Fi, and libraries such as PubSubClient work with it. MicroPython is usually faster for prototyping, while C/C++ gives more control over memory and timing.

Related articles

Pico W vs Pico 2 W for MQTT: RP2040 vs RP2350 Performance, Memory and TLS

The Pico 2 W keeps the Pico W's footprint and Wi-Fi chip but swaps the RP2040 for the faster RP2350. This comparison looks at what that means for MQTT devices: CPU, memory, TLS, security features, software support, and which board to buy for which project.

8 min read

Raspberry Pi RFID MQTT Access Logging with the RC522 Reader

Wire an RC522 RFID reader to a Raspberry Pi, read tags in Python, check them against a local allowlist and publish every access attempt as an MQTT event that loggers, dashboards and alerting tools can consume.

7 min read

All articles →

Your private MQTT broker is a few clicks away

Create an account, get your broker credentials and connect your first device — no servers to install, patch or scale.