ESP8266 range question

What is the typical range of an NodeMCUv1 esp8266 running in SoftAP mode in line of sight without noisy environment. I'm getting about 20ft without loosing connection with multiple android phones. However I am able to connect to an AP from pretty far away?!?

The range of wireless connection depends on how "loud" you are shouting, how far are sender and receiver apart, what is in between and how sensitive are the ears on the other side. If you communicate both ways, the same is true for the way back. It called the link budget and uses a love/hate logarithmic unit called Decibel (dB).

From this you can see there are a couple of points of failure.

If your WiFi access point has good antennas, a sensitive receiver and a high power transmiter you will be able to talk to it and listen to it over longer distances, without changing anything on your side.

Your mobile phone needs to be cute and cool. It can't have antennas sticking out of it and it can't use as much power.

If you want to compare the chips capability. Google 8266 data sheet. Then look for TX Power and RX Sensitivity. It's usually on the first couple of pages because these are key differentiators for wireless chips.

TX Power, a larger positive number means more power can be sent. This does not mean you are allowed to send with this much power. This is different for each country and for each frequency band.

RX Sensitivity, a more negative value means more sensitivity.

Beware: 0 dBm means 1mW and not 0 mW.

2 Likes

That is not a helpful answer. Cellphone infact do have antennas built into the case. They have multiple antennas for 5ghz an 2.4ghz. This is not a cellphone to esp8266 issue. This is a issues with the esp8266 itself. 20ft does not seem right. Or does it? Nodemcu to Nodemcu I get 20ft. I am going to assume this isn't right. What exactly is causing this. I use multiple types of modules all with the same exact result. Is this to be expected with standard nodemcu ap????

I have had a pair of ESP8266 modules working with ESP-NOW at a range of about 100 metres outdoors. I don't see why the same range would not be possible with WiFi.

...R

Robin2:
I have had a pair of ESP8266 modules working with ESP-NOW at a range of about 100 metres outdoors. I don't see why the same range would not be possible with WiFi.

...R

I dont know how reliable wifioverview360 for android is but at about 20-30ft in 802.11b mode at max power inside my home about 30ft away I'm showing
-80dB. The esp8266 is in my hallway and I'm standing at the other end of the hallway. I soldered a 2.4ghz antenna from one of my nrf24 card directly to the esp8266 and I cant tell if it helped any. I may have gotten an extra 10ft out of it.

What would be the ideal esp8266 breakout board for the best possible SoftAP range?

I am sorry the answer was not helpful. The fact is, antennas in mobile phones need to make compromises that antennas in wifi access point do not need to make.

WiFi access points are designed to get good connections in houses with lots of walls, steel and the fact that they are not moved around. Power usage and small housing are of second concern. Why are routers ten times the size of a mobile phones, made from cheap plastic, many have antennas sticking out of them and get warm?

Your mobile phone has metal inside is very small and you are conditioned to move when you have a bad connection.

WiFi uses 2.4GHz, which is the resonance frequency of water. That means the signals are absorbed by air moisture. That's why it is a free ISM band. You cannot use it for broadcast of TV and other commercial services. The signals are very weak and good antennas and sensitive receivers are important.

Soldering antennas to your nodes will not work in most cases. For most electrical engineers this is black magic. The ones who know this stuff, use very expensive equipment and experimentation to get the best out of every situation. Many engineers use readymade modules with build in antennas because they do not want to deal with high frequency issues. So do not feel bad about it.

There are WiFi modules with external antennas. This will give you the best chance of getting longer distances between nodes.

If it does not have to be WiFi and you do not have large amounts of data look at sub GHz technologies like LoRa. You can achieve longer distances easier.

1 Like

Is there a way to override the mW output from esp8266? Is 20.5 is maximum output power period? Shouldn't this be more like 40mw? I didn't see any mention in the data sheet about the output mW of the antenna. I'm not very good at understand the sensitivity details either. I'm just assuming its 20.5 mW

Klaus_K:
WiFi uses 2.4GHz, which is the resonance frequency of water. That means the signals are absorbed by air moisture. That's why it is a free ISM band.

There is absorbtion of radio waves due to mositure in the air, but the effect is very small indeed, fractions of a dB per kilometer.

