Tutorial: Alexa with Indoor Air Quality
In this tutorial we show you how to set-up an Amazon Alexa smart speaker based on a Raspberry Pi 3 that you can ask for the current indoor air quality, ambient temperature and humidity.


Prerequisites
Software
- AWS Account and AWS developer account
- A computer with SSH setup (Ubuntu LTS is recommended)
- Basic Linux and Raspberry Pi know-how is of Advantage
- Here you can download the sample codes for smart speaker resources: smart_speaker_resources.tar.gz
Hardware Components
- Raspberry Pi 3
- ReSpeaker 2-Mics Pi HAT
- SHTC1 and SGPC3 connected to i2c-1 (e.g. as a Raspberry Pi Shield)
- A speaker up to 1 Watt (we use a 0.5 Watt speaker)
- JST 2.0 Micro cable to connect the speaker to the Re-Speaker
- Optional: a couple of spacers and screws and a plexiglas cover
Hardware Assembly
Note that for the rest of the tutorial, we'll be using Sensirion's Environmental Sensor Shield; if you're using your own sensor Hardware, please make sure you connect them in the same way, connecting to I2C-1.
Step 1

Install 2 x 12 mm2 female-female spacers to the site with the shield connector of the Raspberry Pi 3 and 2 x 12 mm2 male-female spacers to the opposite site.
Step 2

Add 2 x 10 mm2 female-female spacers to the middle holes of sensor shield as shown in the picture below.
Step 3

Plug the sensor shield onto the Raspberry Pi 3 and screw it down.
Step 4

Install 2 x 10 mm2 female-female spacers to the Respeaker-2 mic HAT. You can skip this step if you don’t have a plexiglass cover.
Step 5

Plug the ReSpeaker board onto the sensor board and screw down. If you have a plexi glass cover, you can also stack the 10 mm male-female and 12mm female-female spacer and add them as pictured below.
Step 6

Cut the JST 2.0 to the appropriate length and solder it to the speaker.
Step 7

