Connect Two ESP8266 Devices Over WiFi Without Using a Router

Disclosure: Some of the links on this site are affiliate links. This means that, at zero cost to you, I will earn an affiliate commission if you click through the link and finalize a purchase.

How To Connect Two ESP8266 Devices Over WiFi Without a Router

Are you interested in learning how to establish a fast and effortless connection between two ESP8266 devices using Arduino?

This article presents a straightforward, step-by-step solution for connecting two ESP8266 devices, which doesn’t require a router! To ensure a quick setup, we will utilize UDP due to its simplicity.

In this article you will learn how to make both host and client projects for ESP8266 using the Arduino IDE.

The example projects are designed to communicate with each other, demonstrating a simple data transfer over WiFi without the need for a router.

How do I make two ESP8266 “talk?”

To enable communication between two ESP8266 devices, there are two essential steps we need to follow:

  • Make a physical connection between the ESP8266 devices – we can either connect the devices physically using wires, or by means of a wireless transceiver.
  • Ensure the devices are “speaking the same language” – both devices should be configured to use the same protocol, which is a set of rules the devices follow in order to understand one another.

In this article we will be linking the devices wirelessly using the ESP8266 onboard WiFi capability. The protocol or “language” that we will use will be UDP.

UDP (User Datagram Protocol) is a communication protocol that allows devices to exchange data over a network. Think of UDP as a way for the devices to send short messages (packets) back and forth without establishing a dedicated connection.

It’s like passing notes between two people without having a continuous conversation.

To establish UDP communication between the ESP8266 devices, both the host and client projects will perform the following steps:

  1. Assign roles: Decide which device will act as the “server” and which will be the “client.” The server waits for messages, and the client sends messages to the server.
  2. Set up the devices: Make sure both ESP8266 devices are connected to the same Wi-Fi network. They need to be on the same “channel” to communicate with each other.
  3. Host setup: The host device prepares itself to receive messages. It opens a “listening” port, which is like having an open mailbox to receive incoming messages. It waits for messages to arrive.
  4. Client setup: The client device prepares to send messages to the server. It knows the server’s address (like an IP address) and the port number it needs to send messages to.
  5. Message exchange: The client creates a message (packet) and sends it to the server’s address and port number. The server receives the message and processes it. They can keep exchanging messages in this way.

Prerequisite

You will need to have the Arduino IDE installed and configured to flash ESP devices. You will also need two ESP8266-based boards such as the Wemos D1 Mini, which are surprisingly cheap on Amazon, click here to check the prices.

If you are new to ESP8266 and Arduino, there are a couple of useful articles that you can check out first as a primer:

Sending UDP Data Over WiFi With ESP8266

We will create a host and client application to run on each of the ESP8266 devices. The host 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.

In this example we will create a simple application that can read a digital pin on the client ESP8266 and send the state over UDP to the host ESP8266.

To visually indicate the state of the client pin, the host will illuminate its onboard LED based on the corresponding state of the pin on the client device.

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!

ESP8266 UDP Host Example

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

Adding the ESP8266 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 (AP) 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.

We will define the constant AD_SSID, which will contain the name of our ESP8266 router.

We will define the constant AP_PASS, which will contain the password required for accessing our ESP8266 router.

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

Configure UDP Parameters

To establish the connection, we’ll assign the host’s IP address as “local_ip” for later use in the client application. While it’s not mandatory to specify the IP address, ensure that your client application connects to the host’s IP address as needed.

The gateway should match the local IP address, and the subnet mask should remain as specified here. Additionally, we’ll define a port for UDP communication. Feel free to modify this value if you prefer to use a different port.

We’ll create a buffer called “packetBuffer” to store received UDP packets. This buffer will serve as a designated memory area where incoming packets from the client application can be stored.

// 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 the LED

Since we’ll receive a UDP packet and utilize the first byte’s content to determine the LED’s state, it’s crucial to designate the physical LED pin as an output.

In my setup with a pair of Wemos D1 Mini ESP boards, I use Arduino pin 2 to control the onboard LED (despite its label as D4). If you’re using a different board, please adjust this configuration accordingly.

void setup() {

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

Setup the 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.

  // Setup serial port
  Serial.begin(115200);
  Serial.println();

Begin the 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.

  // 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 the 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.

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

This is the end of the setup function, so don’t forget to close it with a } curly brace.

Handle receiving UDP packets

With the setup function complete, it’s time to construct the main program loop function, where we will handle any incoming data packets.

Finally, we must address the handling of a packet received from the client application, which is then read and stored in the packetBuffer.

Since the client application places the button state in the first byte of the buffer, we can determine the LED’s state by examining the first byte of the buffer, denoted as packetBuffer[0].

void loop() {

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

} 

Completed ESP8266 Host Code

You should now have the following code in your host project:

#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);
  }      

} 

ESP8266 UDP Client Example

Once the host application is complete, we can proceed to develop the client application for the second ESP board. Let’s begin by creating a new sketch specifically for the client application.

Adding the ESP8266 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 your WiFi credentials

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

// Set WiFi credentials
#define WIFI_SSID "TheOtherESP"
#define WIFI_PASS "flashmeifyoucan"

Configure UDP Parameters

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

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

Setup the 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.

void setup() {

  // Setup IO
  pinMode(2, INPUT);

Setup the 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.

  // Setup serial port
  Serial.begin(115200);
  Serial.println();

Connect to WiFi

We will connect to the ESP device running the host 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.

  // 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 the UDP port

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

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

We are now at the end of the setup function, don’t forget to close it with a } curly brace.

Read the 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.

void loop() {

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

Send UDP data packet

Finally we can send the state of the button to the host. 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.

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

Completed ESP8266 Client Code

You should now have the following code in your client project:

#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

Throughout this article, we have explored the client and host applications necessary to establish communication between two ESP devices using the Arduino core.

While this example is straightforward, it serves as a foundation for further expansion of 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!

Article Updates

July 5th 2023 : Code checked, minor formatting updates and improvements to explanations, featured image updated and content expanded to cover some frequently asked questions.

Article first published March 30th 2020.

Thanks so much for visiting my site! If this article helped you achieve your goal and you want to say thanks, you can now support my work by buying me a coffee. I promise I won't spend it on beer instead... 😏

2 thoughts on “How To Connect Two ESP8266 Devices Over WiFi Without a Router”

  1. Dear,
    Congratulations on your excellent work and contribution. Your post was very didactic and will help us a lot.
    I ask if you have any post with server and client with LoRa radio? If not, you could tell me where I can get it.
    I am developing a work to receive signal from a DS18B20 temperature sensor installed at 1000m distance of my house. That’s why I need to use LoRa radio.
    Thank you.
    Carlos Mota

  2. Unbelievably helpful!! I have spent way too many hours trying to get other existing examples to compile. They all return cryptic errors when compiling and the authors haven’t addressed any of them. You have provided a simple explanation and example for a very simple task without cluttering it up with complicated and unnecessary libraries! Kudos and huge thanks!

Leave a Comment

Your email address will not be published. Required fields are marked *


Scroll to Top