ESP8266 NodeMCU Access Point (AP) for Web Server

In this tutorial, you’ll learn how to set your ESP8266 NodeMCU as an Access Point (AP) using Arduino IDE. This allows you to connect directly to your ESP8266 via Wi-Fi without a wireless router.

ESP8266 NodeMCU Access Point AP for Web Server

To set the ESP8266 as an Access Point use WiFi.softAP(ssid, password);

ESP8266 Station and Access Point

In most of our ESP8266 NodeMCU web server projects, we connect the ESP8266 to a wireless router. In this configuration, we can access the ESP8266 through the local network.

In this scenario, the router acts as an access point and the ESP8266 is set as a station. So, you need to be connected to your router (local network) to control the ESP8266.

ESP866 NodeMCU set as a Wi-Fi Station

In some cases, this might not be the best configuration (when you don’t have a router nearby). But if you set the ESP8266 as an access point (hotspot), you can be connected to the ESP8266 using any device with Wi-Fi capabilities without the need to connect to your router.

In simple words, when you set the ESP8266 as an access point you create its own Wi‑Fi network and nearby Wi-Fi devices (stations) can connect to it (like your smartphone or your computer).

ESP866 NodeMCU Set as an Access Point (AP) Mode

In this tutorial, we’ll show you how to set the ESP8266 as an access point in your web server projects. This way, you don’t need to be connected to a router to control your ESP8266.

Because the ESP8266 doesn’t connect further to a wired network (like your router), it is called soft-AP (soft Access Point).

This means that if you try to load libraries or use firmware from the internet, it will not work. It also doesn’t work if you try to make HTTP requests to services on the internet like publishing sensor readings to the cloud.

Installing the DHT Library for ESP8266

For this example, we’ll use a previous web server project that displays sensor readings from a DHT sensor.

Having the ESP8266 Board installed in Arduino IDE, to read from the DHT sensor, we’ll use the DHT library from Adafruit. To use this library you also need to install the Adafruit Unified Sensor library.

Follow the next steps to install those two libraries:

1. Open your Arduino IDE and go to Sketch Include Library > Manage Libraries. The Library Manager should open.

2. Search for “DHT” on the Search box and install the DHT library from Adafruit.

Installing Adafruit DHT library

3. After installing the DHT library from Adafruit, type “Adafruit Unified Sensor” in the search box. Scroll all the way down to find the library and install it.

Installing Adafruit Unified Sensor driver library

After installing the libraries, restart your Arduino IDE.

ESP8266 NodeMCU Access Point (AP)

In this example, we’ll modify the ESP8266 Web Server from a previous tutorial to add access point capabilities. Here’s the project example we’ll use: ESP8266 DHT11/DHT22 Temperature and Humidity Web Server with Arduino IDE.

What we’ll show you here can be used with any ESP8266 web server example.

Upload the sketch provided below to set the ESP8266 as an access point.

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com/esp8266-nodemcu-access-point-ap-web-server/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*********/

// Import required libraries
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Hash.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>

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

#define DHTPIN 5     // Digital pin connected to the DHT sensor

// Uncomment the type of sensor in use:
//#define DHTTYPE    DHT11     // DHT 11
#define DHTTYPE    DHT22     // DHT 22 (AM2302)
//#define DHTTYPE    DHT21     // DHT 21 (AM2301)

DHT dht(DHTPIN, DHTTYPE);

// current temperature & humidity, updated in loop()
float t = 0.0;
float h = 0.0;

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

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;    // will store last time DHT was updated

// Updates DHT readings every 10 seconds
const long interval = 10000;  

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 3.0rem; }
    .units { font-size: 1.2rem; }
    .dht-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
</head>
<body>
  <h2>ESP8266 DHT Server</h2>
  <p>
    <span class="dht-labels">Temperature</span> 
    <span id="temperature">%TEMPERATURE%</span>
    <sup class="units">&deg;C</sup>
  </p>
  <p>
    <span class="dht-labels">Humidity</span>
    <span id="humidity">%HUMIDITY%</span>
    <sup class="units">%</sup>
  </p>
</body>
<script>
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperature").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperature", true);
  xhttp.send();
}, 10000 ) ;

setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("humidity").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/humidity", true);
  xhttp.send();
}, 10000 ) ;
</script>
</html>)rawliteral";

// Replaces placeholder with DHT values
String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATURE"){
    return String(t);
  }
  else if(var == "HUMIDITY"){
    return String(h);
  }
  return String();
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);
  dht.begin();
  
  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);

  // Print ESP8266 Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });
  server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", String(t).c_str());
  });
  server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", String(h).c_str());
  });

  // Start server
  server.begin();
}
 
void loop(){  
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    // save the last time you updated the DHT values
    previousMillis = currentMillis;
    // Read temperature as Celsius (the default)
    float newT = dht.readTemperature();
    // Read temperature as Fahrenheit (isFahrenheit = true)
    //float newT = dht.readTemperature(true);
    // if temperature read failed, don't change t value
    if (isnan(newT)) {
      Serial.println("Failed to read from DHT sensor!");
    }
    else {
      t = newT;
      Serial.println(t);
    }
    // Read Humidity
    float newH = dht.readHumidity();
    // if humidity read failed, don't change h value 
    if (isnan(newH)) {
      Serial.println("Failed to read from DHT sensor!");
    }
    else {
      h = newH;
      Serial.println(h);
    }
  }
}