Glue the Speaker on the plexiglass cover, and install the cover on top. Afterwards you can plug in the JST 2.0 cable.
Software Setup
Step 1: Prepare your host system
All instructions assume you are running an Ubuntu or other Debian-like operating system. For other operating systems, please refer to official documentation here.
sudo apt-get install zip pv
Step 2: Setup Raspberry PI
- Download the latest raspbian stretch light image from the official Homepage: www.raspberrypi.org/downloads/raspbian/
- Unzip and install it on your SD-Card. Make sure the output device points to your SD card.
unzip 2017-11-29-raspbian-stretch-lite.zip pv 2017-11-29-raspbian-stretch-lite.img | sudo dd of=/dev/mmcblk0 oflag=sync bs=4M
- Setup SSH connection:
You need to connect a keyboard and display to the Raspberry Pi for the initial setup.
Enable SSH
sudo systemctl enable ssh sudo systemctl start ssh
Setup DHCP on eth0 and disable dhcpcd service (we will setup our own configuration with dnsmasq)
sudo systemctl disable dhcpcd.service
create directory for dnsmasq
mkdir -p /etc/dnsmasq.d/
And setup own dhcpd service: Create a file /etc/dnsmasq.d/dhcp with the following content
# DHCP only on eth0 interface=eth0 dhcp-range=eth0,192.168.1.100,192.168.1.199,4h # disable sending DNS server and router dhcp-option=3 dhcp-option=6
- Setup Network connection:
Create a file /etc/wpa_supplicant/wpa_supplicant.conf with the following content:
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 network={ ssid="<my-wifi-name>" scan_ssid=1 proto=RSN key_mgmt=WPA-PSK pairwise=CCMP TKIP group=CCMP TKIP psk="<my-wifi-password>" }
Replace <my-wifi-name> and <my-wifi-password> with the SSID and password of your wifi.
Edit /etc/network/interfaces and replace everything in there with the following content
auto lo auto wlan0 auto eth0 iface lo inet loopback iface default inet dhcp allow-hotplug eth0 iface eth0 inet static address 192.168.1.10 netmask 255.255.255.0 network 192.168.1.0 broadcast 192.168.1.255 allow-hotplug wlan0 iface wlan0 inet dhcp pre-up wpa_supplicant -Dwext -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf -B pre-down killall wpa_supplicant
Now you can restart and finalize networking
sudo systemctl restart networking.service sudo apt install dnsmasq
- Setup SSH connection
From your host you can now setup the SSH connection for easy access
ssh-copy-id pi@192.168.1.10
From now on you can ssh into the Raspberry Pi with ssh pi@192.168.1.10
- Setup I2C and SPI
We use raspi-config to enable i2c and spi for the Raspberry Pi. The options are under 4 Interfacing Options
sudo raspi-config
Note: You can also expand the file system if you like, so you can use the whole space of the SD-card. Allow the user to access the spi and i2c interfaces by configuring two udev rules:
sudo addgroup i2c sudo addgroup spi
/etc/udev/80-i2c.rules
KERNEL=="i2c-dev", GROUP="i2c", MODE="0660" # set I2C permissions for regular I2C drivers SUBSYSTEM=="i2c", RUN+="/bin/chgrp -R i2c /sys%p", RUN+="/bin/chmod -R g=u /sys%p" # set I2C permissions for input-type I2C drivers SUBSYSTEM=="input", RUN+="/bin/chgrp -R i2c /sys%p", RUN+="/bin/chmod -R g=u /sys%p"
/etc/udev/81-spi.rules
KERNEL=="spidev*", GROUP="spi", MODE="0660"
And in /boot/config.txt add the following: /boot/config.txt
dtparam=i2c0=on dtparam=i2c1=on dtparam=i2c_arm=on dtparam=i2c_vc=on dtparam=i2c0_baudrate=40000 dtparam=i2c1_baudrate=40000
and in /etc/modules
i2c-bcm2708 shtc1 sgpxx
Now install some tools we need on the Raspberry Pi (make sure the wifi connection from on the Raspberry Pi works)
sudo apt-get install build-essential raspberrypi-kernel-headers git python-pip i2c-tools sudo pip install virtualenv spidev
- Setup the sgpc3 driver
Copy the driver source to the raspberry pi
scp sgpxx.tar.gz pi@192.168.1.10:
Unpack it and compile it
Install SGPC3 driver and crc8 dependency
mkdir -p src/sgpxx tar -xzf sgpxx.tar.gz -C src/sgpxx # Install CRC8 module cd src git clone https://github.com/Sensirion/crc8.git cd crc8 make sudo install -p -m 644 crc8.ko /lib/modules/$(uname -r)/kernel/drivers/ sudo depmod -a sudo modprobe crc8 # Install SGPxx driver cd ~/src/sgpxx/ make sudo install -p -m 644 sgpxx.ko /lib/modules/$(uname -r)/kernel/drivers/iio/ sudo depmod -a sudo modprobe sgpxx
- Reboot the Raspberry Pi
sudo reboot
Step 3: Install AlexaPi
We are using AlexaPi project to setup the connection to Alexa. Before installing Alexa Pi you have to setup an Alexa Voice Service. You can follow the instructions (only 1. Register at Amazon) on this page: github.com/alexa-pi/AlexaPi/wiki/Installation
Make sure you also add 192.168.1.10:5050 as an allowed endpoint for the registration, so you can register the alexa device from your host computer.
There are also plenty of other resources available online on how to register a device. Make sure you write down all the credentials, you will need them in this step.
Execute the following steps on the Raspberry Pi to install AlexaPi:
sudo su cd /opt git clone https://github.com/alexa-pi/AlexaPi.git /opt/AlexaPi/src/scripts/setup.sh
You will be asked for some information.
For the first few questions you can just click enter, the defaults are fine:
- OS: debian
- Your device: raspberrypi
- Do you want AlexaPi to run on boot? 1 - yes systemd
- Would you like to also install Airplay support? Yes (or no, it does not matter)
When you are asked for the client setup:
Enter your Device Type ID []: Enter your Security Profile Description []: Enter your Security Profile ID []: Enter your Client ID []: Enter your Client Secret []:
After AlexaPi is finished with the installation you have to open 192.168.1.10 on your host computer which will forward you to the AWS login. Login with your amazon account and the alexa device will be connected to your user. You should now also be able to find and configure the device under alexa.amazon.com
Patch AlexaPi
Copy the following 2 files to /opt/AlexaPi/src/alexapi/device_platforms/
- ap102.py
- respeaker2micplatform.py
Update /etc/opt/AlexaPi/config.yaml and change the device to "respeaker2mic" and add the respeaker2mic config to platforms:
platform: device: "respeaker2mic" platforms: respeaker2mic: # GPIO Pin with button connected button: 17
Setup SPI and GPIO access
sudo adduser alexapi spi sudo adduser pi gpio sudo adduser pi i2c
(optional) Audio debugging for root and pi user
sudo adduser root audio sudo adduser pi audio
Load SHTC1 and SGPC3 on startup. Add the following to /etc/rc.local
echo sgpc1x 0x58 | sudo tee /sys/class/i2c-adapter/i2c-1/new_device echo shtc1 0x70 | sudo tee /sys/class/i2c-adapter/i2c-1/new_device udevadm trigger
- Step 5: Setup ReSpeaker 2 mic head
On the raspberry pi
sudo su cd /opt git clone https://github.com/respeaker/seeed-voicecard.git cd seeed-voicecard sudo ./install.sh 2mic
- Step 6: Restart Raspberry Pi
Restart your Raspberry Pi
sudo reboot
- Step 7: Configure Alsa
Use alsamixer to set the microphones and speaker levels
Recommended settings (press F4 to get to playback settings):

