ESP8266 Client-Server Wi-Fi Communication Between Two Boards (NodeMCU)

Learn how to establish a Wi-Fi communication (HTTP) between two ESP8266 NodeMCU boards to exchange data without the need to connect to the internet (you don’t need a router).

You’re going to set one ESP8266 as an Access Point (Server) and another ESP8266 as a Station (Client). Then, the server and the client will exchange data (sensor readings) via HTTP requests. We’ll program the ESP8266 boards using Arduino IDE.

ESP8266 Client-Server Wi-Fi Communication Between Two Boards

In this example, we’ll send BME280 sensor readings from one board to the other. The receiver will display the readings on an OLED display.

If you have an ESP32 board, you can read this dedicated guide: ESP32 Client-Server Wi-Fi Communication.

// video

Project Overview

To better understand how everything works, take a look at the following diagram.

ESP8266 Client-Server Wi-Fi Communication Between Project overview
  • The ESP8266 server creates its own wireless network (ESP8266 Soft-Access Point). So, other Wi-Fi devices can connect to that network (SSID: ESP8266-Access-Point, Password: 123456789).
  • The ESP8266 client is set as a station. So, it can connect to the ESP8266 server wireless network.
  • The client can make HTTP GET requests to the server to request sensor data or any other information. It just needs to use the IP address of the server to make a request on a certain route: /temperature, /humidity or /pressure.
  • The server listens for incoming requests and sends an appropriate response with the readings.
  • The client receives the readings and displays them on the OLED display.

As an example, the ESP8266 client requests temperature, humidity and pressure to the server by making requests on the server IP address followed by /temperature, /humidity and /pressure, respectively (HTTP GET).

The ESP8266 server is listening on those routes and when a request is made, it sends the corresponding sensor readings via HTTP response.

Parts Required

Parts required for ESP8266 Client-Server Communication

For this tutorial, you need the following parts:

  • 2x ESP8266 Development boards.
  • BME280 sensor.
  • I2C SSD1306 OLED display.
  • Jumper Wires.
  • Breaboard.

Installing Libraries

For this tutorial you need to install the following libraries:

Asynchronous Web Server Libraries

We’ll use the following libraries to handle HTTP request:

These libraries are not available to install through the Library Manager. So, you need to unzip the libraries and move them to the Arduino IDE installation libraries folder.

Alternatively, you can go to Sketch Include Library > Add .ZIP library… and select the libraries you’ve just downloaded.

BME280 Libraries

The following libraries can be installed through the Arduino Library Manager. Go to Sketch Include LibraryManage Libraries and search for the library name.

I2C SSD1306 OLED Libraries

To interface with the OLED display you need the following libraries. These can be installed through the Arduino Library Manager. Go to Sketch Include LibraryManage Libraries and search for the library name.

#1 ESP8266 Server (Access Point)

ESP8266 Server with BME280 temperature humidity pressure

The ESP8266 server is an Access Point (AP), that listens for requests on the /temperature, /humidity and /pressure URLs. When it gets requests on those URLs, it sends the latest BME280 sensor readings.

For testing, we’re using a BME280 sensor, but you can use any other sensor by modifying a few lines of code (for example: DHT11/DHT22 or DS18B20).

Schematic Diagram

Wire the ESP8266 to the BME280 sensor as shown in the following schematic diagram.

ESP8266 BME280 Wiring Schematic Diagram
BME280ESP8266
VIN/VCC3.3V
GNDGND
SCLGPIO 5 (D1)
SDAGPIO 4 (D2)

Arduino Sketch for #1 ESP8266 Server

Upload the following code to your board.

/*
  Welcome to GND_TO_VCC!!
*/

// Import required libraries
#include <ESP8266WiFi.h>
#include "ESPAsyncWebServer.h"

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

// Set your access point network credentials
const char* ssid = "ESP8266-Access-Point";
const char* password = "123456789";

/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

String readTemp() {
  return String(bme.readTemperature());
  //return String(1.8 * bme.readTemperature() + 32);
}

String readHumi() {
  return String(bme.readHumidity());
}

String readPres() {
  return String(bme.readPressure() / 100.0F);
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);
  Serial.println();
  
  // Setting the ESP as an access point
  Serial.print("Setting AP (Access Point)…");
  // Remove the password parameter, if you want the AP (Access Point) to be open
  WiFi.softAP(ssid, password);

  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);

  server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readTemp().c_str());
  });
  server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readHumi().c_str());
  });
  server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readPres().c_str());
  });
  
  bool status;

  // default settings
  // (you can also pass in a Wire library object like &Wire2)
  status = bme.begin(0x76);  
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
  
  // Start server
  server.begin();
}
 
void loop(){
  
}

Testing the ESP8266 Server

Upload the code to your board and open the Serial Monitor. You should get something as follows:

Testing the ESP8266 Server Serial Monitor Arduino IDE

This means that the access point was set successfully.

Now, to make sure it is listening for temperature, humidity and pressure requests, you need to connect to its network.

In your smartphone, go to the Wi-Fi settings and connect to the ESP8266-Access-Point. The password is 123456789.

ESP8266 Server Access Point AP Connection

While connected to the access point, open your browser and type 192.168.4.1/temperature

