Introduction: How To: DIY Home Automation With NodeMCU and Amazon Alexa

About: Hello everyone. I have held many titles in my journey on this floating rock in space, but the one I am the most proud of is the title of Maker. I have been writing consumer electronic reviews, DIY tutorials, a…

If you read my last tutorial on DIY Home Automation with the LinkNode R4 and Amazon Alexa you already know the foundation of this tutorial, but instead of using a purpose built board this time, I am going to walk you through the steps to accomplish the same thing using a NodeMCU and a 4-channel relay board. As with every home automation tutorial I write, the purpose of these tutorials is not to show you how to fully integrate the system into your home's infrastructure, but to give you a starting point of how to control Mains AC powered devices using low-voltage DC devices.

Step 1: The Video

This video will show you what you can expect if you follow this tutorial. Watch it first, then read through the instructable to learn how to use Amazon Alexa to control relays in your home using NodeMCU.

Step 2: Bill of Materials

Step 3: Required Software and Documentation

To complete this project, you will need the following software and documentation.

Step 4: What Is NodeMCU?

NodeMCU is an open source IoT platform that includes firmware which runs on the ESP8266 Wi-Fi SoC from Espressif Systems, and hardware which is based on the ESP-12 module. By default the NodeMCU firmware uses the Lua scripting language which is based on the eLua project, and built on the Espressif Non-OS SDK for ESP8266. It uses many open source projects, such as lua-cjson, and spiffs.

Step 5: NodeMCU + Arduino IDE Home Automation

As Arduino.cc began developing new MCU boards based on non-AVR processors like the ARM/SAM MCU and used in the Arduino Due, they needed to modify the Arduino IDE so that it would be relatively easy to change the IDE to support alternate tool chains to allow Arduino C/C++ to be compiled down to these new processors. They did this with the introduction of the Board Manager and the SAM Core. A "core" is the collection of software components required by the Board Manager and the Arduino IDE to compile an Arduino C/C++ source file down to the target MCU's machine language. Several creative ESP8266 enthusiasts have developed an Arduino core for the ESP8266 WiFi SoC that is available at the GitHub ESP8266 Core webpage. This is what is popularly called the "ESP8266 Core for the Arduino IDE" and it has become one of the leading software development platforms for the various ESP8266 based modules and development boards, including NodeMCUs.

If you have not read my previous instructable on this subject, to get started using a NodeMCU you will need to perform a few task in the Arduino IDE to be able to begin programming your NodeMCU with the Arduino IDE. Follow the steps below to get the Arduino IDE set up to work with the ESP8266 and NodeMCU.

Step 6: Setting Up the Arduino IDE to Program the NodeMCU: Part 1

  • Follow the next several to download the Arduino IDE, and prepare it to program the ESP8266.
  • Before you get started you will need to download the latest version of the Arduino IDE here.
  • Once Arduino has been installed, run the program, and navigate to File > PreferencesEnter this URL “http://arduino.esp8266.com/stable/package_esp8266com_index.json” into the Additional Board Manager URLs field.

Step 7: Setting Up the Arduino IDE to Program the NodeMCU: Part 2

Open the Boards manager that is located in Tools > Board Menu > Boards Manager

Step 8: Setting Up the Arduino IDE to Program the NodeMCU: Part 3

Search and install the esp8266 platform (and don't forget to select your ESP8266 board from Tools --> Board menu after installation).

Step 9: Setting Up the Arduino IDE to Program the NodeMCU: Part 4

Finally, hover over the Tools menu and go to Tools ---> Board ---> and select the NodeMCU 0.9 (ESP-12 Module) board if you are using a NodeMCU V0.9 board, or the NodeMCU 1.0 (ESP-12 Module) board if you are using a NodeMCU V1.0 board.

Step 10: The Schematic

The schematic for this project is fairly simple and about as straightforward as it can be. Follow the diagram above along with the pin to pin connections listed in the next step to duplicate my setup. Note that the 20x4 Character LCD I am using has the I2C backpack already soldered on. If you wish to use a separate LCD and I2C backpack, follow the pinouts on your specific LCD and I2C backpack to ensure that they are connected properly.

Step 11: Pin to Pin Mappings

I2C Backpack to NodeMCU Connections

  • I2C Backpack GND Pin to NodeMCU GND Pin
  • I2C Backpack VSS Pin to NodeMCU 5Vin / 5V Pin
  • I2C Backpack SCL Pin to NodeMCU D1 Pin
  • I2C Backpack SDA Pin to NodeMCU D2 Pin

NodeMCU to 4-Channel Relay Board Connections

  • Relay Board GND Pin to NodeMCU GND Pin
  • Relay Board VCC Pin to NodeMCU 5Vin / 5V Pin
  • Relay Board Relay Pin 1 to NodeMCU Pin D5 / GPIO14
  • Relay Board Relay Pin 2 to NodeMCU Pin D8 / GPIO15
  • Relay Board Relay Pin 3 to NodeMCU Pin D9 / GPIO03
  • Relay Board Relay Pin 4 to NodeMCU Pin D10 / GPIO01

Step 12: The Code

I will not be sharing all of the files needed to get the NodeMCU up and running with Amazon Alexa here as it would be a lot of code. Please visit my GitHub to download a zip archive of all of the necessary files needed. Note that the code below will not compile, or upload without these additional files, so head over to my github to grab them all.

I will share the main Arduino sketch that I used so that you can have an idea of how everything ties together. I won't break down the entire code, but I will point out that I am creating four callbacks with unique names, four switches with unique names, and four integers which define the relays. I am also defining four unique invocation names for Alexa to understand, which are mapped to separate ports on the web server, and each unique invocation name has two settings, On and Off.

Finally, I set the pinmode for each of the four relay pins as an output. Then it is as simple as setting up eight different functions for each relay. With the type of relay board I am using, I also have to set all four of the relay pins to a HIGH state in the setup code. This is necessary due to the way the coils are wired inside the relays that are used on the board. A HIGH signal turns the relays off, and a low signal turns them on.

For example, when Alexa hears the “Turn on lightOne” command, the ESP8266 on the NodeMCU runs the lightOneOn function. There is a lot more that goes on with the code that handles the FauxMo Belkin WeMo emulation, and to be quite honest, I am not fully sure that I understand every aspect of it just yet. I do know that it works, and adding new devices (up to 14 is supported by WeMo and Alexa) is as easy as duplicating the things I mentioned above, and giving each new device a unique name. So without further ado, here is the Arduino sketch that makes the magic you saw in the video above work. Remember that this code is useless without the other five files that can be found on my Github repo for this project.

The LCD code and LCD hardware are completely optional and neither is required for this project to work. I included an LCD in the project for debugging / visual aid purposes only. If you do not wish to use an LCD in your project, simply comment out the LCD related code or remove it from the .ino file completely. Note: If you run into any issues with the code not compiling, make sure that the full set of files, six in total, are opened in the Arduino IDE, and that the folder they are stored in is named exactly like the main .ino file. Some users have experienced issues due to the folder name and the .ino file name being different.

Note: This code will not compile or upload to your device without downloading the additional five files needed for the FauxMos code to work. Download that code from my GitHub by clicking here.

/******************************************
   The unmodified version of this code is originally
   by kakopappa and can be found at  http://bit.ly/2kKQiRg.

   This version of the code has been modified by Charles Gantt
   and requires five additional files which can be found at  http://bit.ly/2kKQiRg.

   Find out more about this project on Charles' website
    http://bit.ly/2kKQiRg.

   Follow Charles and TheMakersWorkbench on the following sites:
   YouTube: bit.ly/TMWB-on-YouTube
   TMWB on Facebook: bit.ly/TMWB-on-Facebook
   CJGanttMakes on Facebook: bit.ly/CJGanttMakes
   TMWB on Twitter: bit.ly/TMWB-on-Twitter
   Charles Gantt on Twitter: bit.ly/CJGanttOnTwitter
   Instructables: bit.ly/CJGanttOnInstructables
   TMWB Website: bit.ly/TheMakersWorkbench
   Charles Gantt on Element14: bit.ly/CJGantt-On-E14
   Charles Gantt on GitHub: bit.ly/CJGantt-on-Github
*/

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiUdp.h>
#include <functional>
#include "switch.h"
#include "UpnpBroadcastResponder.h"
#include "CallbackFunction.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// prototypes
boolean connectWifi();

//on/off callbacks
void lightOneOn();
void lightOneOff();
void lightTwoOn();
void lightTwoOff();
void outletOneOn();
void outletOneOff();
void outletTwoOn();
void outletTwoOff();

// Change this before you flash
const char* ssid = "Skynet";
const char* password = "8039795700";

boolean wifiConnected = false;

UpnpBroadcastResponder upnpBroadcastResponder;

Switch *lightOne = NULL;
Switch *lightTwo = NULL;
Switch *outletOne = NULL;
Switch *outletTwo = NULL;

// Set Relay Pins
int relayOne = 14;
int relayTwo = 15;
int relayThree = 03;
int relayFour = 01;

// Addr: 0x3F, 20 chars & 4 lines. Sometimes display boards use address 0x27
LiquidCrystal_I2C lcd(0x3F, 4, 20); //Frentally display, use 0x3F if not working try 0x27

void setup()
{
  //Initalize LCD
  lcd.init();
  lcd.noBacklight();
  lcd.backlight();
  lcd.begin(20, 4);

  //Serial.begin(115200);

  // Initialise wifi connection
  wifiConnected = connectWifi();
  //Serial.print("WiFi Connected");

  if (wifiConnected) {
    upnpBroadcastResponder.beginUdpMulticast();

    // Show WiFi status on LCD along with SSID of network
    lcd.setCursor(0, 0);
    lcd.print("   WiFi Connected   ");
    lcd.print(ssid);

    // Define your switches here. Max 14
    // Format: Alexa invocation name, local port no, on callback, off callback
    lightOne = new Switch("Light One", 80, lightOneOn, lightOneOff);
    lightTwo = new Switch("Light Two", 81, lightTwoOn, lightTwoOff);
    outletOne = new Switch("Outlet One", 82, outletOneOn, outletOneOff);
    outletTwo = new Switch("Outlet Two", 83, outletTwoOn, outletTwoOff);

    //Serial.println("Adding switches upnp broadcast responder");
    upnpBroadcastResponder.addDevice(*lightOne);
    upnpBroadcastResponder.addDevice(*lightTwo);
    upnpBroadcastResponder.addDevice(*outletOne);
    upnpBroadcastResponder.addDevice(*outletTwo);

    //Set relay pins to outputs
    pinMode(14, OUTPUT);
    pinMode(15, OUTPUT);
    pinMode(03, OUTPUT);
    pinMode(01, OUTPUT);

    //Create Polling Message
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("   Polling Status   ");
    lcd.setCursor(0, 2);
    lcd.print("  Of Smart Devices  ");
    delay(2000);

    //Set each relay pin to HIGH this display status messagefor each relay
    digitalWrite(relayOne, HIGH);   // sets relayOne on
    lcd.clear();
    lcd.print("Light  One: Off     ");
    delay(500);
    digitalWrite(relayTwo, HIGH);   // sets relayOne on
    lcd.setCursor(0, 1);
    lcd.print("Light  Two: Off     ");
    delay(500);
    digitalWrite(relayThree, HIGH);   // sets relayOne on
    lcd.setCursor(0, 2);
    lcd.print("Outlet One: Off     ");
    delay(500);
    digitalWrite(relayFour, HIGH);   // sets relayOne on
    delay(500);
    lcd.setCursor(0, 3);
    lcd.print("Outlet Two: Off     ");

    //Create system initialized message
    lcd.clear();
    lcd.setCursor(0, 0);
    delay(1000);
    lcd.print(" System Initialzed  ");
    delay(1000);
    lcd.setCursor(0, 2);
    lcd.print(" Ready For Commands ");
    delay(2000);

    //Set up device status message
    lcd.clear();
    lcd.print("Light  One: Off     ");
    delay(500);
    lcd.setCursor(0, 1);
    lcd.print("Light  Two: Off     ");
    delay(500);
    lcd.setCursor(0, 2);
    lcd.print("Outlet One: Off     ");
    delay(500);
    lcd.setCursor(0, 3);
    lcd.print("Outlet Two: Off     ");


  }
}

void loop()
{
  if (wifiConnected) {
    upnpBroadcastResponder.serverLoop();
    lightOne->serverLoop();
    lightTwo->serverLoop();
    outletOne->serverLoop();
    outletTwo->serverLoop();
  }
}

void lightOneOn() {
  // Serial.print("Switch 1 turn on ...");
  digitalWrite(relayOne, LOW);   // sets relayOne on
  lcd.setCursor(0, 0);
  lcd.print("Light  One: On      ");
}

void lightOneOff() {
  // Serial.print("Switch 1 turn off ...");
  digitalWrite(relayOne, HIGH);   // sets relayOne off
  lcd.setCursor(0, 0);
  lcd.print("Light  One: Off     ");
}

void lightTwoOn() {
  // Serial.print("Switch 2 turn on ...");
  digitalWrite(relayThree, LOW);   // sets relayTwo on
  lcd.setCursor(0, 1);
  lcd.print("Light  Two: On      ");
}

void lightTwoOff() {
  // Serial.print("Switch 2 turn off ...");
  digitalWrite(relayThree, HIGH);   // sets relayTwo Off
  lcd.setCursor(0, 1);
  lcd.print("Light  Two: Off     ");
}

//sockets

void outletOneOn() {
  //  Serial.print("Socket 1 turn on ...");
  digitalWrite(relayFour, LOW);   // sets relayThree on
  lcd.setCursor(0, 2);
  lcd.print("Outlet One: On      ");
}

void outletOneOff() {
  // Serial.print("Socket 1 turn off ...");
  digitalWrite(relayFour, HIGH);   // sets relayThree off
  lcd.setCursor(0, 2);
  lcd.print("Outlet One: Off     ");
}

void outletTwoOn() {
  // Serial.print("Socket 2 turn on ...");
  digitalWrite(relayTwo, LOW);   // sets relayFour on
  lcd.setCursor(0, 3);
  lcd.print("Outlet Two: On      ");
}

void outletTwoOff() {
  // Serial.print("Socket 2 turn off ...");
  digitalWrite(relayTwo, HIGH);   // sets relayFour off
  lcd.setCursor(0, 3);
  lcd.print("Outlet Two: Off     ");
}

// connect to wifi – returns true if successful or false if not
boolean connectWifi() {
  boolean state = true;
  int i = 0;

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");
  Serial.println("Connecting to WiFi");

  // Wait for connection
  // Serial.print("Connecting ...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    //Serial.print(".");
    if (i > 10) {
      state = false;
      break;
    }
    i++;
  }

  if (state) {
    //  Serial.println("");
    //  Serial.print("Connected to ");
    //  Serial.println(ssid);
    // Serial.print("IP address: ");
    //  Serial.println(WiFi.localIP());
  }
  else {
    // Serial.println("");
    //Serial.println("Connection failed.");
  }

  return state;
}

Step 13: Bringing It All Together + Demonstration

With everything connected and the code uploaded to your NodeMCU, you can now connect some mains powered devices to the relays, and then ask Alexa to turn on the corresponding devices. Check out the video above, and if there is enough interest in building the demonstration board I used, I will make a video, and Instructable for that as well.

So that is going to wrap up this project for now. If you are interested in seeing more videos, and reading more tutorials / reviews like this, please head over to my YouTube Channel, and click on the subscribe button. Also remember to click the like button on the video above, and to leave me a comment on what you thought about this project. Stay tuned for more Amazon Alexa, and NodeMCU / ESP8266 related content. I have a whole series planned out, that will culminate in my entire office being automated. Watch the video above to see the project in action. As always, remember to #HackTheWorld and #MakeAwesome!

Additionally, if you would like to see more tutorials like this, as well as the more of the other types of articles I post over at The Makers Workbench, head over to my Patreon page and consider donating monthly to help me keep the lights on. Every donation counts, and with your support, we can continue to create great content that you like week in and week out!

Sensors Contest 2017

Participated in the
Sensors Contest 2017

Microcontroller Contest 2017

Participated in the
Microcontroller Contest 2017