Arduino

How To Setup Communication Between Two ESP8266 Using Arduino

Are you wanting to learn how to quickly and easily link two ESP8266 modules using Arduino? This article provides an easy step-by-step solution and you don’t even need a router!

In order to get you up and running quickly, we shall be using UDP due to its simplicity. Both client and server examples will be given in this tutorial, simplified in order to help you understand how to implement them in your own application.

Prerequisite

You will need to have the Arduino IDE installed and configured to flash ESP devices. You will also need two ESP-based boards such as the Wemos D1 Mini.

I would recommend that you first follow my tutorials on how to configure the Arduino IDE for ESP devices and how to send and receive data using UDP on ESP devices in order to gain some basic understanding if you are new to ESP devices and Arduino.

Sending data with UDP

We will create a client and server application to run on each of the ESP devices. The server will act as a WiFi access point and the client will connect to this access point.

Once a connection has been established it will be possible to send UDP data packets back and forth between the two ESP devices. For this example we will read a digital pin on the client and send the state over UDP to the server. The server will then operate the onboard LED depending on the state of the pin on the client.

This example is similar to the “button” sketch (see examples > digital > button from the file menu in the Arduino IDE), however we are connecting the button to the LED over WiFi. Awesome!

Server

First we need to create a new sketch in Arduino for the server. Once complete we can go ahead and load this onto the ESP device that we want to function as the server.

Add the libraries

First we need to include the ESP8266WiFi and WiFiUdp libraries. If you have not yet installed the libraries or setup the Arduino IDE for ESP devices, go ahead and check out my tutorial on how to configure the Arduino IDE for ESP devices.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

Set access point credentials

Next we need to define the WiFi credentials for the access point. Feel free to specify your own credentials here but make a note of them as we will need them when writing the client application.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

// Set AP credentials
#define AP_SSID "TheOtherESP"
#define AP_PASS "flashmeifyoucan"

Configure UDP

We will specify the IP address of the server as local_ip so that we can use it when writing the client application. It is not essential that you specify the IP address but you will need to ensure that the client is connecting to the server IP address in your own application.

The gateway should match the local IP address and the subnet mask should be left set as specified here. We also need to define a port used for UDP communication, you can change this value if you prefer to use a different port.

We will also create a buffer for received UDP packets called packetBuffer. This is a defined area in memory where we can hold the received packets when they arrive from the client application.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

// Set AP credentials
#define AP_SSID "TheOtherESP"
#define AP_PASS "flashmeifyoucan"

// UDP
WiFiUDP UDP;
IPAddress local_IP(192,168,4,1);
IPAddress gateway(192,168,4,1);
IPAddress subnet(255,255,255,0);
#define UDP_PORT 4210

// UDP Buffer
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];

Setup LED

As we will be receiving a UDP packet and using the contents of the first byte to set the state of the LED, we must define the physical LED pin as an output.

I am using a pair of Wemos D1 Mini ESP boards which use Arduino pin 2 to control the onboard LED (even though the pin is labelled as D4). You should change this to suit your device if you are using a different board.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

// Set AP credentials
#define AP_SSID "TheOtherESP"
#define AP_PASS "flashmeifyoucan"

// UDP
WiFiUDP UDP;
IPAddress local_IP(192,168,4,1);
IPAddress gateway(192,168,4,1);
IPAddress subnet(255,255,255,0);
#define UDP_PORT 4210

// UDP Buffer
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];

void setup() {

  // Setup LED pin
  pinMode(2, OUTPUT);

Setup serial port

Next we will setup the serial port in order to receive information in the serial console. This is not essential for this project but it can be useful for debugging.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

// Set AP credentials
#define AP_SSID "TheOtherESP"
#define AP_PASS "flashmeifyoucan"

// UDP
WiFiUDP UDP;
IPAddress local_IP(192,168,4,1);
IPAddress gateway(192,168,4,1);
IPAddress subnet(255,255,255,0);
#define UDP_PORT 4210

// UDP Buffer
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];

void setup() {

  // Setup LED pin
  pinMode(2, OUTPUT);
  
  // Setup serial port
  Serial.begin(115200);
  Serial.println();

Begin access point

Now we can begin the access point using the setup that we have defined. For more information on this code see my tutorial on how to configure the Arduino IDE for ESP devices.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

// Set AP credentials
#define AP_SSID "TheOtherESP"
#define AP_PASS "flashmeifyoucan"

// UDP
WiFiUDP UDP;
IPAddress local_IP(192,168,4,1);
IPAddress gateway(192,168,4,1);
IPAddress subnet(255,255,255,0);
#define UDP_PORT 4210

// UDP Buffer
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];