You should get the temperature value in your browser:

ESP8266 Server Access Point AP Test request temperature

Try this URL path for the humidity 192.168.4.1/humidity:

ESP8266 Server Access Point AP Test request humidity

Finally, go to 192.168.4.1/pressure URL:

ESP8266 Server Access Point AP Test request pressure

If you’re getting valid readings, it means that everything is working properly. Now, you need to prepare the other ESP8266 board (client) to make those requests for you and display them on the OLED display.

#2 ESP8266 Client (Station)

ESP8266 Client Receive Readings via HTTP GET Request BME280

The ESP8266 Client is a Wi-Fi station that connects to the ESP8266 Server. The client requests the temperature, humidity and pressure from the server by making HTTP GET requests on the /temperature, /humidity, and /pressure URL routes. Then, it displays the readings on the OLED display.

Schematic Diagram

Connect an OLED display to your ESP8266 board as shown in the following schematic diagram.

ESP32 OLED Display Wiring Schematic Diagram

I

PinESP8266
Vin3.3V
GNDGND
SCLGPIO 5 (D1)
SDAGPIO 4 (D2)

Arduino Sketch for #2 ESP8266 Client

Upload the following code to the other ESP8266 (the client):

*/
Welcome to GNd_TO_VCC!!
*/

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>

#include <ESP8266WiFiMulti.h>
ESP8266WiFiMulti WiFiMulti;

const char* ssid = "ESP8266-Access-Point";
const char* password = "123456789";

//Your IP address or domain name with URL path
const char* serverNameTemp = "http://192.168.4.1/temperature";
const char* serverNameHumi = "http://192.168.4.1/humidity";
const char* serverNamePres = "http://192.168.4.1/pressure";

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

String temperature;
String humidity;
String pressure;

unsigned long previousMillis = 0;
const long interval = 5000; 

void setup() {
  Serial.begin(115200);
  Serial.println();
  
  // Address 0x3C for 128x64, you might need to change this value (use an I2C scanner)
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  display.clearDisplay();
  display.setTextColor(WHITE);
 
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP(ssid, password);
  while((WiFiMulti.run() == WL_CONNECTED)) { 
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("Connected to WiFi");
}

void loop() {
  unsigned long currentMillis = millis();
  
  if(currentMillis - previousMillis >= interval) {
     // Check WiFi connection status
    if ((WiFiMulti.run() == WL_CONNECTED)) {
      temperature = httpGETRequest(serverNameTemp);
      humidity = httpGETRequest(serverNameHumi);
      pressure = httpGETRequest(serverNamePres);
      Serial.println("Temperature: " + temperature + " *C - Humidity: " + humidity + " % - Pressure: " + pressure + " hPa");
      
      display.clearDisplay();
      
      // display temperature
      display.setTextSize(2);
      display.setCursor(0,0);
      display.print("T: ");
      display.print(temperature);
      display.print(" ");
      display.setTextSize(1);
      display.cp437(true);
      display.write(248);
      display.setTextSize(2);
      display.print("C");
      
      // display humidity
      display.setTextSize(2);
      display.setCursor(0, 25);
      display.print("H: ");
      display.print(humidity);
      display.print(" %"); 
      
      // display pressure
      display.setTextSize(2);
      display.setCursor(0, 50);
      display.print("P:");
      display.print(pressure);
      display.setTextSize(1);
      display.setCursor(110, 56);
      display.print("hPa");
           
      display.display();
      
      // save the last HTTP GET Request
      previousMillis = currentMillis;
    }
    else {
      Serial.println("WiFi Disconnected");
    }
  }
}

String httpGETRequest(const char* serverName) {
  WiFiClient client;
  HTTPClient http;
    
  // Your IP address with path or Domain name with URL path 
  http.begin(client, serverName);
  
  // Send HTTP POST request
  int httpResponseCode = http.GET();
  
  String payload = "--"; 
  
  if (httpResponseCode>0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    payload = http.getString();
  }
  else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  // Free resources
  http.end();

  return payload;
}

Testing the ESP8266 Client

Having both boards fairly close and powered, you’ll see that ESP #2 is receiving new temperature, humidity and pressure readings every 5 seconds from ESP #1.

This is what you should see on the ESP8266 Client Serial Monitor.

Testing the ESP8266 Client Serial Monitor Arduino IDE

The sensor readings are also displayed in the OLED.

ESP8266 Client Server Communication example data exchange for sensor readings

That’s it! Your two ESP8266 boards are talking with each other.

Published by Gnd_To_Vcc

Here to spread my knowledge . Knowledge should always be spread not stored.

One thought on “ESP8266 Client-Server Wi-Fi Communication Between Two Boards (NodeMCU)

  1. I have a exception 9 when use your code, when i call the pressure function.

    Exception 9: LoadStoreAlignmentCause: Load or store to an unaligned address
    PC: 0x401053f5
    EXCVADDR: 0xffffffff

    Decoding stack results
    0x40100cfb: free(void*) at C:\Users\Pasquale\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\umm_malloc\umm_malloc.cpp line 398
    0x40214a85: ethernet_input_LWIP2 at netif/ethernet.c line 188

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create your website with WordPress.com
Get started
%d bloggers like this: