ESP8266 and ESP32 AT Commands

NodeMCU V3, ESP8266

In this tutorial, I’ll show you some of the important and frequently used ESP8266 AT Commands or AT Instruction Set.  

ESP8266 WiFi Module offers complete networking solutions to our DIY (Do-it-yourself) and IoT (Internet of Things) projects. It provides WiFi connectivity to any microcontroller through its full TCP/IP Stack.

This means that you can use the ESP8266/ESP32 like a WiFi Modem, this is especially handy when you don’t want to reprogram an entire module for a project, or if you already have a working project on an Arduino type board, and just want to add WiFi connectivity to the project.



It is however important to tell you that it is sometimes better to write your own code to achieve exactly what you want. The AT Commands, in my opinion, is however extremely useful to quickly test something, or do a very simple integration. Your opinion and or milage will definitely vary on this one, feel free to comment and make suggestions as always 🙂

Kidbright 32, based on the ESP32 WROOM Chip

Let us get started then

Please NOTE:

The AT Command Set will ONLY function on a NEW ESP8266/ESP32 Module that you have not loaded custom firmware onto, OR on a module that you have re-flashed with the AT Command Firmware. This means that, If you have used the Arduino IDE to upload custom code to your ESP8266/ESP32 module, these commands will NOT work for you,
UNLESS you flash the module with ESPRESSIF AT Command Firmware!

The ESP8266 WiFi module and the microcontroller can be interfaced through the UART and with the help of a wide range of AT Commands, the Microcontroller can then control the ESP Module.

The AT Commands of the ESP8266 WiFi Module are responsible for controlling all the operations of the module like restarting, connecting to WiFi, changing the mode of operation and so forth.

Basically, the ESP8266 AT Commands can be classified into four types:

  • Test
  • Query
  • Set
  • Execute

In the following table, I will give you an example of the different types of AT Commands. I will use a sample command of “TEST” to demonstrate the differences between the different type of commands.

Command TypeCommand FormatCommand Function
TestAT+TEST=?Returns a value or a range of parameters
QueryAT+TEST?Returns the current value of a certain parameter
SetAT+TEST=parameter1, parameter2, …Set configuration of a certain parameter of group of parameters
ExecuteAT+TESTExecutes an action
Types of AT Commands for ESP8266 or ESP32

Test Commands: The Test AT Commands of ESP8266 WiFi Module are used to get the parameters of a command and their range.

Query Commands: The Query Commands returns the present value of the parameters of a command.

Set Commands: The Set Commands are used set the values of the parameters in the commands and also runs the commands.

Execute Commands: The Execute Commands will run the commands without parameters.  

NOTE: Not all of the ESP8266 AT Commands support all the four command types.

The ESP8266 AT Commands Set is divided into three categories. They are:

  • Basic AT Commands 
  • WiFi AT Commands 
  • TCP/IP AT Commands 

There are a total of 88 AT Commands for ESP8266 WiFi Module. We will however only look at a few of the most important ones.

If you want to know the details of all the ESP8266 AT Commands, then I suggest that you visit the official documentation page provided by Espressif Systems (the manufacturer of ESP8266EX SoC),  here.   

NOTE: The Parameters mentioned in [] are optional.

Basic ESP8266 AT Commands

As per the official documentation from Espressif Systems, there are a total of 23 Basic AT Commands.

Basic AT Commands
AT
AT+RST
AT+GMR

AT

This is the basic command that tests the AT start up i.e. if the AT System is working correctly or not. If the AT start up is successful, then the response is OK.

CommandResponse
ATOK

AT+RST

This command can be used to restart (reset) the ESP8266 WiFi Module.    

CommandResponse
AT+RSTOK

AT+GMR

This command is used to check the version information of the firmware and SDK. The response consists of three things: the AT Firmware version, the SDK version and the compilation time of the BIN file.

CommandResponse
AT+GMR<AT Version><SDK Version><Compile Time>OK

Other important Basic AT Commands: AT+GSLP, ATE and AT+UART.

WiFi AT Commands

