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 HardwareAs 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 SoftwareYou 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 ClientConnect 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!
Comments