void setup() {

  // Setup LED pin
  pinMode(2, OUTPUT);
  
  // Setup serial port
  Serial.begin(115200);
  Serial.println();

  // Begin Access Point
  Serial.println("Starting access point...");
  WiFi.softAPConfig(local_IP, gateway, subnet);
  WiFi.softAP(AP_SSID, AP_PASS);
  Serial.println(WiFi.localIP());

Begin listening to UDP port

We also need to begin listening to the specified UDP port. The serial console commands are simply for debugging, so that we can see the device has successfully started listening to the port.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

// Set AP credentials
#define AP_SSID "TheOtherESP"
#define AP_PASS "flashmeifyoucan"

// UDP
WiFiUDP UDP;
IPAddress local_IP(192,168,4,1);
IPAddress gateway(192,168,4,1);
IPAddress subnet(255,255,255,0);
#define UDP_PORT 4210

// UDP Buffer
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];

void setup() {

  // Setup LED pin
  pinMode(2, OUTPUT);
  
  // Setup serial port
  Serial.begin(115200);
  Serial.println();

  // Begin Access Point
  Serial.println("Starting access point...");
  WiFi.softAPConfig(local_IP, gateway, subnet);
  WiFi.softAP(AP_SSID, AP_PASS);
  Serial.println(WiFi.localIP());

  // Begin listening to UDP port
  UDP.begin(UDP_PORT);
  Serial.print("Listening on UDP port ");
  Serial.println(UDP_PORT);

Handle receive packet

The last thing we need to do is handle a packet received from the client application. The packet is read and placed in the packetBuffer. The client application will put the button state into the first byte of the buffer, therefore we can set the state of the LED based upon the first byte of the buffer, packetBuffer[0].

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

// Set AP credentials
#define AP_SSID "TheOtherESP"
#define AP_PASS "flashmeifyoucan"

// UDP
WiFiUDP UDP;
IPAddress local_IP(192,168,4,1);
IPAddress gateway(192,168,4,1);
IPAddress subnet(255,255,255,0);
#define UDP_PORT 4210

// UDP Buffer
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];

void setup() {

  // Setup LED pin
  pinMode(2, OUTPUT);
  
  // Setup serial port
  Serial.begin(115200);
  Serial.println();

  // Begin Access Point
  Serial.println("Starting access point...");
  WiFi.softAPConfig(local_IP, gateway, subnet);
  WiFi.softAP(AP_SSID, AP_PASS);
  Serial.println(WiFi.localIP());

  // Begin listening to UDP port
  UDP.begin(UDP_PORT);
  Serial.print("Listening on UDP port ");
  Serial.println(UDP_PORT);

}

void loop() {

  // Receive packet
  UDP.parsePacket();
  UDP.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
  if (packetBuffer[0]){
    digitalWrite(2, HIGH);
  } else {
    digitalWrite(2, LOW);
  }      

} 

Client

Now we have completed the server application, we can create a client application for a second ESP board. Go ahead and create a new sketch for the client application.

Add the libraries

First we need to include the ESP8266WiFi and WiFiUdp libraries. If you have not yet installed the libraries or setup the Arduino IDE for ESP devices, go ahead and check out my tutorial on how to configure the Arduino IDE for ESP devices.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

Set WiFi credentials

Next we need to set the WiFi network credentials. As we are connecting directly to the access point setup in our server application, we need to specify the same SSID and password that we used for the server.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
 
// Set WiFi credentials
#define WIFI_SSID "TheOtherESP"
#define WIFI_PASS "flashmeifyoucan"

Configure UDP

We will specify the remote_IP address as the same address that we gave to the server, as this is where we wish to send our packets of data. We also need to specify the same port.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
 
// Set WiFi credentials
#define WIFI_SSID "TheOtherESP"
#define WIFI_PASS "flashmeifyoucan"

// UDP
WiFiUDP UDP;
IPAddress remote_IP(192,168,4,1);
#define UDP_PORT 4210

Setup input pin

As we will be connecting a button to this ESP device to control the LED on the other ESP device, we need to define the pin connected to the button as an input pin. I am using pin 2 for the button but you can choose any pin you like.

If you don’t have a button handy you can just connect a wire between the pin and GND. When the pin is connected to GND the state of the pin will be low and with the wire removed the state of the pin will be high.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
 
// Set WiFi credentials
#define WIFI_SSID "TheOtherESP"
#define WIFI_PASS "flashmeifyoucan"

// UDP
WiFiUDP UDP;
IPAddress remote_IP(192,168,4,1);
#define UDP_PORT 4210

