Skip to content
Buy 10+ on select items — save 10% auto-applied
Free US shipping on orders $35+
Order by 3pm ET — ships same-day from the US
Skip to main content

Raspberry Pi Pico W AWS IoT Core: MQTT LED Control | ShillehTek

December 22, 2023 222 views

Raspberry Pi Pico W AWS IoT Core: MQTT LED Control | ShillehTek
Project

Connect a Raspberry Pi Pico W to AWS IoT Core with secure MQTT in MicroPython, then toggle the onboard LED from the cloud with ShillehTek.

45 min Intermediate1 parts

Video Tutorial (Optional)

Watch first if you want to see the full AWS IoT Core setup and MicroPython MQTT code for the Raspberry Pi Pico W in real time.

Project Overview

In this project, you connect a Raspberry Pi Pico W to AWS IoT Core and use MQTT (with MicroPython) to toggle the Pico W onboard LED from the cloud.

AWS IoT Core is Amazon's managed cloud service for IoT applications. It lets you connect devices securely to the cloud, collect and analyze data, and take action based on that data.

Subscribe: Youtube

Support: https://www.buymeacoffee.com/mmshilleh

Hire me at UpWork to build your IoT projects: https://www.upwork.com/freelancers/~017060e77e9d8a1157

  • Time: 45 to 90 minutes
  • Skill level: Intermediate
  • What you will build: A secure MQTT subscriber on Pico W that receives cloud messages and turns the onboard LED on, off, or toggles it

Parts List

From ShillehTek

External

Note: Keep your AWS IoT Core endpoint, certificates, and keys as private as possible. You will upload the cert/key files onto the Pico W filesystem for TLS MQTT to work.

Step-by-Step Guide

Step 1 - Create a policy, Thing, certificates, and endpoint in AWS IoT Core

Goal: Create the AWS IoT Core resources your Pico W needs to connect securely over MQTT (policy, Thing, certificates/keys, Root CA, and your IoT endpoint).

What to do: Create an AWS account if you do not already have one at https://aws.amazon.com/. Then open the AWS Console, search for IoT Core, and open the service.

AWS Console search showing IoT Core selected for setting up a Raspberry Pi Pico W device
Open AWS IoT Core from the AWS Console.

What to do: In the left menu, go to Security and select Policies. Create a policy and customize it for your use case (the original tutorial shows a general-purpose policy setup).

AWS IoT Core left menu highlighting Policies under Security for Pico W MQTT setup
Navigate to Policies under Security.
AWS IoT Core policy configuration screen used to authorize Raspberry Pi Pico W MQTT actions
Example policy configuration from the tutorial.

What to do: Create a Thing by going to All Devices in the left menu, then Things and choose Create Things. Name it however you like.

AWS IoT Core Things creation screen for registering a Raspberry Pi Pico W as a device
Create a new Thing in AWS IoT Core.
AWS IoT Core workflow screen showing steps for creating a Thing and generating certificates for Pico W
Follow the Create Thing wizard steps.
AWS IoT Core Thing naming step for Raspberry Pi Pico W device registration
Name your Thing.

What to do: Generate certificates for your Thing (the tutorial uses auto-generated certificates). Attach the policy you created to the Thing.

AWS IoT Core certificate generation screen for Pico W secure MQTT connection
Auto-generate certificates for the device.
AWS IoT Core policy attachment screen for enabling Pico W permissions
Attach your policy to the Thing.

What to do: Download the four device-related files shown in the tutorial: device certificate, public key, private key, and the Root CA 2048 file. You will upload these to the Pico W so the TLS MQTT client can connect.

AWS IoT Core download certificates screen showing device cert, public key, private key, and Root CA for Pico W
Download the certificates and keys for the Pico W.

What to do: Save your AWS IoT Core endpoint. In AWS IoT Core, you can find it by going to Settings and locating the Endpoint value. You will substitute it into the MicroPython code.

AWS IoT Core Settings page showing the device data endpoint needed by Raspberry Pi Pico W MQTT client
Copy the AWS IoT Core endpoint from Settings.

Expected result: You have a Thing created, a policy attached, certificates and keys downloaded, and your AWS IoT Core endpoint saved for use in code.

Step 2 - Upload files to the Pico W and run the MicroPython MQTT client

Goal: Put the required cert/key files and MQTT library on the Pico W, then run a MicroPython script that subscribes to an MQTT topic and toggles the onboard LED.

What to do: Open your MicroPython editor (the tutorial uses Thonny) and upload the four AWS files (device cert, keys, and Root CA) to the Pico W.

Thonny file manager showing AWS certificate and key files uploaded to Raspberry Pi Pico W
Upload the downloaded AWS certificate and key files to the Pico W.

What to do: Download the MicroPython umqtt library code from this link and add it to your Pico W filesystem:

https://raw.githubusercontent.com/micropython/micropython-lib/master/micropython/umqtt.simple/umqtt/simple.py

