Advertisement

Home IoT – Voice Controlled Lab Lights with Amazon Alexa and ESP8266

I recently won an Amazon Echo in a BBQ cooking competition and I was eager to get it set up in my house. As you may know, the Echo allows you to use voice commands to do things like order from Amazon, play music, set timers, and get the weather forecast.  By adding additional “skills”, it also allows you to integrate with smart home and Internet of Things (IoT) devices.

I integrated it with my Hue lights and my SmartThings hub by installing the relevant skills for those devices and was able to control everything with voice commands to Alexa.  But being a maker, I wasn’t satisfied with just buying premade devices.  I wanted to be able to create my own smart IoT gadgets that I could use with the Echo.

I had recently installed an Adafruit analog LED light strip for task lighting in my home lab but I needed a better way to control it.  Adding voice control to it would be a great solution.

Around 8 feet long, the lighting strip contains 18 sets of 4 LEDs per foot, in red, green, blue, and white colors, and runs on 12 volt DC power. The LEDs are arranged in repeating sets of 3, each with current-limiting resistors. One segment looks like this:

 

 

A logical choice for controlling a DIY smart home device is the ESP8266.  With an integrated microcontroller, 9 GPIO pins which can also be used for I2C or SPI, a serial UART, and built-in Wi-Fi, the ESP8266 has all of the elements required for a basic IoT device in an inexpensive package.  I already had an Adafruit HUZZAH ESP-8266 in my parts bin, so that’s what I chose to start with.

The missing piece was the software to make this work.  A brief search of the web led me to the fauxmoESP library. This is an Arduino IDE compatible software library that emulates a Belkin Wemo device and uses that protocol to communicate with the Echo.

 

Laying Out the Schematic

Armed with this information and the library code, all I needed to do was to put together a circuit and the code to control my LEDs.  Each segment of 3 LEDs draws around 20 mA of power per color, so that’s a total power draw of 80 mA per segment. I have an 8 foot strip, with 6 segments per foot, for a total of 6*8*80 mA = ~3.8 amps @ 12 volts.

The ESP8266 runs at 3.3 volts and has GPIO pins with a maximum current capacity of only 12 mA. To drive the 12 volt, high-current LED strip, we are going to need some help, in the form of a beefy external power supply and a quartet of N-Channel MOSFETs. The MOSFETs allow us to switch the 12 volt circuits on and off using the 3.3 volt GPIO pins on the ESP8266.  The basic circuit is shown below:

 

 

For testing, I assembled all of this on a breadboard and attached an 18 inch scrap piece of LED strip that I had left over from my project. 12 volt input power is supplied by my bench power supply and the 3.3 volt power for the ESP8266 is provided by an OKI regulator on the breadboard.

 

 

Setting Up the Code

With everything assembled, it was time to write the code.  I started out by installing the fauxmoESP library by downloading the zip file and adding it to the Arduino IDE.

Next, I copied the example code from the fauxmoESP_Basic.cpp into a blank Arduino sketch and saved it as fauxmo.ino, modifying it to match my selected GPIO pins and hardware. I created five virtual devices to control my LED lights:

  • “test red” for red LEDs
  • “test green” for green LEDs
  • “test blue” for blue LEDs
  • “test white” for white LEDs
  • “test lights” to control all 4 colors at the same time

 

#include 
#include 
#include "fauxmoESP.h"

#define SERIAL_BAUDRATE   115200
#define WIFI_SSID         "myssid"
#define WIFI_PASS         "topsecret"

fauxmoESP fauxmo;

void wifiSetup() {

    // Set WIFI module to STA mode
    WiFi.mode(WIFI_STA);

    // Connect to WIFI
    Serial.printf("[WIFI] Connecting to %s ", WIFI_SSID);
    WiFi.begin(WIFI_SSID, WIFI_PASS);

    // Wait
    while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(100);
    }
    Serial.println();

    // Connected!
    Serial.printf("[WIFI] STATION Mode, SSID: %s, IP address: %s\n", WiFi.SSID().c_str(), WiFi.localIP().toString().c_str());
}