View raw code

Customize the SSID and Password

You need to define a SSID name and a password to access the ESP8266. In this example we’re setting the ESP8266 SSID name to ESP8266-Access-Point, but you can modify the name to whatever you want. The password is 123456789, but you can also modify it.

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

Setting the ESP8266 as an Access Point (AP)

There’s a section in the setup() to set the ESP8266 as an access point using the softAP() method:

WiFi.softAP(ssid, password);

There are also other optional parameters you can pass to the softAP() method. Here’s all the parameters:

.softAP(const char* ssid, const char* password, int channel, int ssid_hidden, int max_connection)
  • ssid (defined earlier): maximum of 31 characters
  • password (defined earlier): minimum of 8 characters. If not specified, the access point will be open (maximum 63 characters)
  • channel: Wi-Fi channel number (1-13). Default is 1
  • ssid_hidden: if set to true will hide SSID
  • max_connection: max simultaneous connected stations, from 0 to 8

Next, get the access point IP address using the softAPIP() method and print it in the Serial Monitor.

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

Note: by default, the access point IP address is 192.168.4.1

These are the snippets of code you need to include in your web server sketches to set the ESP8266 as a soft access point.

To learn how the full web server code works, read: ESP8266 NodeMCU DHT11/DHT22 Temperature and Humidity Web Server with Arduino IDE.

Parts Required

To proceed with this tutorial, you need the following parts:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Schematic Diagram

Assemble all the parts by following the next schematic diagram:

ESP8266 NodeMCU Access Point (AP) Web Server Circuit Schematic Diagram DHT sensor

Connecting to the ESP8266 Access Point

Having the ESP8266 running the sketch, in your smartphone open your Wi-Fi settings and tap the ESP8266-Access-Point network:

Connect to ESP8266 NodeMCU Access Point (AP Mode)

Enter the password you’ve defined earlier.

ESP8266 NodeMCU Access Point (AP) Enter Password

Open your web browser and type the IP address http://192.168.4.1. The web server page should load:

ESP8266 NodeMCU Access Point Web Server using Arduino IDE

The web server page is a bit different from the original web server. That web server displays two icons next to the temperature and humidity. Those icons are loaded from the Font Awesome website. However, because the ESP8266 acts a soft access point (it is not connected to the internet) we cannot load those icons.

Wrapping Up

In this tutorial you’ve learned how to set the ESP8266 as a soft access point. This allows you to connect to the ESP8266 web server directly via Wi-Fi without the need to connect to a router.

However, note that the ESP8266 is not connected to the internet, so you can’t make HTTP requests to other services to publish sensor data or to get data from the internet (like loading the icons).

You may also like reading:

Thanks for reading.


Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »

Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »


Enjoyed this project? Stay updated by subscribing our weekly newsletter!

9 thoughts on “ESP8266 NodeMCU Access Point (AP) for Web Server”

    • There are similar projects for the Arduino. But you need an Ethernet shield.
      If you don’t have an Ethernet shield, it is more advantageous getting an ESP8266 or ESP32.

      Regards,
      Sara

  1. Great article,

    Note: by default, the access point IP address is 192.168.4.1

    Is it possible to change the default IP address so that multiple access points can be created?

    Thank you

    • Hi Ben.
      Yes, you can do that using the following function to configure the access point:
      softAPConfig (local_ip, gateway, subnet)
      Regards,
      Sara

  2. Hy dears,
    I’m wondering if a “non NodeMCU” ESP8266 model will go to the same.
    I have some older ESP01 by hand, but perhaps these boards haven’t enough memory to load the sketch. Or are there any other reasons they couldn’t do the staff ?

    Best regards and thanks for your job.
    Gatsby

  3. Hi thanks for another great tutorial. I have used many of your tutorials and books to learn iot. i am a little puzzled where I would actually use a soft ap with no connection to the rest of the network. To me the point of iot is that it’s all connected together using my node red server and that i can get telegram messages about what is going on when I’m not at home. Am I missing something here.

    • Hi Archer,
      I see your point. But in some cases, people found it more practical to use an access point rather than connecting to a wi-fi network. For example, to control a toy robot that you want to take anywhere, having an access point can be more practical.
      Thank you for your comment and thank you for supporting our work.
      Regards,
      Sara

  4. Hi Sara, Thank you for the reply

    Yes, you can do that using the following function to configure the access point:
    softAPConfig (local_ip, gateway, subnet)

    Pardon my lack of knowledge,
    In the code I donot see where “gateway” and “subnet” are defined
    do I do add something like

    const char* local_ip = “192.168.4.2”; // ESP8266 IP desired
    const char* gateway = “192.168.0.1”; // ESP8266 gateway desired
    const char* subnet = “255.255.255.0”; // ESP8266 subnet desired

    and put
    softAPConfig (local_ip, gateway, subnet)
    in void setup()
    just after
    WiFi.softAP(ssid, password); // ?
    How do I choose the gateway and subnet numbers?

    Thanks
    Ben

Leave a Comment

Download our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.