esp8266 / Arduino

ESP8266 core for Arduino
GNU Lesser General Public License v2.1
15.96k stars 13.34k forks source link

Connection keeps droping when ESP8266 set up as an access point #1615

Closed vitorsilvalima closed 8 years ago

vitorsilvalima commented 8 years ago

Hi guys, I have been facing some issues when I program my ESP8266/NODEMCU board as an access point. I'm currently using the Arduino version 1.6.7 and esp8266 version 2.0.0. I have tested with different sketches of mine and even with the one provided as an example(WiFIAccessPoint). I don't know why but the connection is really loose and the phone takes a long time to be able to connect to it. I have used ping tools to test sending data to the board and there is a lot of packet loss and connection timeout. The board sometimes even restarts with no reason. What is the most interesting is that when I use esp8266 version 1.6.5 there seems to have no issues and the connection never times out. ps: I use Fedora 23 64 bits.

vitorsilvalima commented 8 years ago

I have installed Arduino version 1.6.5 just to make sure there wasn't any conflict with the IDE and I still have the same issues

hallard commented 8 years ago

@vitorsilvalima I've got the same issue and I found how to reproduce it, I think there is a problem somewhere in the SDK, I spend some time to figure out the problem, here are the step to reproduce this issue :

Request timeout for icmp_seq 4181
Request timeout for icmp_seq 4182
64 bytes from 192.168.4.1: icmp_seq=4183 ttl=255 time=5.497 ms
Request timeout for icmp_seq 4184
Request timeout for icmp_seq 4185
Request timeout for icmp_seq 4186
Request timeout for icmp_seq 4187
64 bytes from 192.168.4.1: icmp_seq=4188 ttl=255 time=46.786 ms
64 bytes from 192.168.4.1: icmp_seq=4189 ttl=255 time=34.177 ms
Request timeout for icmp_seq 4190
Request timeout for icmp_seq 4191
Request timeout for icmp_seq 4192
Request timeout for icmp_seq 4193
Request timeout for icmp_seq 4194
64 bytes from 192.168.4.1: icmp_seq=4195 ttl=255 time=31.984 ms
Request timeout for icmp_seq 4196
64 bytes from 192.168.4.1: icmp_seq=4196 ttl=255 time=1740.184 ms
64 bytes from 192.168.4.1: icmp_seq=4198 ttl=255 time=108.993 ms
64 bytes from 192.168.4.1: icmp_seq=4199 ttl=255 time=22.304 ms
64 bytes from 192.168.4.1: icmp_seq=4200 ttl=255 time=3.922 ms
Request timeout for icmp_seq 4201
64 bytes from 192.168.4.1: icmp_seq=4202 ttl=255 time=8.549 ms
64 bytes from 192.168.4.1: icmp_seq=4203 ttl=255 time=26.428 ms
Request timeout for icmp_seq 4204

here a testing sketch to see the issue

#include <ESP8266WiFi.h>
#include <WiFiClient.h> 
#include <ESP8266WebServer.h>
#define SERIAL_DEBUG    Serial
ESP8266WebServer server(80);
void handleRoot() {
    server.send(200, "text/html", "<h1>Hello World!</h1>");
}

