Project tutorial
ESP01 Webserver to Control Your Arduino UNO, Mega or Nano

ESP01 Webserver to Control Your Arduino UNO, Mega or Nano © GPL3+

Using WiFi to control your Arduino UNO, Nano or Mega as a basis. Includes feedback and simple hardware.

  • 1,561 views
  • 3 comments
  • 10 respects

Components and supplies

Necessary tools and machines

09507 01
Soldering iron (generic)
Reel of Solder
Pliers

Apps and online services

About this project

The Reason

I wanted to build a control unit which worked on WiFi, so it was without wires and as cheap as possible. I managed, with this project, to control up to 10 output devices (On/Off) and have up to 8 inputs to sense local conditions.

The cheapest Arduino compatible WiFi add-on was the ESP-01 made by Espressif Inc and available cheaply on Ebay from many suppliers, mine cost £1.42.

You will also need the programming manual (pdf) from www. Espressif.com it is called

4a-esp8266_at_instruction_set_en.pdf.

It covers all versions of the chipset when used as a modem, which is what we are going to do.

The Arduino is going to be the controlling board as it has the input and output sockets as well the language to control it built in. There are lots of different versions, but this was built on the Arduino UNO R3 version which is the simplest and the cheapest, although not the smallest. You would have to mount the WiFi board via wires to to the Ardunio board for Power and IDC connections to Outputs 2 and 3.

I also bought this on Ebay and it cost £3.20.

However it should work on ALL versions including Nano and Mega, as it only uses the basic commands, makes available ALL digital outputs and reads the Analogue inputs

Although there are lots of Libraries out there for the Arduino, none of them worked on the UNO, as it had only one hardware serial port, which the USB used to connect it to a PC for programming. Therefore I had to use two Digital ports and a piece of software called SoftwareSerial.h, which is part of the Arduino core program.

The ESP-01 WiFi board is connected to the Arduino using these connections. The only other connections I used were for Power (the board uses 3.3v supply from the Arduino board), which also goes to the Chip enable pin to turn on the WiFi and Ground (0 volts).

I avoided using the programming facility of the ESP-01 to keep it simple, and just relied on the supplied Firmware, within the chipset.

The Hardware

As the UNO R3 has a place on the board for a socket to connect up other devices I used this to connect the board up to power and also provide a mounting bracket for the ESP-01 board. I used a standard connection strip for the sockets and soldered it in underneath the board so it was flush with UNO, making a sturdy base for the mounting bracket. The ESP-01 comes with 8 pins, so I needed another socket to connect them to the board without soldering them direct. This required a double set of single pins to be mounted on a stripboard, with the copper side upper most, so the pins on the short side could be soldered to the pad and leave room for the wiring between the ESP-01 socket and the pins.

Board layout showing bracket and socket added on board

I also epoxy resined a thick piece of copper wire a bracket to suspend the ESP-01 above the Arduino board. The copper wire goes around, but not touching the pins on the underside of the stripboard, after the pins have been soldered in place. The other end of the wire goes to either side of the socket holding the ESP-01, where again it is held in place by Epoxy resin.

Stripboard connections

This provides a sturdy structure where the bracket can be removed from the Arduino board safely at any time and the ESP-01 board can be removed in case it goes faulty or is required for other projects.

The connections are as follows:-

Board Layouts

ESP-01 Pin 1 to GND on Ardunio bracket.

ESP-01 Pin 5 to 3.3v on Ardunio bracket.

ESP-01 Pin 7 to 3.3v on Arduino bracket.

ESP-01 Pin 8 to Digital Port 2 on Arduino (via a lead soldered to the socket and a Single Pin to inserted in the Arduino socket)

ESP-01 Pin 4 to Digital Port 3 on Arduino (via a lead soldered to the socket and a Single Pin to inserted in the Arduino socket)

For Nano and Mega connect it via wires to IDC pins plugged into the board, same as the digital ports shown in the diagram.