The WiFi AT Commands are useful in controlling the WiFi features of the ESP8266 Module like setting up the WiFi Mode of operation, get the list of WiFi Networks, connect to a WiFi Network, setup the Access Point (AP), control DHCP, WPS, MAC Address, IP Address etc.

As per the official documentation, there are 40 WiFi AT Commands for ESP8266 Module. Let me introduce a few important AT Commands.

WiFi AT Commands
AT+CWMODE
AT+CWJAP
AT+CWLAP
AT+CWQAP
AT+CIPSTA
AT+CWSAP
AT+CWLIF

AT+CWMODE

This command is used to set the WiFi Mode of operation as either Station mode, Soft Access Point (AP) or a combination of Station and AP. The CWMODE command supports Test, Query and Set type commands.

The syntax, response and parameters (in Set command) of this command are given in the following table.

AT+CWMODE
Command TypeTestQuerySet
FormatAT+CWMODE=?AT+CWMODE?AT+CWMODE=<mode>
Response+CWMODE:<mode>OK+CWMODE:<mode> OKOK
Parameters<mode>1: Station2: Soft Access Point (AP)3: Station+SoftAP
Function Returns current WiFi ModeSets WiFi Mode
      

AT+CWLAP

This command lists out all the available WiFi Networks in the reach of ESP8266. It has both Set and Execute Command types.

AT+CWLAP
Command TypeSetExecute
FormatAT+CWLAP[=<ssid>,<mac>,<channel>,<scan_type>,<scan_time_min>,<scan_time_max>]AT+CWLAP
Response+CWLAP:<ecn>,<ssid>,<rssi>,<mac>,<channel>,<freq      offset>,<freq   cali>,<pairwise_cipher>,<group_cipher>,<bgn>,<wps>OK

NOTE: For more information on Parameters, please refer to the original documentation.

AT+CWJAP

This command is to connect to an Access Point (like a router).

AT+CWJAP
Command TypeQuerySet
FormatAT+CWJAP?AT+CWJAP=<ssid>,<pwd>[,<bssid>]
Response+CWJAP:<ssid>,<bssid>,<channel>,<rssi>OKOKor+CWJAP:<error>FAIL
Parameters<ssid>: SSID of the Access Point.<pwd>: Password.[<bssid>]: MAC Address of AP (usedwhen multiple APs have the same SSID.)<error>1: Connection timeout.2: Wrong password.3: Cannot find the target AP.4: Connection failed.

AT+CWQAP

This command is used to disconnect the ESP8266 from an Access Point.

CommandResponse
AT+CWQAPOK

AT+CIPSTA

This command is used to set a static IP Address to the ESP8266 WiFi Module in Station Mode. This command has both Query and Set type commands.

AT+CIPSTA
Command TypeQuerySet
FormatAT+CIPSTA?AT+CIPSTA=<ip>[,<gateway>,<netmask>]
Response+CIPSTA:<ip>+CIPSTA:<gateway>+CIPSTA:<netmask> OKOK
Parameters<ip>: IP Address<gateway>: Gateway<netmask>: Netmask
FunctionReturns the IP address, Gateway and Netmask.Sets IP Address, Gateway and Netmask.

AT+CWSAP

This command is used to configure the ESP8266 WiFi Module in Soft Access Point (AP) Mode. Both Query and Set types are available for this command.

AT+CWSAP
Command TypeQuerySet
FormatAT+CWSAP?AT+CWSAP =<ssid>,<pwd>,<chl>,<ecn>[,<maxconn>][,<ssid  hidden>]
Response+CWSAP:<ssid>,<pwd>,<chl>,<ecn>,<max conn>,<ssid hidden>OKorERROR
Parameter<ssid>: SSID of AP.<pwd>: Password.<chl>: Channel ID.<ecn>: Encryption method.0: OPEN2: WPA_PSK3: WPA2_PSK4: WPA_WPA2_PSK<max conn>: Max # of Stations<ssid hidden>:0: SSID is broadcasted. (default)1: SSID is not broadcasted.

AT+CWLIF

Using this command, you can get the IP addresses of Stations that are connected to ESP8266, which is configured in SoftAP Mode.