void setup() {
    int ret;
  // Set WiFi to station mode and disconnect from an AP if it was previously connected
  WiFi.mode(WIFI_AP_STA);
  SERIAL_DEBUG.begin(115200);
  SERIAL_DEBUG.println("\r\n========== SDK Saved parameters Start"); 
  WiFi.printDiag(SERIAL_DEBUG);
  SERIAL_DEBUG.println("========== SDK Saved parameters End"); 

  SERIAL_DEBUG.println("Connecting...");
  SERIAL_DEBUG.flush();

  WiFi.begin("YOUR-AP", "YourPSK");

  uint8_t timeout = 20; // 20 * 500 ms = 5 sec time out
  while ( ((ret = WiFi.status()) != WL_CONNECTED) && timeout ){
    SERIAL_DEBUG.print(".");
    SERIAL_DEBUG.flush();
    delay(500);
    --timeout;
  }

  // connected ? 
  if ((ret = WiFi.status()) == WL_CONNECTED) {
    SERIAL_DEBUG.println("connected!");

    SERIAL_DEBUG.print("IP address   : "); 
    SERIAL_DEBUG.println(WiFi.localIP());
    SERIAL_DEBUG.print("MAC address  : "); 
    SERIAL_DEBUG.println(WiFi.macAddress());

  // not connected ? start AP
  } else {
    SERIAL_DEBUG.println("Configuring access point...");
    SERIAL_DEBUG.flush();
    WiFi.softAP("ESP-SOFTAP","allowme");
    SERIAL_DEBUG.print("WiFi.softAP() called");
    SERIAL_DEBUG.flush();
    WiFi.softAPIP();

    SERIAL_DEBUG.print("IP address   : "); 
    SERIAL_DEBUG.println(WiFi.softAPIP());
    SERIAL_DEBUG.print("MAC address  : "); 
    SERIAL_DEBUG.println(WiFi.softAPmacAddress());
  }

    server.on("/", handleRoot);
    server.begin();
    SERIAL_DEBUG.println("HTTP server started");
}

void loop() {
    server.handleClient();
}
hallard commented 8 years ago

Oh, sorry, forgot to mention doing an ESP.eraseConfig() at the beginning os setup()does not solve the problem. May be disabling auto connect could help (I need to try tomorrow) but we'll loose a major feature, auto reconnect is case of main Router/AP reboot

hallard commented 8 years ago

Ok, I've done some basic investigations, hoping some SDK's guru will be able to help us to understand.

I've done a sketch that switch Wifi autoConnect parameter back and forth using NodeMCU board flash button, pushing button toggle on and off. But as changing autoConnect in loop does nothing (SDK says) so on each change I reboot the board. What is clear is that if autoConnect is on and and Wifi STA SSID/PSK does not connect or Router not present, the problem occurs in AP mode (may be take too much time trying to connect in STA mode) And, as soon as autoConnect is disable, AP is working fine, so I suspect autoConnect routine.

But there is a 2nd point, all I've just written is true only if you call ESP.eraseConfig() at the beginning of setup(). If you don't do that, AP is slow and broken whatever autoConnect is on or off. This means that SDK is storing something else somewhere used in conjunction with autoConnect.

Note also that ESP.eraseConfig() preserve autoConnect flag ;-)

Here is the sktech used

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

#define SERIAL_DEBUG  Serial

bool autoConnect;
int buttonState;            
int lastButtonState = LOW;  
long lastDebounceTime = 0;  
long debounceDelay = 50;    // the debounce time

/* ======================================================================
Function: handle_key_led 
Purpose : Manage on board Led and Push button of NodeMCU boards
Input   : 1 to light on the led, 0 to light off
Output  : 1 if button is pressed
Comments: on NodeMCU led is GPIO16 and switch (Flash) on GPIO 0
====================================================================== */
uint8_t handle_key_led( uint8_t level)
{
  uint8_t temp;
  digitalWrite(16, 1);
  pinMode(16, OUTPUT);
  digitalWrite(16, !level);

  // Flash is on GPIO0
  pinMode(0, INPUT);
  temp = digitalRead(0);
  pinMode(0, OUTPUT); 
  return !temp;
}