Do not use the RX, TX ports on the board as these are for the USB and you could damaged the ESP-01 board.

Also do not use the +5v power, as this will also damaged the ESP-01 board.

The rest is just software!

Pin 13 LED, the rest are the same connections to GND and Output pin.

The LED's shown on the Picture are just used to test the outputs are working, they all have 1K resistors between them and the output Pin. The Other side is connected to Gnd pin on the Arduino board. The resistor is not the right Colours, but this is a limitation of Fritzing!

The Analogue pins are left unconnected, for use as inputs, either as inputs from other devices or switches. They are not needed to be connected to test the board or the software as they generate a value unconnected.

The Software

You need the Arduino IDE (Integrated Development Environment) which is FREE and downloadable from Ardunio.cc. The.ino program I have written and a program called a TCPclient to control the board through WiFi from a PC, Android or Iphone. These are also FREE and downloadable from the platforms you normally use (Google play for instance) or searched for through Google.com.

You need to install the IDE program on a PC or Linux machine to transfer the program to the UNO board.

The R3 version comes with a USB socket on the board to connect up a standard data lead (not a charger lead) on modern mobile phones. The other end goes into a USB 2 port on the PC.

You use this for programming, but when operating the board it requires a Battery of 7-12 volts to be connected to the UNO board power socket to power both boards. It does work, despite comments on various forums.

Once the board has been accepted by the IDE software you can cut and paste the program into a new “sketch” as they call the program. When you save it in the IDE it will be converted into a.ino program which you can name yourself.

TheProgram