srnet:
There is absorbtion of radio waves due to mositure in the air, but the effect is very small indeed, fractions of a dB per kilometer.

So am I getting the expected behavior of a standard nodemcu with the PCB trace antenna? Btw its 10 degrees where I'm at so not much moisture in the air.

Another strange thing ive noticed about the client side of the esp8266 when i connect it to my home network the ping delay is 500+ms most of the time timing out. however it still seems to be functioning? when i changed the server to STA mode and connected it to my home network the ping delay is only 5ms. any ideas?

c:\Windows\System32>ping 10.0.0.13

Pinging 10.0.0.13 with 32 bytes of data:
Reply from 10.0.0.13: bytes=32 time=1188ms TTL=255
Reply from 10.0.0.13: bytes=32 time=570ms TTL=255
Request timed out.
Request timed out.

Ping statistics for 10.0.0.13:
    Packets: Sent = 4, Received = 2, Lost = 2 (50% loss),
Approximate round trip times in milli-seconds:
    Minimum = 570ms, Maximum = 1188ms, Average = 879ms

c:\Windows\System32>

Server,
Pinging 10.0.0.12 with 32 bytes of data:
Reply from 10.0.0.12: bytes=32 time=1ms TTL=255
Reply from 10.0.0.12: bytes=32 time=1ms TTL=255
Reply from 10.0.0.12: bytes=32 time=9ms TTL=255
Reply from 10.0.0.12: bytes=32 time=1ms TTL=255

Ping statistics for 10.0.0.12:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 1ms, Maximum = 9ms, Average = 3ms

c:\Windows\System32>

I do not know exactly which libraries you are using, please let me know which one, if the function calls below do not exist in your library.

First, look at the ESP8266 data sheet for TX Power. You should see

TX Power 802.11 b: + 20dBm (that is 100mW)
TX Power 802.11 g: + 17dBm (that is 50mW)
TX Power 802.11 n: + 14dBm (that is 25mW)

RX Power 802.11 b: - 91dBm (that is 8 to the power of -10 mW) most sensitive
RX Power 802.11 g: - 75dBm (that is 3 to the power of -8 mW) second most sensitive
RX Power 802.11 n: - 72dBm (that is 6 to the power of -8 mW) least sensitive but close to 2

So 802.11b should give you the longest distance, which makes sense it has the lowest bitrate. But test all three modes to see which one is the best in your environment.

There should be a function WiFi.setPhyMode(PHY_MODE_11B).

If this is set you should be able to use the WiFi.setOutputPower(20.5); to set the maximum output power of 100mW. Be careful when you call this function when you have chosen a different phy mode. I am not sure what happens. You would need to look at the source code. It could just simply call the maximum possible, the minimum or do nothing at all.

Klaus_K:
I do not know exactly which libraries you are using, please let me know which one, if the function calls below do not exist in your library.

First, look at the ESP8266 data sheet for TX Power. You should see

TX Power 802.11 b: + 20dBm (that is 100mW)
TX Power 802.11 g: + 17dBm (that is 50mW)
TX Power 802.11 n: + 14dBm (that is 25mW)

RX Power 802.11 b: - 91dBm (that is 8 to the power of -10 mW) most sensitive
RX Power 802.11 g: - 75dBm (that is 3 to the power of -8 mW) second most sensitive
RX Power 802.11 n: - 72dBm (that is 6 to the power of -8 mW) least sensitive but close to 2

So 802.11b should give you the longest distance, which makes sense it has the lowest bitrate. But test all three modes to see which one is the best in your environment.

There should be a function WiFi.setPhyMode(PHY_MODE_11B).

If this is set you should be able to use the WiFi.setOutputPower(20.5); to set the maximum output power of 100mW. Be careful when you call this function when you have chosen a different phy mode. I am not sure what happens. You would need to look at the source code. It could just simply call the maximum possible, the minimum or do nothing at all.

Im not exactly sure what im looking for in the library that happens when calling that function. However i am using those functions. I tried,b,n,g and b giving the best range i have left it there as i don't need a high data rate. at b mode at max output power 20.5 i still am at -80 - -85 db when 20-30ft away from the SoftAP. I will post my client code below. it seems something in my loop (probably the sensor read function) was causing the extremely high latency. The main issue here now is i cannot connect these to my home network as b,g,n modes will drastically slow down the wireless network all together. This is why i would like to use the esp8266 in SoftAP mode so i don't need to use local home network resources.

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

