CircuitPython Usage

Secrets File Setup for Adafruit IO

While you created a secrets.py file and connected to the internet in the previous step, you'll need to edit the secrets.py file to include your Adafruit IO Username and Secret Key.

Add the following code to your secrets.py file, replacing _your_adafruit_io_username with your Adafruit IO username.

Then, replace _your_big_huge_super_long_aio_key_ with your Adafruit IO Active Key.

Download: file
secrets = {
    'ssid' : '_your_wifi_ssid_',
    'password' : '_your_wifi_password_',
    'aio_username' : '_your_adafruit_io_username_',
    'aio_key' : '_your_big_huge_super_long_aio_key_'
    }

Make sure you save this file before proceeding as secrets.py in the root directory of your board CIRCUITPY drive.

Code Usage

Copy the following code to your code.py file on your microcontroller:

# Adafruit MiniMQTT Pub/Sub Example
# Written by Tony DiCola for Adafruit Industries
# Modified by Brent Rubell for Adafruit Industries
import time
import board
import busio
from digitalio import DigitalInOut
import neopixel
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_minimqtt import MQTT

### WiFi ###

# Get wifi details and more from a secrets.py file
try:
    from secrets import secrets
except ImportError:
    print("WiFi secrets are kept in secrets.py, please add them there!")
    raise

# If you are using a board with pre-defined ESP32 Pins:
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)

# If you have an externally connected ESP32:
# esp32_cs = DigitalInOut(board.D9)
# esp32_ready = DigitalInOut(board.D10)
# esp32_reset = DigitalInOut(board.D5)

spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
"""Use below for Most Boards"""
status_light = neopixel.NeoPixel(
    board.NEOPIXEL, 1, brightness=0.2)  # Uncomment for Most Boards
"""Uncomment below for ItsyBitsy M4"""
# status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
# Uncomment below for an externally defined RGB LED
# import adafruit_rgbled
# from adafruit_esp32spi import PWMOut
# RED_LED = PWMOut.PWMOut(esp, 26)
# GREEN_LED = PWMOut.PWMOut(esp, 27)
# BLUE_LED = PWMOut.PWMOut(esp, 25)
# status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED)
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(
    esp, secrets, status_light)

### Feeds ###

# Setup a feed named 'photocell' for publishing to a feed
photocell_feed = secrets['aio_username'] + '/feeds/photocell'

# Setup a feed named 'onoff' for subscribing to changes
onoff_feed = secrets['aio_username'] + '/feeds/onoff'

### Code ###

# Define callback methods which are called when events occur
# pylint: disable=unused-argument, redefined-outer-name
def connected(client, userdata, flags, rc):
    # This function will be called when the client is connected
    # successfully to the broker.
    print('Connected to Adafruit IO! Listening for topic changes on %s' % onoff_feed)
    # Subscribe to all changes on the onoff_feed.
    client.subscribe(onoff_feed)


def disconnected(client, userdata, rc):
    # This method is called when the client is disconnected
    print('Disconnected from Adafruit IO!')


def message(client, topic, message):
    # This method is called when a topic the client is subscribed to
    # has a new message.
    print('New message on topic {0}: {1}'.format(topic, message))


# Connect to WiFi
wifi.connect()

# Set up a MiniMQTT Client
mqtt_client = MQTT(socket,
                   broker='io.adafruit.com',
                   username=secrets['aio_username'],
                   password=secrets['aio_key'],
                   network_manager=wifi)

# Setup the callback methods above
mqtt_client.on_connect = connected
mqtt_client.on_disconnect = disconnected
mqtt_client.on_message = message

# Connect the client to the MQTT broker.
print('Connecting to Adafruit IO...')
mqtt_client.connect()

photocell_val = 0
while True:
    # Poll the message queue
    mqtt_client.loop()

    # Send a new message
    print('Sending photocell value: %d...' % photocell_val)
    mqtt_client.publish(photocell_feed, photocell_val)
    print('Sent!')
    photocell_val += 1
    time.sleep(1)

WiFi Connection Pinouts

If you are using a board with a built-in ESP32 (like the PyPortal), you do not need to make changes to the code. It's already setup for usage with those boards. However, if you are using an externally connected  ESP32 (like the AirLift Breakout), you'll need to define the ESP32's pinouts.

Make sure to change the ESP32 pin definitions in the code to match your wiring. You can do this by uncommenting and editing the following lines in your code to match your wiring.

Download: file
esp32_cs = DigitalInOut(board.D9)
esp32_ready = DigitalInOut(board.D10)
esp32_reset = DigitalInOut(board.D5)

Feed Publishing Example

Directly after saving the code.py file, open a serial monitor/REPL to see the output. It should look something like the following:

Download: file
code.py output:
Connecting to Adafruit IO...
Connected to Adafruit IO! Listening for topic changes on brubell/feeds/onoff
Sending photocell value: 0...
Sent!
Sending photocell value: 1...
Sent!
Sending photocell value: 2...
Sent!
Sending photocell value: 3...
Sent!

Navigate to the dashboard you created earlier. You should see the photocell gauge increasing its value as your CircuitPython device publishes the increasing photocell value to Adafruit IO.

If you navigate to the page for the photocell feed, you'll see the values increasing there along with metadata about when the data was received by the Adafruit IO broker.

Feed Subscription Example

While we're publishing the increasing photocell value to Adafruit IO - our code also subscribes to changes on the onoff feed.

The example code.py subscribes to the onoff feed when the client successfully connects to Adafruit IO. You don't need to make any changes to your code!

With the code still running on your CircuitPython device - click the toggle switch to send a value to the onoff feed. You should see the value appear on your serial monitor/REPL.

If you really want to see the speed of MQTT - remove the one second delay in the while True loop.

Change the following code (within while True) from:

print('Sent!')
photocell_val += 1
time.sleep(1)

to

print('Sent!')
photocell_val += 1
time.sleep(0.5)

Be warned - if you do this you will not be able to run the code for very long. This is because Adafruit IO's MQTT server imposes a rate limit to prevent excessive load on the service.

The current Adafruit IO Data Rate is at most 1 request per second (or 60 requests within 60 seconds), without an Adafruit IO+ Boost applied to your account.

Going Further - the Adafruit IO CircuitPython Module

While you can use this code to communicate with Adafruit IO, the recommend method of using CircuitPython with Adafruit IO is with the Adafruit IO CircuitPython module

This module has methods to simplify using the Adafruit IO MQTT API. It also includes helper features to make your experience using Adafruit IO better.

If you want to use Adafruit IO and CircuitPython, check out Adafruit IO CircuitPython and its code examples on GitHub!

This guide was first published on Jul 23, 2019. It was last updated on Jul 23, 2019. This page (CircuitPython Usage) was last updated on Nov 13, 2019.