Introduction: Control Raspberry Pi GPIO With Amazon Echo and Python

The main goal of this instructable to use Alexa's voice commands with an Amazon Echo to control the GPIO on a Raspberry Pi using Python. This instructable has been adapted from the Memory Game example at Flask-Ask: A New Python Framework for Rapid Alexa Skills Kit Development.

An Echo is not required but is highly recommended. This is a very simple example but demonstrates how easy it is to expose the Raspberry Pi's functionality to Alexa with just a few lines of Python.

The main reason I am writing this is because I could not find a similar guide elsewhere and felt the functionality was cool enough that it deserved one. There are currently several different ways of adding custom Smart Home programming to Alexa but as far as I know this is the first method using Raspberry Pi and Python.

Step 1: Initial Setup

I used a Raspberry Pi 3 and a fresh Raspbian Jessie-lite image downloaded from

Two terminal sessions will be needed so using SSH to access the Pi is recommended. Once logged in, enter the following commands to install the required packages and python libraries:

sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install python2.7-dev python-dev python-pip
sudo pip install Flask flask-ask

Step 2: Setup Ngrok

I couldn't think of a better explanation so here is a quote from Amazon's guide I linked earlier:

ngrok is a command-line program that opens a secure tunnel to localhost and exposes that tunnel behind an HTTPS endpoint. ngrok makes it so Alexa can talk to your code right away. Follow the next three steps to generate a public HTTPS endpoint to

Visit and get the latest Linux ARM release as a zip and unzip inside the home directory:

unzip /home/pi/

Next, run it from the command line with:

sudo ./ngrok http 5000

Your screen should look like the image above. Note the 'Forwarding' URL that starts with https, it will be used later.

Note: Unfortunately the ngrok URL changes every time the service is started so it is not a permanent solution if you are trying to run this full time. I'd recommend a service like Yaler or Page Kite if you need a more permanent URL to use with your new Skill.

Step 3: Python Script

Open a new terminal session and create a new python file named


Copy/paste the following code into the new file:

from flask import Flask
from flask_ask import Ask, statement, convert_errors import RPi.GPIO as GPIO import logging


app = Flask(__name__) ask = Ask(app, '/')


@ask.intent('GPIOControlIntent', mapping={'status': 'status', 'pin': 'pin'}) def gpio_control(status, pin):

try: pinNum = int(pin) except Exception as e: return statement('Pin number not valid.')

GPIO.setup(pinNum, GPIO.OUT)

if status in ['on', 'high']: GPIO.output(pinNum, GPIO.HIGH) if status in ['off', 'low']: GPIO.output(pinNum, GPIO.LOW)

return statement('Turning pin {} {}'.format(pin, status))

Save and close the file.

Start the flask server with:

sudo python

Leave both ngrok and running while we setup the new skill in AWS...

Step 4: AWS Account

First create or login to your AWS Developer Account and open your list of Alexa skills.

Step 5: Alexa Skill - Information

Set the Skill Name to 'GPIO Control' and the Invocation Name to the word(s) you want to use to activate the skill. Click 'Next' to continue.

Step 6: Alexa Skill - Interaction Model

Copy/paste the following into the 'Intent Schema' box:

"intents": [{

"intent": "GPIOControlIntent",

"slots": [{

"name": "status",

"type": "GPIO_CONTROL"

}, {

"name": "pin",





Next, click 'Add Slot Type' and under 'Enter Type' write in 'GPIO_CONTROL'. Under 'Enter Values' write:


This is just a simple example. 'high', 'low' or pretty much any other word could be added.

Copy/paste the following into the 'Sample Utterances' box:

GPIOControlIntent to turn pin {pin} {status}

Click on 'Save' and then 'Next'.

Step 7: Alexa Skill - Configuration

Select 'HTTPS' as the Service Endpoint Type and select a region.

Enter the ngrok URL from step 2 and click 'Next'. The URL should be something like:

Step 8: Alexa Skill - SSL Certificate

Select the 'My development endpoint is a sub-domain of a domain that has a wildcard certificate from a certificate authority' option and click 'Next'.

Step 9: Alexa Skill - Testing

If everything was setup correctly you should now see a screen similar to the first image above. The Skill is now enabled and can be accessed through any Amazon Echo device(or at that is connected to your AWS Developer Account using the following syntax:

Alexa, tell Raspberry Pi to turn pin {pin number} {on or off}

For example:

Alexa, tell Raspberry Pi to turn pin twenty one on

If you are having any issues, the simplest way to test the Skill would be to use the Voice or Service Simulator found on the Test page. Try entering the following into the 'Enter Utterance' box under the Service Simulator:

 turn pin twenty one on

Then hit 'Ask GPIO Control' to run the test.

Step 10: Wrapping Up

After testing there is no need to continue through the Skill setup any further as the rest applies to releasing the skill publicly. As far as I can tell there is nothing stopping someone from running this continuously in a 'development' mode for personal use though... My ultimate goal is to use this to integrate Alexa into my existing Raspberry Pi-based Smart Home setup so that everything can be controlled hands-free.

This was my first Instructable so any feedback is appreciated. If you have any questions or trouble setting this up I will do my best to help. Good luck!

Step 11: Bonus Points - Using Words Instead of Pin Number

If you've followed all of the above steps and want to add some more functionality you can create an intent that can be called with actual words like 'fan' or 'light' by following the steps below.

Add the following code to

@ask.intent('LocationControlIntent', mapping={'status': 'status', 'location': 'location'})
def location_control(status, location):

locationDict = { 'fan': 12, 'light': 21 }

targetPin = locationDict[location]

GPIO.setup(targetPin, GPIO.OUT)

if status in ['on', 'high']: GPIO.output(targetPin, GPIO.HIGH) if status in ['off', 'low']: GPIO.output(targetPin, GPIO.LOW)

return statement('Turning {} {}!'.format(location, status))

Copy/paste the following into the 'Intent Schema' box:


"intents": [{
        "intent": "LocationControlIntent",
        "slots": [{
            "name": "status",
            "type": "GPIO_CONTROL"
            "name": "location",
            "type": "LOCATION"


Next, click 'Add Slot Type' and under 'Enter Type' write in 'LOCATION'. Under 'Enter Values' write down any words you want to be able to use to trigger this intent, for example:


Copy/paste the following into the 'Sample Utterances' box:

LocationControlIntent to turn {location} {status}
LocationControlIntent to change the {location} to {status}

Click on 'Save' and it will update your settings and after that the new phrases will be usable. Example:

Alexa, tell Raspberry Pi to turn fan on
Alexa, tell Raspberry Pi to change the light to off
IoT Builders Contest

Participated in the
IoT Builders Contest

First Time Authors Contest 2016

Participated in the
First Time Authors Contest 2016