What to do: Copy the contents into a file in your lib folder. Create a simple.py file and paste the code into it.

Thonny showing simple.py MQTT library file placed on Raspberry Pi Pico W in the lib folder
Add the umqtt simple library as simple.py.

What to do: Create a new Python file in the Pico W root directory and modify the following code to match your Wi-Fi details, certificate filenames, and AWS IoT Core endpoint.

Code:

# module imports
import machine
import network
import ssl
import time
import ubinascii

from simple import MQTTClient

import config


SSID = config.SSID
WIFI_PASSWORD = config.WIFI_PASSWORD

MQTT_CLIENT_ID = ubinascii.hexlify(machine.unique_id())
### Replace with the names of the files from your certs and keys
MQTT_CLIENT_KEY = "46cc41c44191da56db300a8bce37e1c2ebafa2211becebde9dc6a778fd6c3829-private.pem.key"
MQTT_CLIENT_CERT = "46cc41c44191da56db300a8bce37e1c2ebafa2211becebde9dc6a778fd6c3829-certificate.pem.crt"

### You can find this URL by going into the AWS IoT Core Settings under "Endpoint"
MQTT_BROKER = config.IOT_CORE_ENDPOINT
MQTT_BROKER_CA = "AmazonRootCA1.pem"

led = machine.Pin("LED", machine.Pin.OUT)


# function that reads PEM file and return byte array of data
def read_pem(file):
    with open(file, "r") as input:
        text = input.read().strip()
        split_text = text.split("\n")
        base64_text = "".join(split_text[1:-1])
        return ubinascii.a2b_base64(base64_text)


def connect_internet():
    try:
        sta_if = network.WLAN(network.STA_IF)
        sta_if.active(True)
        sta_if.connect(SSID, WIFI_PASSWORD)

        for i in range(0, 10):
            if not sta_if.isconnected():
                time.sleep(1)
        print("Connected to Wi-Fi")
    except Exception as e:
        print('There was an issue connecting to WIFI')
        print(e)


# callback function to handle received MQTT messages
def on_mqtt_msg(topic, msg):
    # convert topic and message from bytes to string
    topic_str = topic.decode()
    msg_str = msg.decode()

    print(f"RX: {topic_str}\n\t{msg_str}")

    # process message
    if topic_str is 'LED':
        if msg_str is "on":
            led.on()
        elif msg_str is "off":
            led.off()
        elif msg_str is "toggle":
            led.toggle()


connect_internet()
# read the data in the private key, public certificate, and
# root CA files
key = read_pem(MQTT_CLIENT_KEY)
cert = read_pem(MQTT_CLIENT_CERT)
ca = read_pem(MQTT_BROKER_CA)

# create MQTT client that use TLS/SSL for a secure connection
mqtt_client = MQTTClient(
    MQTT_CLIENT_ID,
    MQTT_BROKER,
    keepalive=60,
    ssl=True,
    ssl_params={
        "key": key,
        "cert": cert,
        "server_hostname": MQTT_BROKER,
        "cert_reqs": ssl.CERT_REQUIRED,
        "cadata": ca,
    },
)

print(f"Connecting to MQTT broker")
# register callback to for MQTT messages, connect to broker and
# subscribe to LED topic
mqtt_client.set_callback(on_mqtt_msg)
mqtt_client.connect()
mqtt_client.subscribe('LED')


# main loop, continuously check for incoming MQTT messages
print("Connection established, awaiting messages")
while True:
    mqtt_client.check_msg()

The script connects to Wi-Fi, establishes an MQTT connection to AWS IoT Core using TLS/SSL, subscribes to the LED topic, and controls the onboard LED based on received messages.

Note that the tutorial uses a config file to hide sensitive information, but you can also substitute values directly in the script.

What to do: To test it, go back to the AWS console and use the MQTT test client to publish messages to the LED topic (for example: on, off, or toggle).

AWS IoT Core MQTT test client publishing to the LED topic for Raspberry Pi Pico W
Use the AWS IoT Core test client to publish to the LED topic.
Thonny shell showing received MQTT messages while Raspberry Pi Pico W toggles onboard LED
You should see messages printed in your editor shell while the Pico W LED changes state.

Expected result: You see incoming MQTT messages printed in your MicroPython editor shell, and the Pico W onboard LED turns on, turns off, or toggles based on what you publish to the LED topic.

Conclusion

You connected a Raspberry Pi Pico W to AWS IoT Core using MicroPython, TLS MQTT, and the umqtt library, then subscribed to an MQTT topic to toggle the onboard LED from the cloud.

If you enjoyed this video/tutorial be sure to subscribe to the channel and like the video. Even better consider donating in the BuyMeACoffee link above.

Want parts, tools, and project supplies for your next build? Grab what you need from ShillehTek.com. If you want help customizing this project or building an IoT solution for your product, check out our IoT consulting services.