In this tutorial, we will show you how to set up your own IoT device. To achieve that, you will learn how to

  • Create a device on Adafruit IO
  • Publish/subscribe data using the MQTT protocol (on which the Adafruit IO platform is based)

In particular, we will do this with a specific example project in which we will connect a sensor (the photoresistor we used in the last tutorial, sampled through our MCP3008 ADC) and an actuator (an LED) and have them both interface with the Adafruit IO platform. The sensor will simply report values which will be visible through the web interface, while the actuator will change its status (on or off) according to a remote button that is controlled via the Adafruit IO dashboard (also on the web interace).

There are many steps to follow, but thankfully they are all simple and well documented:

1. Create an account on Adafruit IO

Follow the instructions here to create an account on io.adafruit.com in order to be able to gain access to the platform.

2. Set up your RaspberryPi to interact with Adafruit IO

Follow the instructions here to install the Adafruit IO Python client code on your RPi so that we can use it in our scripts.

3. Create feeds for the trandscucers on Adafruit IO

Learn about feeds in Adafruit IO here. Then use that knowledge to set up two feeds: one for the photoresistor (which you can name “photoresistor”, or whatever you like), and one for the LED (which I’ve named “LED” but you can choose whatever name you like).

The details of each of those feeds are up to you, but you want the photoresistor feed to be a line chart or something similar; while the LED one to look like a button or slider with values limited to “0” or “1”.

4. Connect the feeds to a dashboard

Learn about dashboards in Adafruit IO here and then create one that links to both of the feeds we just created.

5. Find out your secret Key to access your account remotely

Click on the “My Key” tab in your Adafruit IO web interface to learn your username and key. Copy/paste this so that you can use it later in the next steps.

6. Publish/Subscribe Data using MQTT Protocol

You are now ready to start using the sensors and actuators with Adafruit IO.

From here on, I will assume that you have connected your RPi to sample from the phtoresistor in the same way that we did for Tutorial #3, and that you have also connected an LED like we did in Tutorial #2 (i.e., on BCM 18 of the GPIO). If you are curious about the details of the underlying protocol we will use to connect these to the Adafruit IO platform, read here for a simple introduction on what is MQTT communication protocol.

It may take a while to parse through the code below, but this is all you need to complete the tutorial. Create a Python script with this sample code filled in (i.e., add your actual Key and correct the feed names and GPIO pins) and then run it. All set!

# Insipired by Brent Rubell's code here: https://learn.adafruit.com/quickstart-rp2040-pico-with-wifi-and-circuitpython/usage-with-adafruit-io
# and the Adafruit IO documentation, specifically here: https://adafruit-io-python-client.readthedocs.io/en/latest/data.html

import sys # Standard python modules
import busio
import digitalio
import board
import adafruit_mcp3xxx.mcp3008 as MCP
from adafruit_mcp3xxx.analog_in import AnalogIn
import time
import RPi.GPIO as GPIO
from Adafruit_IO import MQTTClient # Adafruit IO MQTT client.

# Set to your Adafruit IO key.
# Remember, your key is a secret,
# so make sure not to publish it when you publish this code!
ADAFRUIT_IO_KEY = 'YOUR_KEY'

# Set to your Adafruit IO username.
# (go to https://accounts.adafruit.com to find your username)
ADAFRUIT_IO_USERNAME = 'YOUR_USERNAME'

# Set to the ID of the feed to subscribe to for updates.
led_button = 'LED'

GPIO.setmode(GPIO.BCM)
red_led = 18
GPIO.setup(red_led, GPIO.OUT)


spi = busio.SPI(clock=board.SCK, MISO=board.MISO, MOSI=board.MOSI)
cs = digitalio.DigitalInOut(board.D5)

# Create an MCP3008 object
mcp = MCP.MCP3008(spi, cs)
# Create an analog input channel on the MCP3008 pin 0
channel = AnalogIn(mcp, MCP.P0)

def connected(client):
    # Connected function will be called when the client is connected to Adafruit IO.
    print("Connected to Adafruit IO! Listening for updates from feed {0}".format(led_button))
    client.subscribe(led_button)

def subscribe(client, userdata, topic, granted_qos):
    # This method is called when the client subscribes to a new feed.
    print("Subscribed to {0} with QOS level {1}".format(topic, granted_qos))

def disconnected(client):
    # Disconnected function will be called when the client disconnects.
    print("Disconnected from Adafruit IO!")


def message(client, feed_id, payload):
    # Method called whenever user/feeds/led has a new value
    print("New message on topic {0}: {1} ".format(feed_id, payload))
    if feed_id == led_button and payload == "1":
        GPIO.output(red_led, GPIO.HIGH)
    elif feed_id == led_button and payload == "0":
        GPIO.output(red_led, GPIO.LOW)
    else:
        print("Unexpected message.")

# Create an MQTT client instance.
client = MQTTClient(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY)

# Setup the callback functions defined above.
client.on_connect    = connected
client.on_disconnect = disconnected
client.on_subscribe  = subscribe
client.on_message = message

# Connect to the Adafruit IO server.
client.connect()

def main():
    prv_refresh_time = 0.0
    while True:
        # Poll for incoming messages
        try:
            client.loop()
        except (ValueError, RuntimeError) as e:
            print("Failed to get data, retrying\n", e)
            client.reconnect()
            continue
        # Send a new light intensity reading to IO every 5 seconds
        if (time.monotonic() - prv_refresh_time) > 5:
            # take the photresistor's voltage reading 
            light = channel.voltage
            print("ADC Voltage from photoresitor: %s" % light)
            # publish it to io
            print("Publishing %s to light intensity feed..." % light)
            client.publish("photoresistor", light)
            print("Published!")
            prv_refresh_time = time.monotonic()


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        GPIO.cleanup()
        client.disconnect()
        sys.exit(0)

Good job! You have successfully set up your own IoT device.