void setup() {
  int ret;

  ESP.eraseConfig();

  // Set WiFi to station mode and disconnect from an AP if it was previously connected
  WiFi.mode(WIFI_AP_STA);
  SERIAL_DEBUG.begin(115200);
  SERIAL_DEBUG.println("\r\n========== SDK Saved parameters Start"); 
  WiFi.printDiag(SERIAL_DEBUG);
  SERIAL_DEBUG.println("========== SDK Saved parameters End"); 
  SERIAL_DEBUG.println("Connecting...");

  // Get current autoconnect state from SDK
  autoConnect = WiFi.getAutoConnect();
  WiFi.begin("DummySSID", "whateverkeyjustdontconnect");

  uint8_t timeout = 10; // 10 * 500 ms = 5 sec time out
  // 500ms loop
  while ( ((ret = WiFi.status()) != WL_CONNECTED) && timeout ) {
    SERIAL_DEBUG.print(".");
    delay(500);
    --timeout;
  }

  // connected ? disable AP, client mode only
  if ((ret = WiFi.status()) == WL_CONNECTED) {
    SERIAL_DEBUG.println("connected!");
    SERIAL_DEBUG.print("STA IP address "); 
    SERIAL_DEBUG.println(WiFi.localIP());
  // not connected ? start AP
  } else {
    //WiFi.mode(WIFI_AP);
    SERIAL_DEBUG.println("Configuring access point...");
    WiFi.softAP("ESP-SOFTAP","allowmeistooshort");
    WiFi.softAPIP();
    SERIAL_DEBUG.print("AP IP address "); 
    SERIAL_DEBUG.println(WiFi.softAPIP());
  }

  SERIAL_DEBUG.println("Starting loop");
}

void loop() {

  uint8_t btn = handle_key_led(autoConnect);

  // Debouncing
  if (btn != lastButtonState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // if the button state has changed:
    if (btn != buttonState) {
      buttonState = btn;

      // Only on button pressed, not released
      if (buttonState == HIGH) {
        autoConnect = !autoConnect;
        WiFi.setAutoConnect(autoConnect);
        SERIAL_DEBUG.print("Autoconnect will be now ");
        SERIAL_DEBUG.println(autoConnect);
        SERIAL_DEBUG.println("Restarting...");
        delay(500);
        // Changing Auto Connect in loop does nothing
        // it will be taken into account on reboot only 
        // see SDK wifi_station_set_auto_connect 
        ESP.reset();
      }
    }
  }

  lastButtonState = btn;
}
vitorsilvalima commented 8 years ago

Hi Hallard,

I just tried to test your code here and it just says the following:

WifiIssue:48: error: 'class ESP8266WiFiClass' has no member named 'getAutoConnect' autoConnect = WiFi.getAutoConnect(); ^ /home/vlima/Arduino/WifiIssue/WifiIssue.ino: In function 'void loop()': WifiIssue:94: error: 'class ESP8266WiFiClass' has no member named 'setAutoConnect' WiFi.setAutoConnect(autoConnect); ^ exit status 1 'class ESP8266WiFiClass' has no member named 'getAutoConnect'

Which version of the library are you using because mine has no getAtutoConnect function?

hallard commented 8 years ago

I'm using IDE 1.6.7 + Latest git version of Arduino-Esp8266

getAutoConnect has been committed on Dec 29th https://github.com/esp8266/Arduino/commit/4a68612af862e0f11ea226bd57927e6aee1d991d#diff-170dccef5e4ac8c81a905fdfe877347f

vitorsilvalima commented 8 years ago

I see. I just installed it but now I've got another problem. The code of your sketch somehow is making my NODEMCU 1.0 restart forever even when I upload any other sketch to the board. The following characters is what I'm getting and they don't stop coming through. ����E�VKE�R|����E�VKE�R|��

vitorsilvalima commented 8 years ago

Actually, this is what I'm getting from the board: Fatal exception (28): epc1=0x40100524, epc2=0x00000000, epc3=0x00000000, excvaddr=0x00000001, depc=0x00000000

hallard commented 8 years ago

Do you still have the same problem with other example sketch ?

vitorsilvalima commented 8 years ago

Yes, I still have this same error with any other sketch now. What may have caused this issue? I have never seen it before

Sent from my Samsung device