IPAddress Server(10, 0, 0, 12);

bool ready = true;
const int oneWireBus = 0;
const char* ssid = "Wireless3";
const char* password = "123456!!";
char verifyStart[7];
char verifyEnd[7];
unsigned int localUdpPort = 4220;  // local port to listen on
char incomingPacket[255];  // buffer for incoming packets
int ServerPort = 4210;

byte Temp1[8] = {0x28, 0x0E, 0xD3, 0x45, 0x92, 0x15, 0x02, 0xB4 };

unsigned long now = 0;
unsigned long now2 = 0;

struct packet {
  int local;
  float temp;
};
packet localData;
WiFiUDP Udp;
OneWire oneWire(oneWireBus);
DallasTemperature sensors(&oneWire);
void setup() {
  sensors.setResolution(Temp1, 11);
  WiFi.persistent(0);
  WiFi.softAPdisconnect();
  WiFi.mode(WIFI_STA);
  Serial.begin(115200);
  Serial.println();
  WiFi.setOutputPower(20.5);
  WiFi.setAutoConnect(true);
  WiFi.setPhyMode(WIFI_PHY_MODE_11N);

  WiFi.begin(ssid, password);
  IPAddress ip(10, 0, 0, 13);
  IPAddress gateway(10, 0, 0, 1);
  IPAddress subnet(255, 0, 0, 0);
  WiFi.config(ip, gateway, subnet);
  sensors.begin();
  Serial.println(" connected");
  Udp.begin(localUdpPort);
  Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
}

void averageReading () {
  ready = false;
  Serial.println("2");
  float average = 0.0 ;
  for (byte i = 0 ; i < 20 ; i++) {
    sensors.requestTemperatures();
    average +=  sensors.getTempFByIndex(0); //get temp reading from dallas library
  }
  if (average / 20 > -10 && average / 20 < 199) {
    localData.temp = average / 20;
  }
  Serial.print(localData.temp);
  Serial.println("ºF");
  sendPacket();
}

void sendPacket() {
  Serial.println("3");
  const char delimiter[] = "NODE01";
  const char delimiter2[] = "01NODE";

  Udp.beginPacket(Server, ServerPort);
  Udp.write((const uint8_t *)delimiter, sizeof(delimiter) - 1);
  Udp.write((const uint8_t *)&localData, sizeof(localData));
  Udp.write((const uint8_t *)delimiter2, sizeof(delimiter2) - 1);
  Udp.endPacket();
  ready = true;
}
void loop()
{
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    //Serial.print(".");
  }
  if (ready) {
    if (millis() - now2 >= 550) {
      //Serial.println("1");
     // averageReading ();
      now2 = millis();
    }
  }

  int packetSize = Udp.parsePacket();
  if (packetSize) {
    Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    int len = Udp.read(incomingPacket, 800);
    strncpy(verifyStart, (char*)incomingPacket, 6 );
    strncpy (verifyEnd, (char*)incomingPacket + len - 6 , 7 );
    Serial.println(verifyStart);
    Serial.println(verifyEnd);
    if (strcmp(verifyStart, "NODECM") == 0) {
      const char ACK[] = "ACKED1";
      Udp.beginPacket(Server, ServerPort);
      Udp.write((const uint8_t *)ACK, sizeof(ACK) - 1);
      Udp.endPacket();
    }
  }
}

right now i have it set to n mode just because its connected to my wireless router.

Regarding the ping, I do not have a nodemcu. I have a ATWINC1500 WiFi. After a long time, I get 46ms ping delay for the first one and then just below 10ms.

The delay probably comes from the power management. Embedded WiFi modules need to save as much power as possible to compete in the market. Maybe the ESP8266 firmware developer where a bit too aggressive and choose to have longer delays in favor of saving power. It sounds like a good idea to have longer delay and lower power in one mode and use some more power but have shorter delay in another mode. That could explain the difference between AP and STA mode.

Klaus_K:
Regarding the ping, I do not have a nodemcu. I have a ATWINC1500 WiFi. After a long time, I get 46ms ping delay for the first one and then just below 10ms.

The delay probably comes from the power management. Embedded WiFi modules need to save as much power as possible to compete in the market. Maybe the ESP8266 firmware developer where a bit too aggressive and choose to have longer delays in favor of saving power. It sounds like a good idea to have longer delay and lower power in one mode and use some more power but have shorter delay in another mode. That could explain the difference between AP and STA mode.

I can't physically measure the transmit power. But it sure seems to me that at a 100mw I should get a lot more than 30ft range. Maybe your on to something. I will reflash the firmware and see what happens

So i reflashed the firmware and its the same result. i flashed the firmware from here ESP8266_AT/bin at master · espressif/ESP8266_AT · GitHub

i think i just need a better module or something. not setting the power to high resulted in a weaker connection.

Heres my code for the SoftAP.

//extern "C"{
//  #include "user_interface.h"
//}
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <LiquidCrystal_I2C.h>
IPAddress local_IP(192, 168, 4, 1);
IPAddress gateway(192, 168, 4, 1);
IPAddress subnet(255, 255, 255, 0);

IPAddress Client1(192, 168, 4, 100);
LiquidCrystal_I2C lcd(0x27, 20, 4);
WiFiUDP Udp;
unsigned long previousMillis = 0;
unsigned long minmaxwait = 0;
unsigned long minmaxwait2 = 0;
int ledState = LOW;
const long interval = 300;
bool running = false;
bool alarm = false;
const char* ssid = "weatherStation";
const char* password = "a1b2c3d4";
unsigned long now = 0;
unsigned long now2 = 0;
unsigned long now3 = 0;
unsigned long now4 = 0;
unsigned int localUdpPort = 4210;  // local port to listen on
unsigned int clientPort = 4220;
char incomingPacket[800];  // buffer for incoming packets
float maxTemp = -99;
float minTemp = 199;
struct packet {
  int local;
  float temp;
};
packet localData;

void setup() {
  WiFi.setPhyMode(WIFI_PHY_MODE_11B);
  pinMode(12, INPUT_PULLUP);
  digitalWrite(12, HIGH);
  pinMode(14, OUTPUT);
  digitalWrite(14, LOW);
  lcd.init();
  lcd.backlight();
  //WiFi.setOutputPower(20.5); 
  WiFi.persistent(0);
  Serial.begin(115200);
  Serial.println();
  WiFi.mode(WIFI_AP);
  

  while (!WiFi.softAP(ssid, password, 9, false, 15)) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(WiFi.softAPConfig(local_IP, gateway, subnet) ? "Ready" : "Failed!");
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("CONNECTING!!");
  Udp.begin(localUdpPort);
  Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.softAPIP().toString().c_str(), localUdpPort);
}

void sendCommand(IPAddress to, char* data,  bool requestResponse) {
  char* packetData = data;
  const char delimiter[] = "NODECM";
  const char delimiter2[] = "CMNODE";
  Udp.beginPacket(to, clientPort);
  if (requestResponse) {
    Udp.write((const uint8_t*)delimiter, sizeof(delimiter) - 1);
    Udp.write((const char*)packetData, sizeof(packetData));
    Udp.write((const uint8_t*)delimiter2, sizeof(delimiter2) - 1);
  } else {
    Udp.write((const char*)packetData, sizeof(packetData));
  }
  Udp.endPacket();
}