[code]
// You may use on board LED connected to pin 13
// Elminated delays and serial monitor commands, reduced response time to 5 seconds.
#include <SoftwareSerial.h>
int serialRx = 2;   // software serial  RX  TX 
int serialTx = 3;   // ESP-01 RX goes to this port, TX goes to Port 2
int d = 0;
// ESP-01 CH_PD pin 7 Must go to 3.3v, not +5v to enable operation as UART (AP)
// UNO R3 has enough power to make it work.
// No other connections required
String inMsg ;     // variable to collect strings
int sensorPin = 8;    // set maximum number of pins for the Analouge inputs
int LEDPin = 13 ;  // variable to assign pin to LED.
int responseTime = 10; //communication timeout
SoftwareSerial portOne(serialRx, serialTx); // communications port to ESP-01
String Msg = ""; // to collect Analouge input data 
void setup() {
// Serial.begin(19200); // for debugging only
String  msg =""  ; 
 portOne.begin(115200);                // Start software serial port
 delay(200);
 sendToWifi("ATE0",100);  // set Echo Off. Otherwise echo was ON.
 sendToWifi("AT+CWMODE=2",responseTime); // configure as access point on Chinese version
 // sendToWifi("AT+CWMODE_CUR = 2",responseTime); // configure as access point (AP)
 sendToWifi("AT+CIPMUX=1",responseTime); // configure for multiple connections
 // AT+CIPAP=<ip>[,<gateway>,<netmask>]
 sendToWifi("AT+CIPAP_CUR=\"192.168.5.1\"",responseTime); // Set IP address for AP
 sendToWifi("AT+CIPSERVER=1,80",responseTime); // Create and turn on server on port 80
 sendToWifi("AT+CWDHCP_CUR=0,1",responseTime); // Set AP with DHCP ON (required)
 //AT+CWSAP=<ssid>,<pwd>,<chl>,<ecn>[,<max conn>][,<ssid hidden>]
 // Open AP Port
 sendToWifi("AT+CWSAP=\"ESP8266\",\"1234567890\",5,3,1,0",responseTime); // Set Soft AP parameters problems sending " characters
 sendToWifi("AT+CIPAP_CUR?",responseTime);
 sendToWifi("AT+CIPSTO=600",responseTime); // Set timeout to 10 minutes
 pinMode(LEDPin,OUTPUT); // Open Port to operate LED on board
//   //serial.println("Setup is done!");
 // delay(2000);
}
void loop() {
  //Serial.println("Waiting....");
 if(portOne.available()>0){
   inMsg = readFromWifi();
   //serial.print("Received msg inside loop = ");
   inMsg.toUpperCase();
  // Serial.println(inMsg);
   // Messages in CAPITALS
   if (inMsg.endsWith("HELLO") ) {
   // Serial.println ("Wifi says : Hello");
       sendData("Wifi says : Hello\r");    // Send confirmation of Command + CR
       Send_inputs();
 }
   else if (inMsg.endsWith("LEDON") ){
         digitalWrite(LEDPin,HIGH);       // If just LEDON turn on Pin 13
         sendData("Wifi says : LEDON\r");        // Send confirmation of Command + CR
         Send_inputs(); // Send Analouge inputs
   }
  else if (inMsg.endsWith("LEDOFF") ){  
      String     msg = SETLEDS(0) ; // set all LEDs off.
       sendData("Wifi says : LEDOFF\r");   // Send confirmation of Command + CR  
       Send_inputs(); // Send Analouge inputs     
   }   
   else if (inMsg.indexOf("LEDONN",0)>6 ){  // if Command is to set a Number
        d = inMsg.indexOf("LEDONN",0)+6; // Set d to next letter after command // string starts with zero
    int a = 0; // zero collected number
    int dt = inMsg.length(); // find end of string (CR)
   if ( d+3 < dt){              // if there is a 4 digit number after command
           a = inMsg.substring(d, d+4).toInt(); // store 4 digits in number a
     String    msg ="ERROR";
           if ((a > 0) & (a < 1024) ) {  // Command not used for zero (use LEDOFF), avoids no number available
            msg = SETLEDS(a) ; // set all LEDs on or off, returns Binary string as confirmation
            }
            msg = "Wifi says : LEDONN="+msg+"\r";
           sendData(msg ); // Send confirmation of Command + CR
            Send_inputs();  // Send Analouge inputs
            }
  }
  // delay(9000);                              // deliberately large delay to help collect dump of serial port.
}
    inMsg="";  // Clear buffer
   delay(800); // delay to stop duplicate messages
}
void sendToWifi(String command, const int timeout){
// only send command, not intereted in response
 String response = "";
 // Serial.print("Sent command to ESP8266-E12: ");
  // Serial.print(command);
 delay(50);
 portOne.println(command); 
 long int time = millis();
 while( (time+timeout) > millis())
 {
   while(portOne.available())
   { 
     char c = portOne.read(); 
     response+=c;
   }  
 }
  // Serial.print("Response from ESP8266-E12: ");
  // Serial.print(response);
}
String  readFromWifi(){
 char arrayInMsg[100];
 String tempStr; 
 int count =0;
 while( portOne.available() > 0 ){
   arrayInMsg[count]= portOne.read();
   delay(80);
   // get out if you see CR or LF
   if ((arrayInMsg[count]=='\n') or (arrayInMsg[count]=='\r')) break; 
   // changed character array comparison or it causes errors
   count++;       
 }
 arrayInMsg[count] = '\0';                     // Null terminate finally
 tempStr = String (arrayInMsg);                // cast it to string
 tempStr.trim();                               // precaution
 // Serial.print(tempStr);
 return tempStr;
}
/*
* Name: sendData
* Description: Function used to send string to tcp client using cipsend
* Params: 
* Returns: void
*/
void sendData(String str){
 String len="";
 len+=str.length();
 sendToWifi("AT+CIPSEND=0,"+len,responseTime); // Setup command to send str data length to channel 0
 delay(100);
 sendToWifi(str,responseTime);//Send String str with 0 closing the transmission and return to AT mode
  delay(100);
 do {
 delay(100);
 } while (portOne.available()==0); // wait untill response data "sent" or "failed"
}
String  SETLEDS(int long pulse) {
 pulse= pulse << 4; // move numbers up to pin 4
String response2 = "" ;
   for ( int x = 13; x >3 ; x--)  { // Pins 13 down to 4
   if (pulse & (1 << x)) { // compare pulse with bit number of Digital output port
    digitalWrite(x,HIGH);
    response2 = response2 + "1";
    // Serial.print("1"); // just for testing
   }
   else {
    digitalWrite(x,LOW);
    response2 = response2 + "0";
   // Serial.print("0"); // just for testing
    }
    }
   // Serial.println(""); // just for testing
    return response2; // Return Binary string
 }
// Send Analouge data
void Send_inputs(){
 delay (1000);
 Msg = Sensor_Read(); // replace Msg with Analouge input string
       Msg = "Analoue Reads 0-7:"+ Msg + "\r";
       sendData(Msg);    // Send Analouge inputs + CR
}
 // Read all analouge inputs routine
String Sensor_Read(){
 String response3 = "" ;
 for (int y = 0; y < sensorPin; y++) { // read ALL analouge inputs
 String an = "A" + String(y,DEC);      // format for Pin numbers
int f = an.toInt(); // turn string into a Analouge Input pin number
response3 = response3 + String(analogRead(f),DEC); // add value to string
if (y < sensorPin-1){
response3 = response3 +",";    // add a comma if not last number
}
}
 return response3;            // return string of numbers to loop
}
[/code]

Using the TCP Client

Connect the computer to the WiFi board by selecting the SSID to connect to, and giving it the correct password. The computer should “connect” and the WiFi signal strength will increase, by coming out of low power mode.

Run the TCPclient program

PC Realterm Program setting Port

Select the Programmed TCIP address in the program, in this case 192.168.5.1.

Add the Port 80, there are different ways to do this depending on the program. In Realterm it is 192.168.5.1:80, on the Android TCP Client it is in a separate box.

The program can then connect to the Arduino program via TCPIP.

You can then send one of the four commands

TCIP Client responses from Arduino

HELLO, which just replies “Wifi says : Hello”

with a Carriage Return character on the end, so you can direct the Client to move on to the next line, to make it easier to see.

The command LEDON, does just that lighting the LED on Output 13 (which is the on board LED).

Only responding with “Wifi says : LEDON” when the command has been done.

The command LEDONNxxxx, puts out the Outputs which correspond with the Digital Outputs from 3 to 13. This gives 10 outputs to control devices.

Digital Outputs 0 &1 are used by the USB to program the Arduino.

Digital Outputs 2 & 3 are used to connect the ESP-01.

Only responding with “Wifi says : LEDON and the Binary equivalent such as 0000000001 (for command LEDONN0001) when the command has been done.

The command LEDOFF, puts out the Outputs by making them LOW.

Only responding with “Wifi says : LEDOFF” when the command has been done.

The full program also returns all 8 Analogue input values in a string after the words "Analogue Reads 0-7:". The inputs are separated by commas so a program can sort them out and use them. Some Arduino boards can only do 6 inputs.

The LED's are turned OFF at the start of the program, so this is the default.

Feel free to change the SSID, password, IP address, port and LED used to suit your use.

You can add other commands, but it might slow down the response time.

With the serial.print entries enabled it slowed to 25 seconds from 5 seconds!

Code

ESP-01 and UNO Webserver Remote ControlArduino
Control your Arduino board via WiFi and get a feedback
[code]
// You may use on board LED connected to pin 13
// Elminated delays and serial monitor commands, reduced response time to 5 seconds.
#include <SoftwareSerial.h>

int serialRx = 2;   // software serial  RX  TX 
int serialTx = 3;   // ESP-01 RX goes to this port, TX goes to Port 2
int d = 0;
// ESP-01 CH_PD pin 7 Must go to 3.3v, not +5v to enable operation as UART (AP)
// UNO R3 has enough power to make it work.
// No other connections required
String inMsg ;     // variable to collect strings
int sensorPin = 8;    // set maximum number of pins for the Analouge inputs
int LEDPin = 13 ;  // variable to assign pin to LED.
int responseTime = 10; //communication timeout
SoftwareSerial portOne(serialRx, serialTx); // communications port to ESP-01
 String Msg = ""; // to collect Analouge input data 