AT+CWLIF
Format (Execute Command)AT+CWLIF
Response<ip addr>,<mac>OK
Parameters<ip address>: IP Address of the Station<mac>: MAC Address of the station

TCP/IP AT Commands

The TCP/IP AT Commands are responsible for communication over the internet. There are a total of 25 TCP/IP AT Commands for ESP8266 WiFi Module. Some of the important ones are mentioned here.

TCP/IP Commands
AT+CIPSTATUS
AT+CIPSTART
AT+CIFSR
AT+CIPMUX
AT+CIPSERVER
AT+CIUPDATE

AT+CIPSTATUS

This TCP/IP AT Command of the ESP8266 WiFi Module get the information or status of the connection. Only the Execute type command is available.

AT+CIPSTATUS
Command TypeExecute
FormatAT+CIPSTATUS
ResponseSTATUS:<stat>+CIPSTATUS:<linkID>,<type>,<remoteIP>,<remoteport>,<localport>,<tetype>
Parameter<stat>:2: Connected to an AP and its IP is obtained.3: Created a TCP or UDP transmission.4: Disconnected.5: Does NOT connect.<linkID>: ID of the connection.<type>: “TCP” or “UDP”.<remoteIP>: Remote IP address.<remoteport>: Remote port number.<localport>: Local port number.<tetype>:0: Client.1: Server.

AT+CIPSTART

This AT Command is used to establish one of the three connections: TCP, UDP or SSL. Depending on the type of TCP Connection (single or multiple), the format of the Set command will vary.

AT+CIPSTART
Command TypeSet
FormatSingle TCP ConnectionMultiple TCP Connection
AT+CIPSTART=<type>,<remoteIP>,<remoteport>[,<TCPkeepalive>]AT+CIPSTART=<linkID>,<type>,<remoteIP>,<remoteport>[,<TCPkeepalive>]
ResponseOKorERROR(Response when TCP connection is already established:ALREADY CONNECTED)
Parameters<link    ID>: ID of connection.<type>: “TCP”, “UDP” or “SSL”.<remoteIP>: Remote IP address.<remoteport>: Remote port number.[<TCPkeepalive>]: detection time interval

NOTE: The above table shows command for only establishing the TCP Connection. For establishing UDP and SSL Connections, please refer to the official documentation.

AT+CIFSR

This AT Command is used to obtain the IP Address of the ESP8266 WiFi Module.

AT+CIFSR
Command TypeExecute
FormatAT+CIFSR
Response+CIFSR:APIP,<SoftAPIPaddress>+CIFSR:APMAC,<SoftAPMACaddress>+CIFSR:STAIP,<StationIPaddress>+CIFSR:STAMAC,<StationMACaddress>OK
Parameters<SoftAPIPaddress>: IP address of the ESP8266 SoftAP;<SoftAPMACaddress>: MAC address of the ESP8266 SoftAP<StationIPaddress>: IP address of the ESP8266 Station.<StationMACaddress>: MAC address of the ESP8266 Station

AT+CIPMUX

This AT Command is used to enable or disable multiple TCP Connections.

AT+CIPMUX
Command TypeQuerySet
FormatAT+CIPMUX?AT+CIPMUX=<mode>
Response+CIPMUX:<mode>OKOK
Parameters<mode>:0: Single connection1: Multiple connections

AT+CIPSERVER

This AT Command is used to create or delete a TCP Server.

AT+CIPSERVER
Command TypeSet
FormatAT+CIPSERVER=<mode>[,<port>]
ResponseOK
Parameters<mode>:0: Delete Server.1: Create Server.

NOTE: A TCP Server can be created only when AT+CIPMUX=1 i.e. multiple connections are enabled.

AT+CIUPDATE

This AT Command is used update the software through WiFi Connection i.e. for over the air (OTA) updates.

AT+CIUPDATE
Command TypeExecute
FormatAT+CIUPDATE
Response+CIPUPDATE:<n>OK
Parameters<n>:
1: Find the Server
2: Connect to the Server
3: Get the Software Version
4: Start Update

