1.
Part Description |
Amazon.com |
---|---|
Amazon Alexa Device | Amazon Echo Dot |
NodeMCU Development Board | NodeMCU V1.0 |
4-Channel Relay Board | SainSmart 4-Channel Relay Module |
20x4 I2C Character LCD | SainSmart IIC/I2C/TWI 20x4 LCD |
Dupont Style Jumper Wires | Haitronic 120pc Dupont Jumper Wires |
Bread Board | Qunqi 830 tie point & 400 tie point Breadboard Kit |
Part Description |
URL |
---|---|
Arduino IDE | Download the latest version of Arduino here |
WeMos Source Code | Download my version of the FauxMos source code here |
NodeMCU Documentation | Visit the NodeMCU project homepage here |
If you read my last tutorial on DIY Home Automation with the LinkNode R4 and Amazon Alexa you already know the jist 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 here at The Makers Workbench, the purpose of both 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.
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.
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 post 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.
Follow the steps below to download the Arduino IDE, and prepare it to program the ESP8266.
1. Download the latest version of the Arduino IDE here.
2. Once Arduino has been installed, run the program, and navigate to File > Preferences
3. Enter this URL “http://arduino.esp8266.com/stable/package_esp8266com_index.json” into the Additional Board Manager URLs field.
4. Now open the Boards manager that is located in Tools > Board Menu > Boards Manager
5. Then search and install the esp8266 platform (and don't forget to select your ESP8266 board from Tools --> Board menu after installation).
6. 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.
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 below 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.
I2C Backpack to NodeMCU Connections
NodeMCU to 4-Channel Relay Board Connections
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.
/****************************************** 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/2lRDwAJ Find out more about this project on Charles' website http://www.themakersworkbench.com 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); 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; }
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.
If you would like more tutorials such as this, just let me know in the comments. Additionally, if you would like to see more tutorials like this, as well as the more of the other types of articles we post here at The Makers Workbench, head over to our Patreon page and consider donating monthly to help us keep the lights on. Every donation counts, and with your support, we can continue to post a couple of tutorials each week.