void setup() {

  // Setup IO
  pinMode(2, INPUT);

Setup serial port

Next we will setup the serial port in order to receive information in the serial console. This is not essential for this project but it can be useful for debugging.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
 
// Set WiFi credentials
#define WIFI_SSID "TheOtherESP"
#define WIFI_PASS "flashmeifyoucan"

// UDP
WiFiUDP UDP;
IPAddress remote_IP(192,168,4,1);
#define UDP_PORT 4210

void setup() {

  // Setup IO
  pinMode(2, INPUT);
  
  // Setup serial port
  Serial.begin(115200);
  Serial.println();

Connect to WiFi

We will connect to the ESP device running the server application using the basic WiFi connection code. If you want a more detailed explanation on how this works, go check out check out the WiFi section of this tutorial.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
 
// Set WiFi credentials
#define WIFI_SSID "TheOtherESP"
#define WIFI_PASS "flashmeifyoucan"

// UDP
WiFiUDP UDP;
IPAddress remote_IP(192,168,4,1);
#define UDP_PORT 4210

void setup() {

  // Setup IO
  pinMode(2, INPUT);
  
  // Setup serial port
  Serial.begin(115200);
  Serial.println();
 
  // Begin WiFi
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  WiFi.mode(WIFI_STA);
 
  // Connecting to WiFi...
  Serial.print("Connecting to ");
  Serial.print(WIFI_SSID);
  // Loop continuously while WiFi is not connected
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(100);
    Serial.print(".");
  }
 
  // Connected to WiFi
  Serial.println();
  Serial.print("Connected! IP address: ");
  Serial.println(WiFi.localIP());

Open UDP port

We also need to open the specified UDP port to make a connection with the server. The serial console commands are simply for debugging, so that we can see the device has successfully opened the port.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
 
// Set WiFi credentials
#define WIFI_SSID "TheOtherESP"
#define WIFI_PASS "flashmeifyoucan"

// UDP
WiFiUDP UDP;
IPAddress remote_IP(192,168,4,1);
#define UDP_PORT 4210

void setup() {

  // Setup IO
  pinMode(2, INPUT);
  
  // Setup serial port
  Serial.begin(115200);
  Serial.println();
 
  // Begin WiFi
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  WiFi.mode(WIFI_STA);
 
  // Connecting to WiFi...
  Serial.print("Connecting to ");
  Serial.print(WIFI_SSID);
  // Loop continuously while WiFi is not connected
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(100);
    Serial.print(".");
  }
 
  // Connected to WiFi
  Serial.println();
  Serial.print("Connected! IP address: ");
  Serial.println(WiFi.localIP());

  // Begin UDP port
  UDP.begin(UDP_PORT);
  Serial.print("Opening UDP port ");
  Serial.println(UDP_PORT);

Read button

The first thing we need to do in our continuous loop is read the button connected to pin 2 and place the value into a variable.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
 
// Set WiFi credentials
#define WIFI_SSID "TheOtherESP"
#define WIFI_PASS "flashmeifyoucan"

// UDP
WiFiUDP UDP;
IPAddress remote_IP(192,168,4,1);
#define UDP_PORT 4210

void setup() {

  // Setup IO
  pinMode(2, INPUT);
  
  // Setup serial port
  Serial.begin(115200);
  Serial.println();
 
  // Begin WiFi
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  WiFi.mode(WIFI_STA);
 
  // Connecting to WiFi...
  Serial.print("Connecting to ");
  Serial.print(WIFI_SSID);
  // Loop continuously while WiFi is not connected
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(100);
    Serial.print(".");
  }
 
  // Connected to WiFi
  Serial.println();
  Serial.print("Connected! IP address: ");
  Serial.println(WiFi.localIP());

  // Begin UDP port
  UDP.begin(UDP_PORT);
  Serial.print("Opening UDP port ");
  Serial.println(UDP_PORT);
 
}
 
void loop() {

  // Read button
  char buttonState = digitalRead(2);

Send packet

Finally we can send the state of the button to the server. First we must begin a packet and specify the destination IP address and port. Then we can write our buttonState to the outgoing packet buffer before ending the packet.

We will also include a short delay so that the packets to not fire too quickly. A more sophisticated version of this code would only transmit a packet when the button changes state, however I wanted to keep this example simple.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
 
// Set WiFi credentials
#define WIFI_SSID "TheOtherESP"
#define WIFI_PASS "flashmeifyoucan"

// UDP
WiFiUDP UDP;
IPAddress remote_IP(192,168,4,1);
#define UDP_PORT 4210

void setup() {

  // Setup IO
  pinMode(2, INPUT);
  
  // Setup serial port
  Serial.begin(115200);
  Serial.println();
 
  // Begin WiFi
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  WiFi.mode(WIFI_STA);
 
  // Connecting to WiFi...
  Serial.print("Connecting to ");
  Serial.print(WIFI_SSID);
  // Loop continuously while WiFi is not connected
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(100);
    Serial.print(".");
  }
 
  // Connected to WiFi
  Serial.println();
  Serial.print("Connected! IP address: ");
  Serial.println(WiFi.localIP());

  // Begin UDP port
  UDP.begin(UDP_PORT);
  Serial.print("Opening UDP port ");
  Serial.println(UDP_PORT);
 
}
 
void loop() {

  // Read button
  char buttonState = digitalRead(2);

  // Send Packet
  UDP.beginPacket(remote_IP, UDP_PORT);
  UDP.write(buttonState);
  UDP.endPacket();
  delay(100);
  
}

Conclusion

In this article we have looked at both the client and server application required for getting two ESP devices to communicate using the Arduino core. Although this is a simple example it would be easy to expand on the functionality.

Why not go ahead and check out some of my other tutorials for awesome ESP devices next, such as how to build a super-tiny web server!

back to top