void setup() {

// Serial.begin(19200); // for debugging only

String  msg =""  ; 
  portOne.begin(115200);                // Start software serial port
  delay(200);

  sendToWifi("ATE0",100);                           // set Echo Off. Otherwise echo was ON.
  sendToWifi("AT+CWMODE=2",responseTime); // configure as access point on Chinese version
  // sendToWifi("AT+CWMODE_CUR = 2",responseTime); // configure as access point (AP)
  sendToWifi("AT+CIPMUX=1",responseTime); // configure for multiple connections
  // AT+CIPAP=<ip>[,<gateway>,<netmask>]
  sendToWifi("AT+CIPAP_CUR=\"192.168.5.1\"",responseTime); // Set IP address for AP
  sendToWifi("AT+CIPSERVER=1,80",responseTime); // Create and turn on server on port 80
  sendToWifi("AT+CWDHCP_CUR=0,1",responseTime); // Set AP with DHCP ON (required)
  //AT+CWSAP=<ssid>,<pwd>,<chl>,<ecn>[,<max conn>][,<ssid hidden>]
  // Open AP Port
  sendToWifi("AT+CWSAP=\"ESP8266\",\"1234567890\",5,3,1,0",responseTime); // Set Soft AP parameters problems sending " characters
  sendToWifi("AT+CIPAP_CUR?",responseTime);
  sendToWifi("AT+CIPSTO=600",responseTime); // Set timeout to 10 minutes
  pinMode(LEDPin,OUTPUT); // Open Port to operate LED on board
//   //serial.println("Setup is done!");
  // delay(2000);
}

void loop() {
   //Serial.println("Waiting....");
  if(portOne.available()>0){
    inMsg = readFromWifi();
    //serial.print("Received msg inside loop = ");
    inMsg.toUpperCase();
   // Serial.println(inMsg);
    // Messages in CAPITALS
    if (inMsg.endsWith("HELLO") ) {
    // Serial.println ("Wifi says : Hello");
        sendData("Wifi says : Hello\r");    // Send confirmation of Command + CR
        Send_inputs();
  }
    else if (inMsg.endsWith("LEDON") ){
          digitalWrite(LEDPin,HIGH);       // If just LEDON turn on Pin 13
          sendData("Wifi says : LEDON\r");        // Send confirmation of Command + CR
          Send_inputs(); // Send Analouge inputs
    }
   else if (inMsg.endsWith("LEDOFF") ){  
       String     msg = SETLEDS(0) ; // set all LEDs off.
        sendData("Wifi says : LEDOFF\r");   // Send confirmation of Command + CR  
        Send_inputs(); // Send Analouge inputs     
    }   
    else if (inMsg.indexOf("LEDONN",0)>6 ){  // if Command is to set a Number
         d = inMsg.indexOf("LEDONN",0)+6; // Set d to next letter after command // string starts with zero
     int a = 0; // zero collected number
     int dt = inMsg.length(); // find end of string (CR)
    if ( d+3 < dt){              // if there is a 4 digit number after command
            a = inMsg.substring(d, d+4).toInt(); // store 4 digits in number a
      String    msg ="ERROR";
            if ((a > 0) & (a < 1024) ) {  // Command not used for zero (use LEDOFF), avoids no number available
             msg = SETLEDS(a) ; // set all LEDs on or off, returns Binary string as confirmation
             }
             msg = "Wifi says : LEDONN="+msg+"\r";
            sendData(msg ); // Send confirmation of Command + CR
             Send_inputs();  // Send Analouge inputs
             }
   }
   // delay(9000);                              // deliberately large delay to help collect dump of serial port.
}
     inMsg="";  // Clear buffer
    delay(800); // delay to stop duplicate messages
}
void sendToWifi(String command, const int timeout){
// only send command, not intereted in response
  String response = "";
  // Serial.print("Sent command to ESP8266-E12: ");
   // Serial.print(command);
  delay(50);
  portOne.println(command); 
  long int time = millis();
  while( (time+timeout) > millis())
  {
    while(portOne.available())
    { 
      char c = portOne.read(); 
      response+=c;
    }  
  }

   // Serial.print("Response from ESP8266-E12: ");
   // Serial.print(response);
}