I have included a PDF file with the complete AT command Set for download below.

Arduino Web Server – Part 2

Introduction


In my previous post, I showed you how to use AJAX and JavaScript to make a very responsive Web server on Arduino. In Part 2, we will look at making some important modifications.

Arduino has limited storage space – Use an SD Card

As all of us already know, the Arduino, especially the Uno and Nano, has very limited storage space. If we want to create a truly useful IoT Web server device, we need to do something to increase the available storage space on our Arduino Device.

We can however not increase the program memory. What we can do is store our static HTML page, as well as any images and icons, on a SD-CARD. These come in many sizes,
but for our example, I will use a 2gb card, not that we will use all of it anyway.

The standard Arduino Ethernet Shield also comes standard with a SD-CARD reader slot already built in.

Arduino Ethernet Shield for Arduino Uno or Mega. Note That SD Card Slot is already built in

This makes our lives a lot easier. You can also buy a stand-alone SPI SD Card module for a few bucks online. This will be needed if you try to make this project using an Arduino Nano.

Preparing the Card for use

You should format your card using your computer, and a suitable adapter. The card should be formatted to the FAT filesystem. NTFS or other filesystems does unfortunately not work as far as I know.

SD Card IO – How to use the SD Card in Arduino

The Arduino IDE already includes an SD Card library. You can also download additional libraries from the internet that allows more specialized control and functionality. The standard library will however be sufficient for our needs.

It is also easy to test if your card is working or not. The code below is from the “CardInfo” example that ships with the Arduino IDE

/*
  SD card test

  This example shows how use the utility libraries on which the'
  SD library is based in order to get info about your SD card.
  Very useful for testing a card when you're not sure whether its working or not.

  The circuit:
    SD card attached to SPI bus as follows:
 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
 ** CS - depends on your SD card shield or module.
 		Pin 4 used here for consistency with other Arduino examples


  created  28 Mar 2011
  by Limor Fried
  modified 9 Apr 2012
  by Tom Igoe
*/
// include the SD library:
#include <SPI.h>
#include <SD.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// MKRZero SD: SDCARD_SS_PIN
const int chipSelect = 4;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  Serial.print("\nInitializing SD card...");

  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    while (1);
  } else {
    Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.println();
  Serial.print("Card type:         ");
  switch (card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    while (1);
  }

  Serial.print("Clusters:          ");
  Serial.println(volume.clusterCount());
  Serial.print("Blocks x Cluster:  ");
  Serial.println(volume.blocksPerCluster());

  Serial.print("Total Blocks:      ");
  Serial.println(volume.blocksPerCluster() * volume.clusterCount());
  Serial.println();

  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("Volume type is:    FAT");
  Serial.println(volume.fatType(), DEC);

  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  volumesize /= 2;                           // SD card blocks are always 512 bytes (2 blocks are 1KB)
  Serial.print("Volume size (Kb):  ");
  Serial.println(volumesize);
  Serial.print("Volume size (Mb):  ");
  volumesize /= 1024;
  Serial.println(volumesize);
  Serial.print("Volume size (Gb):  ");
  Serial.println((float)volumesize / 1024.0);

  Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  root.openRoot(volume);

  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
}

void loop(void) {
}

Open this example in your Arduino IDE, and then make sure that the CS pin is set to the correct pin for your Ethernet Shield ( Pin 10 is for Ethernet, Pin 4 is usually for the SD Card).

Both of these devices will be connected to the SPI bus on your Arduino, and the CS pin will determine which device is active, by being pulled LOW.

Insert your formatted card into the slot, power on the Arduino, and upload the sketch to the Arduino. Open the Serial monitor. If all goes well, you should see information about your SD Card ( Size, sectors etc being displayed ). If your card was already formatted to the FAT file system and contained other files, the names of these files will also be displayed.

Create your Web Page

Power down the Arduino, and remove the SD Card. Put it into the relevant adapter and connect it to your computer.

Now, open a plain text editor, notepad on windows, or any other specialized html editor, as long as you feel comfortable with it, and create a simple html file. Feel free to use my example below, and modify it to your liking