Step 8: Setup IAQ Logger
We are using the Sensirion cloud to upload the logged data. If you want to use a different backend like AWS IoT please adapt the code accordingly or use a different logger.
On the Raspberry Pi create a folder for the IAQ logger
sudo mkdir ~/iaq_logger
Copy the iaq logger code onto the Raspberry Pi into the newly created folder
scp iaq_logger_app.tar.gz pi@192.168.1.10:iaq_logger/
On the Raspberry Pi
cd iaq_logger tar -xzf iaq_logger_app.tar.gz
And run setup.sh (as pi user)
./setup.sh
Setup Indoor Air Quality Skill
To use the indoor air quality feature we have to implement a custom skill and connect it to AWS lambda. A full documentation on how to configure such a skill can be found on the amazon developer page:
https://developer.amazon.com/docs/custom-skills/host-a-custom-skill-as-an-aws-lambda-function.html
You can choose the alexa-skills-kit-color-expert-python and replace the code with the on provided in the package.
On the developer.amazon.com you can now configure a new Alexa skill. For our smart speaker we used to following interaction model.
Setup Indoor Air Quality Skill
{ "languageModel": { "intents": [ { "name": "AirQuality", "samples": [ "tell me air quality", "tell me indoor air quality" ], "slots": [] }, { "name": "AMAZON.CancelIntent", "samples": [] }, { "name": "AMAZON.HelpIntent", "samples": [] }, { "name": "AMAZON.StopIntent", "samples": [] }, { "name": "Humidity", "samples": [ "tell me humidity", "tell me ambient humidity" ], "slots": [] }, { "name": "Temperature", "samples": [ "tell me temperature", "tell me ambient temperature" ], "slots": [] } ], "invocationName": "sensirion" } }
Congrats, you've made it! Try asking Alexa the following "Alexa, ask Sensirion what's the temperature?".