String  readFromWifi(){
  char arrayInMsg[100];
  String tempStr; 
  int count =0;
  while( portOne.available() > 0 ){
  
    arrayInMsg[count]= portOne.read();
    delay(80);
    // get out if you see CR or LF
    if ((arrayInMsg[count]=='\n') or (arrayInMsg[count]=='\r')) break; 
    // changed character array comparison or it causes errors
    count++;       
  }
  arrayInMsg[count] = '\0';                     // Null terminate finally
  tempStr = String (arrayInMsg);                // cast it to string
  tempStr.trim();                               // precaution
  // Serial.print(tempStr);
  return tempStr;
}
/*
* Name: sendData
* Description: Function used to send string to tcp client using cipsend
* Params: 
* Returns: void
*/
 void sendData(String str){
  String len="";
  len+=str.length();
  sendToWifi("AT+CIPSEND=0,"+len,responseTime); // Setup command to send str data length to channel 0
  delay(100);
  sendToWifi(str,responseTime);//Send String str with 0 closing the transmission and return to AT mode
   delay(100);
  do {
  delay(100);
  } while (portOne.available()==0); // wait untill response data "sent" or "failed"
}

String  SETLEDS(int long pulse) {
  pulse= pulse << 4; // move numbers up to pin 4
 String response2 = "" ;
    for ( int x = 13; x >3 ; x--)  { // Pins 13 down to 4
    if (pulse & (1 << x)) { // compare pulse with bit number of Digital output port
     digitalWrite(x,HIGH);
     response2 = response2 + "1";
     // Serial.print("1"); // just for testing
    }
    else {
     digitalWrite(x,LOW);
     response2 = response2 + "0";
    // Serial.print("0"); // just for testing
     }
     }
    // Serial.println(""); // just for testing
     return response2; // Return Binary string
  }
// Send Analouge data
void Send_inputs(){
  delay (1000);
  Msg = Sensor_Read(); // replace Msg with Analouge input string
        Msg = "Analoue Reads 0-7:"+ Msg + "\r";
        sendData(Msg);    // Send Analouge inputs + CR
}
  // Read all analouge inputs routine
String Sensor_Read(){
  String response3 = "" ;
  for (int y = 0; y < sensorPin; y++) { // read ALL analouge inputs
  String an = "A" + String(y,DEC);      // format for Pin numbers
 int f = an.toInt(); // turn string into a Analouge Input pin number
 response3 = response3 + String(analogRead(f),DEC); // add value to string
 if (y < sensorPin-1){
 response3 = response3 +",";    // add a comma if not last number
 }
 }
  return response3;            // return string of numbers to loop
}
[/code]

Schematics

1K resistor complusory
Use instead of 220 ohms colours shown in Fritzog.
1kr icon wjvnp5y9t0

Comments

Similar projects you might like

Simple UNO calculator

Project tutorial by Joprp05

  • 6,855 views
  • 1 comment
  • 4 respects

Control Arduino Uno Using ESP8266 WiFi Module and Blynk App

Project tutorial by Adithya TG

  • 5,858 views
  • 10 comments
  • 21 respects

Control an LED with the Remote Control

Project showcase by Nicholas_N

  • 3,192 views
  • 2 comments
  • 9 respects

Embedis: Project Keystore Library

by Team thingSoC

  • 1,733 views
  • 1 comment
  • 8 respects

ESP8266 ESP-01 Webserver

by Robin

  • 101,593 views
  • 19 comments
  • 139 respects
Add projectSign up / Login