<!DOCTYPE html>
<html>
    <head>
        <title>Arduino SD Card Web Page EXAMPLE - Maker and IOT Ideas</title>
    </head>
    <body>
        <h1>Welcome to your Arduino Based Web Server</h1>
        <p>This page is stored on the SD Card connected to your Arduino.</p>
        <p>Please do not remove the card while the Arduino is connected to a power source</p>

    </body>
</html>

Save this file as index.htm, and remove the card from your computer, making sure that you properly stop it as per the standard procedures for your operating system.

Put it back into the slot on the Arduino Ethernet Shield, open the serial monitor, and apply power to your Arduino. make sure that you see the file, index.htm listed in the output.

Coding your Webserver

Our next step will be to write the code to create our Arduino Web Server. This code will be similar to the code in part 1 of this series, but I recommend that you start fresh, open a new sketch, and copy-paste my code into the IDE. you can always modify it later to suit your needs…

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 100, 32); // IP address, may need to change depending on network
EthernetServer server(80);  // create a server at port 80

File webFile;

void setup()
{
    
    
    // initialize SD card
    Serial.println("Initializing SD card...");
    if (!SD.begin(4)) {
        Serial.println("ERROR - SD card initialization failed!");
        return;    // init failed
    }
    Serial.println("SD card initialized. [OK]");
    // check for index.htm file
    if (!SD.exists("index.htm")) {
        Serial.println("ERROR - Can't find index.htm file!");
        return;  // can't find index file
    }
    Serial.println("index.htm file found - Starting Webserver");

    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin();           // start to listen for clients
    Serial.begin(9600);       // for debugging
}

void loop()
{
    EthernetClient client = server.available();  // try to get client

    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                if (c == '\n' && currentLineIsBlank) {
                    // send a standard http response header
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println("Connection: close");
                    client.println();
                    // send web page
                    webFile = SD.open("index.htm");        // open web page file
                    if (webFile) {
                        while(webFile.available()) {
                            client.write(webFile.read()); // send web page to client
                        }
                        webFile.close();
                    }
                    break;
                }
                // every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)
}

Upload the sketch to your Arduino and navigate to the IP Address of the server using your browser. You should see the page displayed as you coded it.

What to do from here

You can now modify your page to include links and even images and CSS styling. You should however remember that the Arduino also does not have a lot of RAM memory.
You should thus not add extremely large images or pages. Those will take a long time to display, or may even time-out and not display at all

In the next part of this series, I will show you how to add links, images and CSS to make your page look a bit more visually appealing. We will also integrate the AJAX and JavaScript
functionality from the previous part of the series, to allow our server to interact with the inputs and outputs on the Arduino.

Arduino Web Server using AJAX – Part 1

There are many ways to use Arduino to create your own IoT device. One of the easiest is to configure your Arduino as a Web Server. This way, you can connect to it from any browser capable device on your home network. It is also quite a bit safer to do it this way, as you don’t have to expose your device to the internet, reducing the security implications of many of the other methods available.