-------- Original message -------- From: Charles notifications@github.com Date: 2016-02-10 12:38 (GMT-03:00) To: esp8266/Arduino Arduino@noreply.github.com Cc: Vitor Silva Lima vitor.lima2@fatec.sp.gov.br Subject: Re: [Arduino] Connection keeps droping when ESP8266 set up as an access point (#1615)

Do you still have the same problem with other example sketch ?

Reply to this email directly or view it on GitHubhttps://github.com/esp8266/Arduino/issues/1615#issuecomment-182400644.

hallard commented 8 years ago

Corrupted SDK Config by certainly flashing same device with different flash size between two flash (or sometime just changing board type) try esptool with erase_flash flag, see #1010

vitorsilvalima commented 8 years ago

I got my board working again by uploading the blink sketch using Arduino version 1.6.5 and ESP8266 version 2. And somehow the other loose connection issue seems to have gone away. ESP.eraseConfig();//caused my board to keep restarting Serial.println(WiFi.getAutoConnect()); //returns true

void setup() { delay(1000); Serial.begin(9600); //WiFi.softAPConfig(ip, gateway, subnet); WiFi.mode(WIFI_AP); WiFi.softAP(ssid, password); Serial.println("AP has started!"); Serial.println(WiFi.getAutoConnect()); server.begin(); pinMode(2,OUTPUT); } I tested this code and I don't know how but there is no package loss at all.

hallard commented 8 years ago

I think all of this cleared the "wrong thing" stored in by the SDK. I'm pretty sure if you flash another example sketch which connect to your Wifi Network and then flash back this working sketch while powering off your Wifi Router the problem will came back.

So my point point of view is, until you're not connecting your device to a Wifi network, it will continue working fine.

vitorsilvalima commented 8 years ago

Hi Hallard,

I have just tested uploading an example that connects to the WIFI router and it worked fine and then I upload another example which configured the board as an AP and it also worked fine with pretty good ping results. It is hard to tell what was going on, we may have to read the SDK and try to see what is going on. However, I don't think SSID and PASSWORD are stored directly into the flash memory because it is only used at run time. Moreover, I believe nothing would change the flash memory in an explicit way. We really need to go over that sdk doc and check just to make sure. I will try with my other boards and see if they still have the connection issue and I will let you know. Nevertheless, thank you for your help.

vitorsilvalima commented 8 years ago

*implicit way

hallard commented 8 years ago

@vitorsilvalima SSID and PSK are stored in specific flash area by SDK ;-) So even if you don't connect in your code, it will retain latest successful information which has worked (connected to your SSID) and will connect if auto connect is true (the default) I will open another case for my specific issue. May be you can close you one now if all is working for you.

vitorsilvalima commented 8 years ago

Okay, thank you.

pmcdonaldgit commented 8 years ago

I see there is no activity on this topic since february. I am here via google because I was trying to figure out a series of anomalous events that sound a lot like what's happening here.

In particular, I have had three different wierd situations where a sketch with no password and ssid still connected to the same AP that the device had previously been connected to.

In another instance, the device was running code in STA mode with no mention of AP mode or a network name etc and yet I was able to connect to its AP (after discovering it unexpectedly in a netscan) - so in otherwords I first loaded a sketch that created an AP named "MyAP". I experimented some and decided to do some other experiments and the AP reappeared/remained remained even after I uploaded a new unrelated sketch (which was in fact simultaneously working correctly as a wifi client to my regular router)

There is some really strange stuff going on with what gets saved by the SDK and I think sometimes stuff that was previously saved (silently by the SDK) then gets used accidentally when the parameters to the SDK information results in some subsequent error/failure to connect - even in independent, unrelated sketches.

Anyone able to add anything or point to something useful now?

TIA

paulfer747 commented 8 years ago

Hi GUys, I have ben asking on esp8266.com about this very same thing.

Any answers yet? Mine is the same...in dual mode, when ,my home's router gets turned off, the AP mode becomes completely unreliable.

Regds

Paul

paulfer747 commented 8 years ago

@igrr can you maybe shed some light one this?

Do you have example code of how we can run dual mode STA and AP ? The problem is that when the STA mode cant find a decent AP to connect to the system hangs terribly.

.setAutoConnect(false) may be an option but then how would we code to restart the system?

An example would be nice!

Regds

Paul

hallard commented 8 years ago

Here what I do in every sketch that need AP mode and STA was unable to connect

  // Blah Blah Wifi connection to AP
  //  ....

  // connected to AP ?
  if ( WiFi.status() == WL_CONNECTED ) {
      // Remove AP (in this case I don't need to be AP)
      WiFi.mode(WIFI_STA);
    } else {
      // STA+AP Mode without connected to STA, autoconnect will search
      // other frequencies while trying to connect, this is causing issue
      // to AP mode, so disconnect will avoid this
      // Disabling auto retry search channel
      WiFi.disconnect(); 

      // Start your own AP
      WiFi.softAP("YourSoftAP", "YourKey");
  }
paulfer747 commented 8 years ago

HI @hallard

Thanks for this, but this still does not mean that the ESP is operating in dual mode. It means you need to chose between AP or STA mode. Or have I got it wrong?

I am trying to write a sketch that allows my Android app to connect to the ESP's AP every 30 secs , AND for the ESP to send out data via the internet every minute. It works fine whilst the router in my home is on, but the minute I turn the router off, the AP side of things hangs up with monotonous regularity.

Somehow, somewhere, in the brains of the SDK there must be something that hangs up when it cannot find the router in STA mode.

I have literally tried every means to disable/re enable, etc the WiFi, but there is absolutely nothing that is solving this.

sticilface commented 8 years ago

In my experience the AP is fairly unstable if the STA is trying to reconnect. If it had connection and then doesn't it will do a scan every second, and try to reconnect, which i assume causes too much time to be spent away from handling the main stuff / AP stuff.

You can see if this is happening by enabling the WiFi debug. I think i've made it try to reconnect for 2 mins then disable it, then enable the AP, so that it can work properly.

krzychb commented 8 years ago

In my experience the AP is fairly unstable if the STA is trying to reconnect.

I believe this is because soft-AP and STA are using single hardware channel, If STA reconnects using another channel, then soft-AP has to adjust accordingly. ref. http://bbs.espressif.com/viewtopic.php?f=10&t=324, Case 2

paulfer747 commented 8 years ago

Hi gents. Thanks for this. Yes. I think the only option is to have 2 esp's side by side. One acting as ap and another acting as a sta. Thanks again!

moycat commented 7 years ago

I have been suffering this problem, too. I believe the reason is case 3 in http://bbs.espressif.com/viewtopic.php?f=10&t=324,

Now I have found a (kind of ugly) way to partly solve it. At least now it can reconnect to the ap and the softAP is normal in most time.

It is quite easy: turn off the "auto-reconnect" feature, and set up a timer to let it reconnect once in a proper() time.

This is ugly, because when it is trying to connect, the softAP network TCP connection will still be broken. And it makes my web update aborted if the timer goes off when uploading, so I have to turn it off before upload.

Now the ping result is like:

来自 192.168.4.1 的回复: 字节=32 时间=11ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=8ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=6ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=2ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=5ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=8ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=6ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=8ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=6ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=363ms TTL=128 请求超时。(timeout) 来自 192.168.4.1 的回复: 字节=32 时间=5ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=5ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=6ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=5ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=5ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=7ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=5ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=8ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=5ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=375ms TTL=128 请求超时。 来自 192.168.4.1 的回复: 字节=32 时间=7ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=7ms TTL=128 来自 192.168.4.1 的回复: 字节=32 时间=6ms TTL=128

And the fake code is like:

bool tryConnect = true;

void WiFiConnect(void *pArg)
{
    tryConnect = true;
}

/*Warning: though I have disabled reconnect, it still auto-reconnect after calling WiFi.begin() once. So I have to set this event listener.*/
/*Maybe I don't need this. Please tell me :)*/
void eventListener(WiFiEvent_t event)
{
    if (event == WIFI_EVENT_STAMODE_DISCONNECTED) {
        WiFi.disconnect(); // Wipe the config saved
    }
}

void connectWiFi()
{
    if (!tryConnect) {
        return;
    }
    tryConnect = false;
    WiFi.begin(SSID, PASSWORD);
}

void setup()
{
/*others*/
    WiFi.setAutoConnect(false);
    WiFi.setAutoReconnect(false);
    /*SDK functions. Include their head files first.*/
    os_timer_setfn(&WiFiConnector, WiFiConnect, NULL);
    os_timer_arm(&WiFiConnector, WIFI_INTERVAL, true);
    WiFi.onEvent(eventListener);
/*others*/
}

void loop()
{
/*others*/
    connectWiFi()
/*others*/
}
Wafalafel commented 7 years ago

I am new to this forum. I had this problem of esp8266 not connecting to access point. I an borrowing from an example I saw on the Github website which overcomes this problem. It waits for completion of connection otherwise it resets the ESP processor. It connects every time.

Here is the setup code: //GOOD LUCK!

void setup ( void ) { Serial.begin ( 115200 ); WiFi.mode(WIFI_STA); Serial.println ( "Config" ); //WiFi.config(staticIP, gateway, subnet, dns); //you can configure IP if you like here Serial.println ( "Begin" ); WiFi.begin ( ssid, password );
Serial.println ( "Connecting..." ); // Wait for connection, if it fails restart ESP if(WiFi.waitForConnectResult() != WL_CONNECTED) { Serial.println("WiFi Connect Failed! Rebooting..."); delay(1000); ESP.restart(); } //continue set up code here

//end }

hsadeghilam commented 6 years ago

I have the unstable connection with esp in AP mode when I connect to it via laptop or iPhone, but the connection is fine with my galaxy phone! Any suggestions how to resolve this?

rsonnicksen commented 6 years ago

I am using Arduino 1.6.7 and downloaded the WiFi AP example (never used STA mode) and having same disconnect issues.

gurilem commented 5 years ago

I was have the same problem. I just realized the wifi module on esp8266 needs enough current to make it operates perfectly. Try to power it with 5volt, 1Amp minimum, you can use smartphones charger.

Hope it will works..

Cheers from Indonesia...

Ihsan

apicquot commented 5 years ago

I noticed the same problem regardless of the power: I works fine if I remove the password for the AP. That let me to think WPA2 is to costly in computation and that the esp8266 may triggers a timout in the communication. I works if I switch the clock from 80MHz to 160MHz. Is there any problem with this clock frequency ?

Yonni20140812 commented 5 years ago

Arduino won't help to clear flash when programming, need to clear flash after several re-flash. I have download a blank files into flash for clear flash.

LaudixGit commented 3 years ago

@moycat if you are still around, THANKS! Not attempting to resurrect a thread, but years later still relevant. Commenting here for the next person following Google results.

My solution uses a pin to determine boot mode. If AP is selected, disable reconnect (learned of this from moycat above). Without this, browser dropped/reset AP connect within a second - very bad for my websockets.

normalBootMode = digitalRead(bootModePin); if (normalBootMode == LOW) { Serial.println(F("Become an access point")); WiFi.setAutoConnect(false);
WiFi.setAutoReconnect(false); // if wifi attempts to (re)connect to a previous router it kills the access point WiFi.softAP("APName"); } else { Serial.println(F("Normal mode")); WiFi.setAutoConnect(true); WiFi.setAutoReconnect(true); WiFi.mode(WIFI_STA); WiFi.hostname(hostName); WiFi.begin(ssid, pskPwd); Serial.println("");

// Wait for connection; indicate by flashing led and writing to serial
int iCnt = 0;
while (WiFi.status() != WL_CONNECTED) {
  delay(100);
  digitalWrite(led, HIGH);
  delay(150);
  digitalWrite(led, LOW);
  delay(100);
  digitalWrite(led, HIGH);
  delay(150);
  digitalWrite(led, LOW);
  Serial.print(F("."));
  iCnt++;
  if (iCnt % 25 == 0) { Serial.println("");}  // wrap line every so often
  if (iCnt % 150 == 0) { ESP.restart();}  // give up and reboot
}

}