void loop()
{
  if (running) {
    if (millis() - now4 >= 1000) {
      if (minTemp < 57) {
        alarm = true;
        lcd.setCursor(0, 3);
        lcd.print("TOO COLD!!");
      }
      if (maxTemp > 91) {
        alarm = true;
        lcd.setCursor(0, 3);
        lcd.print("TOO HOT!!");

      }
      now4 = millis();
    }

  }
  if (alarm) {


    unsigned long currentMillis = millis();

    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      if (ledState == LOW) {
        ledState = HIGH;
      } else {
        ledState = LOW;
      }
      digitalWrite(14, ledState);

    }
  }
  if (digitalRead(12) == LOW) {
    maxTemp = -99;
    minTemp = 199;
    alarm = false;
    lcd.setCursor(0, 3);
    lcd.print("            ");
    digitalWrite(14, LOW);
  }
  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    // Serial.println("Message");
    int len = Udp.read(incomingPacket, 800);
    char verifyStart[7];
    char verifyEnd[7];
    Serial.println((char*)incomingPacket);
    strncpy (verifyStart, (char*)incomingPacket, 7 );
    strncpy (verifyEnd, (char *)incomingPacket + len - 6 , 7 );
    if (strcmp(verifyStart, "NODE01") == 0) {
      if (strcmp(verifyEnd, "01NODE") == 0) {
        // Serial.println("Node01");
        memcpy(&localData, incomingPacket + 6, sizeof(localData));
        //Serial.print("Tempature is  ");

        if (localData.temp > -32 && localData.temp < 199) {
          if (localData.temp > maxTemp) {
            if (millis() - minmaxwait >= 3000) {
              running = true;
              maxTemp = localData.temp;
              minmaxwait = millis();
            }
          } else {
            minmaxwait = millis();
          }
          if (localData.temp < minTemp) {
            if (millis() - minmaxwait2 >= 3000) {
              running = true;
              minTemp = localData.temp;
              minmaxwait2 = millis();
            }
          } else {
            minmaxwait2 = millis();
          }
        }
        lcd.setCursor(0, 0);
        lcd.print("Temperature:");
        if (localData.temp > -32 && localData.temp < 199) {
          lcd.setCursor(12, 0);
          lcd.print("      ");
          lcd.setCursor(12, 0);
          lcd.print(localData.temp);

        }

        lcd.setCursor(0, 1);
        lcd.print("Max Temp:");
        lcd.setCursor(9, 1);
        lcd.print("      ");
        lcd.setCursor(9, 1);
        lcd.print(maxTemp);
        lcd.setCursor(0, 2);
        lcd.print("Min Temp:");
        lcd.setCursor(9, 2);
        lcd.print("      ");
        lcd.setCursor(9, 2);
        lcd.print(minTemp);

        //   Serial.println(localData.temp);
        now = millis();
      }
    }
    if (strcmp(verifyStart, "RETURN") == 0) {
      now3 = millis();
    }
    Serial.println("hello");
    Serial.println(len);
    Serial.println(verifyStart);
    Serial.println(verifyEnd);
  }
}

I did a little experiment. I achieved 40m(130ft) free air with a little bit of vegetation distance with RSSI of -81dBm.

Here is the setup

Access Point: 3m(10ft) high outside

  • Adafruit Feather M0 WiFi board
  • Microchip WINC1500 WiFi module
  • Antenna: PCB

Client: ground level maximum distance about 40m(130ft)

  • Arduino Nano 33 IoT
  • ublox NINA-W102 WiFi module
  • Antenna: SMD, part of the module
  • send 100 UDP packages (10 bytes payload) five times (7 packages lost in one of the 5 times)

The library of these modules does not seem to support switching the WiFi modes and power levels. I used the default, which is likely set to maximum, but with around 18dBm (both modules) lower than your module.

Klaus_K:
I did a little experiment. I achieved 40m(130ft) free air with a little bit of vegetation distance with RSSI of -81dBm.

That seems to be consistent with my very limited test. My 100m range was without any vegetation and the stationary ESP8266 was only about 1.5m above ground level.

...R

I guess maybe there's some interference I dont know about. I dont have a spectrum analyzer or tools like that to be sure. Most of the ESP's I'm using are from different sellers and I refreshed the firmware on one of them without any different results. Right now I have them connected to my wifi but this isn't what I wanted although it works fine.

Thanks Klaus for going out of you way to test that. I'm stumped. There's only like 3 other houses near me and they are pretty far away but I guess that dont rule out interference. Then again I figure that would drown out any of my other wifi networks. I have a mikrotik ptp bridge setup between 2 houses but that's running at 5ghz. I guess I'm going to buy one with an sma antenna connector and see what happens there. I'm not going for directional antennas I would like the best radius and range combined that I can get.

Are the antennas oriented in the best direction and is there any metal close to the antenna that might be absorbing the signal?

IIRC the signal from the PCB antenna on an ESP8266-01 module propagates (is that the right word) perpendicular to the PCB.

...R