Skill Level: Intermediate
This tutorial will teach you how to use the Adafruit IO service to connect your Raspberry Pi to the outside world. A basic understanding of electronics and programming is expected along with some familiarity with the Raspberry Pi platform. If you are new to Raspberry Pi or would just like to refresh your knowledge, please see our Blink: Making An LED Blink On A Raspberry Pi tutorial before proceeding with this one. In addition, this tutorial will use a solderless breadboard to build a simple circuit from a schematic diagram. The Core Electronics’ How to Use Breadboards, Science Buddies’ How to Use a Breadboard, and SparkFun’s How to Read a Schematic guides are good resources for learning how to translate a schematic to a breadboard.
The resources created for this tutorial are available on GitHub for your reference.
What Is Needed
- Raspberry Pi Running Raspbian Or Similar Linux Based OS (available on Raspberry Pi Foundation and Adafruit)
- Optional Raspberry Pi GPIO Breakout Board (available on Adafruit and CanaKit)
- Solderless Breadboard (available on Adafruit and SparkFun)
- Preformed Breadboard Jumper Wire Kit (available on SparkFun and CanaKit)
- 4 x Male-Female Jumper Wires (available on Adafruit and Arrow)
- Standard 5mm Red LED (available on Adafruit and SparkFun)
- Momentary Push Button (available on Adafruit and SparkFun)
- 330 Ω Resistor (available on SparkFun and Amazon)
In a previous article, Controlling A Raspberry Pi From A Web Browser With Vapor 3, I described how to create and run a web server on your Raspberry Pi. This worked well for accessing your Raspberry Pi over a local network, but it was not visible over the internet. In order to extend this approach and allow your Raspberry Pi based server to be accessed over the internet, techniques such as port forwarding, external hosting, static IP addressing, or use of a Dynamic DNS service are required. Although doable, these techniques can be complicated, costly, or not very secure. For these reasons, they are not usually the best fit for hobbyists to access their Raspberry Pis over the internet.
This tutorial will instead utilize Adafruit’s Adafruit IO service to connect our Raspberry Pi to the outside world. Adafruit IO is free, secure, compatible across many development boards, and allows your device to be accessed privately or shared to others if you so choose. Upgrades are available, but the free tier gives us a lot to work with and may be all that you will ever need. Also note that the Adafruit IO service is still in beta so some changes are expected over time. Please see the Internet of Things for Everyone and Adafruit IO Basics learning guides for additional information on using the Adafruit IO service. There is even a general category listing that contains all kinds of Adafruit IO based projects.
My development board is the Raspberry Pi 3 Model B running the Raspbian operating system. I am also using an optional GPIO breakout board to make wiring between the Raspberry Pi and the breadboard a little easier. If you are using a different Raspberry Pi model or a different OS that is similar to Raspbian, the vast majority of this tutorial should still apply, however, some minor changes may be necessary.
If you need assistance with your particular setup, post a question in the comments section below and I, or someone else, can try to help you.
Adafruit IO Setup
This project will connect a button and an LED to a Raspberry Pi that we will then associate with the Adafruit IO service for access and control. But before we do that, we need to configure our intentions on Adafruit IO.
If you don’t already have an Adafruit account, go to their website and sign up for one now. Please note that the Adafruit IO service does not require a separate account. Once your account is created, head over to the Adafruit IO site.
Now, let’s create our feeds. Feeds hold the meta data and values associated with a particular component or sensor. They are unique to each individual source of data you send to the system. In our case, we need two feeds, one for a button and one for an LED.
Click Feeds in the left hand panel of the Adafruit IO site. Click the Actions drop down and select Create a New Feed. In the Create a new Feed window that pops up, enter Button in the Name field along with an optional Description such as Button state. Click the Create button when done. Then create a Red LED feed in the same fashion. The Key column in the Feeds listing displays the identifiers that we will use in our program. The keys of button and red-led are shown for the feeds we just created.
If you click on the individual feeds, you will be provided additional information and settings specific to that feed. The main area presents recent data in both visual and listing formats. Clicking the gear icons along the right allows you to change settings for your feed such as privacy and sharing controls.
Now we need a way to visualize and communicate with the feeds. Dashboards are used for this purpose. Widgets such as indicators, sliders, buttons, and charts are available.
Let’s create a dashboard for our project. Click Dashboards in the left hand panel. Click the Actions drop down and select Create a New Dashboard. In the Create a new Dashboard window that pops up, enter Raspberry Pi in the Name field along with an optional Description such as Raspberry Pi based project. Feel free to name the dashboard something that has meaning to you. Click the Create button when done.
Now it is time to add our blocks (widgets) to visually interact with our feeds (data).
Click the Raspberry Pi dashboard we just created and you will be presented with a blank canvas. Click the + icon in the upper right corner of the page and a Create a new block pop-up window will appear with a table of available blocks we can choose. Hovering over the blocks will provide the name of the block. Select the Toggle block. In the next Choose feed window, select the Red LED feed and then click the Next step button. In the Block settings window, enter Red LED Control in the Block Title field and leave the Button On Text and Button Off Text fields as ON and OFF respectively.
You can test the values that will be produced by clicking on the toggle switch on the right side of the window. Click the Create block button to finish. Your block should now be displayed on the screen.
Next, create an Indicator block for the button and choose the Button feed. In the Block settings window, enter Button Indicator in the Block Title field, leave the On Color and Off Color colors as green and red, change the Conditions to > 0, and click the Create block button. The Button Indicator will be displayed below the Red LED Control bock.
The dashboard’s gear icon can be used to adjust your display settings such as size, location, and even change each block’s fields we initially set when an individual block’s gear icon is clicked. If you make any changes, make sure to click the Save button when finished.
Adafruit IO is now ready to interact with our program. Before we leave, we need to retrieve our account credentials that will be required for our program to access the system. Click the Dashboards link at the top of the page to bring you back a level. Then click the View AIO Key link in the left panel and the YOUR AIO KEY popup window will appear. Copy the Username and Active Key values shown for your account and save them for later use.
Building The Circuit
Before connecting any circuitry to your Raspberry Pi, shutdown and disconnect it from power. This avoids accidental damage during wiring.
Place the components and wire up the circuit on a breadboard according to the schematic diagram shown below and then connect it to your Raspberry Pi.
The circuit should look similar to the one shown below once completed.
Once the circuit is built, you can connect power to your Raspberry Pi and boot it up.
Writing The Software
From our Raspberry Pi, we first need to install the libraries required by our Python program. Install the RPi.GPIO library if it is not already installed.
$ pip3 install RPi.GPIO
Next, install the Adafruit IO library.
$ pip3 install adafruit-io
Now, open your favorite text editor and create a Python program named aio_led_button.py with the code shown below.
# aio_led_button.py # # Description: # Interfaces an LED and a button with the Adafruit IO service. # # Circuit: # Red LED connected to BCM pin 21, physical pin 40. # Momentary push button connected to BCM pin 5, physical pin 29. # # Created by John Woolsey on 05/24/2019. # Copyright (c) 2019 Woolsey Workshop. All rights reserved. # Libraries import RPi.GPIO as GPIO from time import sleep from Adafruit_IO import Client, Feed, RequestError # Pin Mapping button = 5 red_led = 21 # Global Variables AIO_USERNAME = "your_username" AIO_KEY = "your_key" AIO_BUTTON_FEED = "button" AIO_REDLED_FEED = "red-led" button_state = False red_led_state = False # Functions def button_pressed(button): """Toggles and sends button state to AIO service. Parameters: button: The pressed button. Returns: None """ global button_state print("Button pressed.") button_state = not button_state aio.send(button_feed.key, 1 if button_state else 0) # Main # Pin configuration GPIO.setmode(GPIO.BCM) # use BCM pin numbering GPIO.setup(button, GPIO.IN, pull_up_down=GPIO.PUD_UP) # utilize microprocessor's internal pull-up resistor GPIO.setup(red_led, GPIO.OUT) # Initialize interrupt service routine # Calls button_pressed() function when button is pressed, # i.e., the button pin value falls from high to low. GPIO.add_event_detect(button, GPIO.FALLING, callback=button_pressed, bouncetime=250) # Adafruit IO configuration aio = Client(AIO_USERNAME, AIO_KEY) # create Adafruit IO REST client instance try: # connect to existing button feed button_feed = aio.feeds(AIO_BUTTON_FEED) except RequestError: # or create button feed if it does not exist button_feed = aio.create_feed(Feed(name=AIO_BUTTON_FEED)) try: # connect to existing red LED feed red_led_feed = aio.feeds(AIO_REDLED_FEED) except RequestError: # or create red LED feed if it does not exist red_led_feed = aio.create_feed(Feed(name=AIO_REDLED_FEED)) # Synchronize feed states button_state = True if aio.receive(button_feed.key).value == "1" else False red_led_state = True if aio.receive(red_led_feed.key).value == "ON" else False GPIO.output(red_led, GPIO.HIGH if red_led_state else GPIO.LOW) print("Press CTRL-C to exit.") try: while True: # Retrieve and update LED state red_led_state = True if aio.receive(red_led_feed.key).value == "ON" else False GPIO.output(red_led, GPIO.HIGH if red_led_state else GPIO.LOW) # Do not flood AIO with requests sleep(0.5) # Cleanup finally: # exit cleanly when CTRL+C is pressed GPIO.cleanup() # release all GPIO resources print("\nCompleted cleanup of GPIO resources.")
Let’s take a look at some of the more interesting parts of the code.
Line 17 imports the items we need for our project from the Adafruit IO library.
Lines 26 and 27 hold your Adafruit IO credentials. Change these values to those representing your account.
Lines 28 and 29 are the feed keys (identifiers) we previously set up on the Adafruit IO site.
Lines 30 and 31 keep track of the current states of our LED and button.
Line 64 begins our configuration for connecting to the Adafruit IO service. We first initialize our
Client instance with the required account credentials using a name of
aio. We then try to access our preexisting
red-led feeds with the
feeds() function. If they do not yet exist, we fall back to creating them with the
Lines 75-77 use the
receive() function to obtain the current state of our feeds from the service, update the state variables accordingly, and then physically turn on or off the LED based on the current LED state.
An interrupt handler is set up at line 61 to run the
button_pressed() function whenever the button is pressed. The
button_pressed() function (defined in lines 36-48) toggles the button state and then sends the new state to Adafruit IO with the
send() function. Although the button we used is actually a momentary button, we are using it more as a switch and just changing the state for each subsequent press.
Lines 81-87 create an endless loop that polls the state of the red LED and physically turns it on or off based on the value received. The
sleep() function waits for half second before our next poll operation. We want turning on and off the LED to feel responsive, but we don’t want to flood the Adafruit IO service with requests. This is why 0.5 seconds was chosen.
If there is something that needs further explanation, please let me know in the comment section and I will try to answer your question.
Running And Testing The System
Now that our circuit is built and our software is written, it is time to run and test our project.
In a terminal window on the Raspberry Pi, run the following command to run the Python program. Note the
Adafruit_IO library requires Python 3.
$ python3 aio_led_button.py
Once the program is running, go back to the Adafruit IO website and open the Raspberry Pi dashboard. Click the Red LED Control switch (Toggle) and you should see the red LED light up on your breadboard. Woo Hoo! Turn it on and off a few times to verify everything is working properly.
Next, press the momentary button on your breadboard. You should see Button pressed. printed to your terminal screen along with the Button Indicator on Adafruit IO change from red to green. Again, press it a few times to verify that everything is okay. Sometimes you might see Button pressed. printed more than once if you press it slowly. If this is happening more often than you would like, you can adjust the button bouncetime from 250 ms to 500 ms in line 61 where we are setting up the interrupt handler.
Press CTRL-C to exit the program when you are done.
Now that our project has data we created during testing, go back and look at the feed data on Adafruit IO. Click Feeds in the left panel then click the Button feed. If you do not see the left panel, click either your username or Dashboards links at the the top of the screen and it will become visible. You will see your recent data points along with when they were created. Do the same for the Red LED feed.
In this tutorial, we learned how to use the Adafruit IO service to connect your Raspberry Pi to the outside world. We configured feeds for each of our connected electrical components and created a dashboard for interacting with those components on the Adafruit IO website. We wrote a Python program that communicates the states of our components with the Adafruit IO service and then used the service to interact with our components.
The final source code and schematic used for this tutorial are available on GitHub.
Don’t forget to check out all of the Adafruit IO based learning guides available by Adafruit.
Thank you for joining me in this journey and I hope you enjoyed the experience. Please feel free to share your thoughts in the comments section below.