It does, however, have the disadvantage of not being able to connect to your device from outside your home network. ( In a later part of this series, I will show you how to do this relatively safely, but take note that you still won’t have SSH encryption to the device, that is a huge security risk in today’s online world.

What use will this kind of IoT device have?

You can use an Arduino based web server to monitor various devices in your home, as well as control them. Many of us have old Android tablets and other devices lying around, that may be to old to run the newest Android Operating System. Such a Tablet can however be mounted to a wall, to provide a permanent display and control device. You will only be limited by your imagination, as well as your skill with interfacing your devices with electronics and Arduino.

A few examples of this can be
– controlling lights
– controlling a fan
– measuring temperature and light levels using various sensors, and performing actions based on those values

But Arduino Web Servers are slow

The normal Arduino web servers that we have all seen in various projects on the internet are indeed slow and cumbersome. This is because they usually have to refresh and reload the entire page to display every single update of a switch or output. We can however take advantage of technology used on computer web servers, as well as the browser of the end user.

Ajax and Javascript

What is AJAX?

AJAX stands for Asynchronous JavaScript and XML.

AJAX is basically the use of JavaScript functions for getting information from the webserver (Your Arduino). This means that data on a web page can be updated without fetching the whole page each time.

This means that only the relevant part of the web page will be updated, either automatically, or when the end user performs an action, like click on a button, or when an input on the actual Arduino changes state.

What is JavaScript?

JavaScript is a client-side scripting language. This means that the code will run on the web browser. Meaning on the end-user computer or mobile device.

The JavaScript is included in the HTML page that will be served by the Arduino Webserver. When you load the web page hosted by the Arduino, the page and the JavaScript is loaded to your browser. Your browser then runs the JavaScript code (provided that you have not disabled JavaScript in your browser).

What will we need to do this?

You will need the following hardware and software to do this project

– Arduino UNO or Compatible
– Arduino Ethernet Shield with NO SD-Card Inserted
– Breadboard
– 1K resistor
– LED
– 10k OR 22k Resistor
– Hookup Wire (5 pieces)
– Push Button

The Circuit

Wire the following circuit on your breadboard

Circuit Diagram for the Arduino AJAX Web Server – Part 1

Connect your Ethernet Shield to the Arduino Uno.
Connect the Resistors, LED and push-button Switch as shown.
Connect +5v from Arduino to Red Line, Gnd From Arduino to Blue line

Connect Orange Wire from Arduino Pin 2 to a hole BETWEEN the 10k resistor and the switch ( See Diagram).
Connect Green Wire from Arduino Pin 3 to a hole above the 1k resistor ( See Diagram)

The Code

Copy the following code into your Arduino IDE, Or download the file below

#include <SPI.h>
#include <Ethernet.h>
// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 100, 32); // IP address, may need to change depending on network
EthernetServer server(80); // create a server at port 80
String HTTP_req; // stores the HTTP request

void setup()
{
Ethernet.begin(mac, ip); // initialize Ethernet device
server.begin(); // start to listen for clients
Serial.begin(9600); // for diagnostics
pinMode(2, INPUT_PULLUP); // switch is attached to Arduino pin 2
pinMode(3, OUTPUT);
digitalWrite(3,LOW);
}

void loop()
{
EthernetClient client = server.available(); // try to get client
if (client) { // got client? 
boolean currentLineIsBlank = true; 
while (client.connected()) 
{ if (client.available()) 
{ // client data available to read char c = client.read(); // read 1 byte (character) from client HTTP_req += c; // save the HTTP request 1 char at a time 
// last line of client request is blank and ends with \n 
// respond to client only after last line received 
if (c == '\n' && currentLineIsBlank) { // send a standard http response header client.println("HTTP/1.1 200 OK"); 
client.println("Content-Type: text/html"); 
client.println("Connection: keep-alive"); 
client.println(); // AJAX request for switch state 
if (HTTP_req.indexOf("ajax_switch") > -1) 
{ 
// read switch state and send appropriate paragraph text 
GetSwitchState(client); 
} else 
{ 
// HTTP request for web page // send web page - contains JavaScript with AJAX calls 
client.println("<!DOCTYPE html>"); 
client.println("<html>"); 
client.println("<head>"); 
client.println("<title>Arduino Web Page with AJAX - Maker and IoT Ideas</title>"); 
client.println("<script>"); 
client.println("function GetSwitchState() {"); 
client.println("nocache = \"&nocache=\"\ + Math.random() * 1000000;"); 
client.println("var request = new XMLHttpRequest();"); 
client.println("request.onreadystatechange = function() {"); 
client.println("if (this.readyState == 4) {"); 
client.println("if (this.status == 200) {"); 
client.println("if (this.responseText != null) {"); client.println("document.getElementById(\"switch_txt\")\.innerHTML =this.responseText;");

client.println("}}}}");
client.println("request.open(\"GET\", \"ajax_switch\" + nocache, true);");
client.println("request.send(null);");
client.println("setTimeout('GetSwitchState()', 1000);");
client.println("}");
client.println("");
client.println("");
client.println(""); 
client.println("Arduino Web Server with AJAX"); 
client.println("Switch Status on D2"); 
client.println( "Switch state: Not requested…"); 
client.println("");
client.println("");
}
// display received HTTP request on serial port
Serial.print(HTTP_req);
HTTP_req = ""; // finished with request, empty string
break;
}
// every line of text received from the client ends with \r\n
if (c == '\n') {
// last character on line of received text
// starting new line with next character read
currentLineIsBlank = true;
}
else if (c != '\r') {
// a text character was received from client
currentLineIsBlank = false;
}
} // end if (client.available())
} // end while (client.connected())
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection
} // end if (client)
}

// send the state of the switch to the web browser
void GetSwitchState(EthernetClient cl)
{
if (digitalRead(2)) {
cl.println("Switch at D2 is: OFF, LED at D3 is OFF");
digitalWrite(3,LOW);
}
else {
cl.println("Switch at D2 is: ON, LED at D2 is ON");
digitalWrite(3,HIGH);
}
}

Upload the code to your Arduino

Testing the results

Open a web browser and go to the IP Address of the server ( the one you set in your code).
If you did everything correctly, you should see a screen similar to this.

The Ajax Web Server shows the button and LED is OFF

Now press the button

The web page should immediately update and tell you that the button is On, and the LED is ON


Ajax Web Server showing Status of Button and LED as ON

The Generated HTML will look like this

<!DOCTYPE html>

<html>

<head>

<title>Arduino Web Page with AJAX - Maker and IoT Ideas</title>

<script>

function GetSwitchState() {

nocache = "&nocache=" + Math.random() * 1000000;

var request = new XMLHttpRequest();

request.onreadystatechange = function() {

if (this.readyState == 4) {

if (this.status == 200) {

if (this.responseText != null) {

document.getElementById("switch_txt").innerHTML = this.responseText;

}}}}

request.open("GET", "ajax_switch" + nocache, true);

request.send(null);

setTimeout('GetSwitchState()', 1000);

}

</script>

</head>

<body onload="GetSwitchState()">

<h1>Arduino Web Server with AJAX</h1>

<h3>Switch Status on D2</h3>

<p id="switch_txt">Switch state: Not requested...</p>

</body>

</html>

Images of the Working Hardware

Please note that I did not use a push button switch in my example. I have just used a piece of hookup wire to connect the pulled-up pin to ground, as it is easier to photograph that way, without my finger being in the way on a button. 🙂

Conclusion

This concludes part 1 of this series. This example can very easily be extended to be more useful, as well as be modified to work on other platforms, like ESP32.
In further parts, I will show you how to extend this very simple server into becoming something much more useful. Please visit again to see the rest of this series.

ESP32 (Kid Bright v 1.3) Voice-Activated IoT Relay Control using IFTTT and Adafruit IO

Today I will show you how to do a very quick IoT relay controller using IFTTT and Adafruit IO. I will be using the Kid Bright v 1.3 Development board, from Gravitec in Thailand. These boards sell for about $USD 25 to 35 each, quite expensive as far as I am concerned, for the amount of functionality that you get.

I will also post a link to the Video Tutorial at the bottom of this tutorial.

Kid Bright v 1,3 Development Board, Advanced user Diagram
Kid Bright 32 Schematic

You can find out more about this board on the Kid Bright Website. Please note that you will need Google Translate, as the site is in the Thai Language.

We will use IFTTT to connect Google Assistant to Adafruit IO in order to control our IoT Relay controller with voice commands.

Let us start our project.

Start the Arduino IDE, and make sure that you have enabled support for NodeMCU or other ESP32 based processors.
You also need to load the libraries for Adafruit IO.

After you have done that, open the “adafruitio_07_digital_out” sketch from the Examples folder for Adafruit IO. We will modify this example to suit our needs, as well as save some time on coding.

Change the Example to the following:
Remember to change the pins to reflect your particular setup.

include “config.h”

define LED_PIN 17
define Relay 27

// set up the ‘readinglight’ feed
AdafruitIO_Feed *readinglight = io.feed(“readinglight”);

void setup() {

pinMode(LED_PIN, OUTPUT);
pinMode(Relay, OUTPUT);

// start the serial connection
Serial.begin(115200);

// wait for serial monitor to open
while(! Serial);

// connect to io.adafruit.com
Serial.print(“Connecting to Adafruit IO”);
io.connect();

// set up a message handler for the ‘readinglight’ feed.
// the handleMessage function (defined below)
// will be called whenever a message is
// received from adafruit io.
readinglight->onMessage(handleMessage); // Handler for our FEED

// wait for a connection
while(io.status() < AIO_CONNECTED) {
Serial.print(“.”);
delay(500);
}

// we are connected
Serial.println();
Serial.println(io.statusText());
readinglight->get();

}

void loop() {

// io.run(); is required for all sketches.
// it should always be present at the top of your loop
// function. it keeps the client connected to
// io.adafruit.com, and processes any incoming data.
io.run();

}

// this function is called whenever an ‘readinglight’ feed message
// is received from Adafruit IO. it was attached to
// the ‘digital’ feed in the setup() function above.
void handleMessage(AdafruitIO_Data *data) {

Serial.print(“received <- “);

if(data->toPinLevel() == HIGH)
Serial.println(“HIGH”);
else
Serial.println(“LOW”);

digitalWrite(LED_PIN, !data->toPinLevel()); // We inverse the logic on the LED, we want it on //when the relay is on, and off when the relay is off
digitalWrite(Relay, data->toPinLevel()); // My Relay Module is Active LOW, so this is correct.
//reverse the logic if your module is Active High
}

Another very important step is that you need to set your Adafruit IO IO-Key in the config.h file. Your Wifi SSID and Password also needs to be supplied here, to enable your ESP32 based processor to connect to Adafruit through your WiFi connection.

Config.h

/ Adafruit IO Config */
define IO_USERNAME “your AdafruitIO username”
define IO_KEY “your AdafruitIO IO Key”
define WIFI_SSID “your wifi ssid”
define WIFI_PASS “your wifi password”

Leave everything else as is in the config.h file

Now login to Adafruit IO, or create a new account if you have not done so already.
Create a new feed, in my case called readinglight, under your feeds.

Click on the Adafruit IO Key button ( top right corner ) and copy your IO Key and Username into the config.h file in the Arduino IDE. Don’t upload your code yet.

Now go to IFTTT, and login or create a new account if you don’t have one already.
After you have logged in, in a new window, go to https://www.ifttt.com/adafruit

Make sure to connect Adafruit and IFTTT, and allow IFTTT to send messages to Adafruit IO.

Then, follow the pictures, and create your first applet.

Select “Say a Simple phrase”
Configure it with what you want to say to activate the relay, Then Click “Create Trigger”
Click on :Adafruit”
Click Send Data to Adafruit IO
Select you feed from the drop-down box. IMPORTANT, USE A 1 to switch something ON, or a 0 to switch it OFF. HIGH AND LOW, or ON and OFF DOES NOT WORK ! Then Click on Create Action
Review your applet, Switch OFF notifications, and Click on Finish.

Now create another Applet, Doing exactly the same, but change your wording to “Light OFF” and the Adafruit IO Data to 0. This applet will be used to switch off the Relay.

Go back to the Feed window in Adafruit IO, and then test Google Assistant by saying your command, like “Hey Google, Light On” and “Hey Google, Light Off”

You should see data arriving in your feed window after each command. A 1 for On and a 0 for Off.

Now go back to your Arduino IDE, Open the Serial Monitor, and Compile and Upload your Code. Test it again, but now you should see data arriving in the Serial Monitor as well.

If all of this is working, You can connect your Relay to the board, and test it again.
When you are happy that all is working as it should, Connect a load to the relay, and enjoy your new Voice-Activated IoT Relay Controller.

It is also easy to add another feed to the existing code. Ask me how if you don’t understand, but it should be quite easy to figure out from the code as well 🙂

https://youtu.be/Q-uwU55VAF4
Voice Controlled IoT Relay controller using Google Assistant, IFTTT and Adafruit IO