void setup() {

    // Init serial port and clean garbage
    Serial.begin(SERIAL_BAUDRATE);
    Serial.println();
    Serial.println();

    // Wifi
    wifiSetup();

    // Output pins
    pinMode(12, OUTPUT);
    pinMode(13, OUTPUT);
    pinMode(14, OUTPUT);
    pinMode(16, OUTPUT);

    // You can enable or disable the library at any moment
    // Disabling it will prevent the devices from being discovered and switched
    fauxmo.enable(true);

    // Add virtual devices - these will be the device names in the Alexa app
    unsigned char device_0 = fauxmo.addDevice("test red");
    unsigned char device_1 = fauxmo.addDevice("test green");
    unsigned char device_2 = fauxmo.addDevice("test blue");
    unsigned char device_3 = fauxmo.addDevice("test white");
    unsigned char device_4 = fauxmo.addDevice("test lights");
 
    // fauxmoESP 2.0.0 has changed the callback signature to add the device_id, this WARRANTY
    // it's easier to match devices to action without having to compare strings.
    fauxmo.onMessage([](unsigned char device_id, const char * device_name, bool state) {
        Serial.printf("[MAIN] Device #%d (%s) state: %s\n", device_id, device_name, state ? "ON" : "OFF");
        switch (device_id) {
          case 0: // red
            state ? digitalWrite(12, HIGH) : digitalWrite(12, LOW);           
            break;
          case 1: // green
            state ? digitalWrite(13, HIGH) : digitalWrite(13, LOW);
            break;
          case 2: // blue
            state ? digitalWrite(14, HIGH) : digitalWrite(14, LOW);           
            break;
          case 3: // white
            state ? digitalWrite(16, HIGH) : digitalWrite(16, LOW);
            break;
          case 4: // all
            if (state) {
              digitalWrite(16, HIGH);
              digitalWrite(12, HIGH);
              digitalWrite(13, HIGH);
              digitalWrite(14, HIGH);             
            }
            else {
              digitalWrite(16, LOW);
              digitalWrite(12, LOW);
              digitalWrite(13, LOW);
              digitalWrite(14, LOW);
            }           
            break;
          default:
            // if nothing else matches, do the default
            // default is optional
          break;
        }
    });
  // The code below allows you to rename a device
  //fauxmo.renameDevice(device_2, "light five");
}

void loop() {

    // Since fauxmoESP 2.0 the library uses the "compatibility" mode by
    // default, this means that it uses WiFiUdp class instead of AsyncUDP.
    // The later requires the Arduino Core for ESP8266 staging version
    // whilst the former works fine with current stable 2.3.0 version.
    // But, since it's not "async" anymore we have to manually poll for UDP
    // packets
    fauxmo.handle();

    static unsigned long last = millis();
    if (millis() - last > 5000) {
        last = millis();
        Serial.printf("[MAIN] Free heap: %d bytes\n", ESP.getFreeHeap());
    }
}

 

 

Programming the ESP8266 in the Arduino IDE

The Adafruit ESP8266 that I used comes with the LUA interpreter installed by default.  To use the Arduino IDE, we are going to overwrite that by uploading our sketch to the device. To upload code, you need a USB to Serial TTL converter, for example an FTDI cable or similar. Mine is on port 13, so I selected that port in the IDE and connected the cable to the breadboard.

To upload the sketch, I put the ESP8266 into bootloader mode by doing the following:

  • Press and hold the GPIO0 button
  • Press and release the Reset button
  • Release the GPIO0 button

In the Arduino IDE, I set the board type to “Adafruit HUZZAH ESP8266” and the COM port to COM13, which is my USB to serial adapter board. Then, I uploaded the sketch, which also compiles the code.

 

 

Pairing with Alexa

Now that the code is uploaded to the ESP8266, we can check the Amazon Alexa apps for the new devices. First go to devices:

 

 

Then scroll to the bottom and select “discover”

 

 

We can now see our 5 devices: test green, test blue, test red, test white, and test lights. Test lights turns  all 4 colors on or off at the same time.

 

 

This was a fun and relatively easy project. I used this same design to Alexa-enable my workbench lights and now I have full voice control of my LED lights.  I’m sure I will find more uses for this project in the future. How would voice control work in your design projects? If you have used other voice control services, what did you think of them?

4 Comments

Join the conversation!

Error! Please fill all fields.
  • Oregonerd

    Line 110: if (millis() – last > 5000)
    Should that be: if (millis() – last > 5000)

    • Oregonerd

      When I copied and pasted the code the line read “& g t ;” (sans quotes and spaces) and wouldn’t compile. Further it copied and pasted into my reply the same way. I swear to the gods of coding!

      Today it appears to be automagically fixed in the html code snip on this page and my reply.

      I had to look at the fauxmoESP_Basic.cpp example code to find the “problem”. The mystery is mine. Browser issue probably 🙂

      The compiler error is still up in Arduino 1.8.5 on my other machine. Looking at it now.

      It’s all better now… Mostly…

      I simplified your code to turn the Red LED on the “Feather Huzzah” on and off. Works by tap in the Alexa app on my Android but not by voice on my Alexa.

      Thanks for the tutorial. Much appreciated!

    • Adam Carlson

      The two lines of code that you have up there are exactly the same. I am not seeing the difference.

  • Adam Carlson

    I could could see this being used in a home theater. Or even better, I could see this being used in a bath/shower setting to control water temperature. The ideas are coming, now I just need time to do them 😉

Looking for the latest from TI?