Closed vseven closed 5 years ago
@AIWIndustries
There is a way to look up a lockup if the Traceback is printed to the terminal.
Install "ESP Exception Decoder" from; https://github.com/me-no-dev/EspExceptionDecoder Instructions are there.
Once installed just copy and paste the traceback line and it will tell you what is happening at lock up.
Hi All,
The following code is working for me.
void wifiReconnect() { while (WiFi.status() != WL_CONNECTED) { WiFi.begin(ssid, password); for(int i=0; i<=50; i++) { digitalWrite(LED_BUILTIN, HIGH); delay(100); Serial.print("."); digitalWrite(LED_BUILTIN, LOW); delay(100); } } }
Use this in the loop() as
if (WiFi.status() != WL_CONNECTED) { wifiReconnect(); }
Hi All I was using ESP32 core updated around 2 months ago. In my program i use Wifi.begin(ssid, pass) in setup() and calling WiFi.reconnect() method on "SYSTEM_EVENT_STA_DISCONNECTED" event. The system was connecting automatically if there are any disconnection. But yesterday i updated to latest core and that started giving error with reason code 8. After some hit and trials, i have commented WiFi.reconnect() then it started working perfectly. Also wifi reconnects automatically if AP is switched off and on.
In my case only in setup method i am using WiFi.mode(WIFI_STA); Wifi.begin()
this is working properly. Can we say that in new core there is no need to call reconnect() and autoreconnect is now working in latest core?
correct. there is no need to call reconnect anymore ;) I have that fixed :P
There is a serious flaw in wifi.Reconnect().
In a deep look thru the libraries I found in several conditions it will connect without doing a DHCP update so you are connected without an IP address. -- I reported it but have not seen a fix yet.
I proved this once buy adding a UDP call in some test code. - I could talk to the AP by UDP but had no IP address. At the same time the MAC showed up on the AP connection list.
You want to use wifi.begin() it is always reliable. - You simply must be sure that you are down when calling it to connect or you could end up with stack overflow issues.
The template I wrote below has never failed to reconnect. It is uses SmartConfig and preferences instead of hard coding the AP/Pass though that could easily be changed.
Some of my code is proprietary to the LED flasher so i left comments in place instead. You can put any indicator code you want there.
Take a look at the wifi down part of loop(). I call WiFi.begin( PrefSSID.c_str() , PrefPassword.c_str() ); while always testing for a return status of WL_CONNECTED.
Hope this helps some.
// ESP32 only, 8266 will not work here
#include "FS.h"
#include "esp_system.h"
#include <esp_wifi.h>
#include <string.h>
#include <WiFi.h>
#include <Preferences.h> // WiFi storage
const char* rssiSSID; // NO MORE hard coded set AP, all SmartConfig
const char* password;
String PrefSSID, PrefPassword; // used by preferences storage
int WFstatus;
int UpCount; = 0;
int32_t rssi; // store WiFi signal strength here
String getSsid;
String getPass;
String MAC;
// SSID storage
Preferences preferences; // declare class object
// END SSID storage
void setup() {
Serial.begin(115200);
Serial.printf("\tWiFi Setup -- \n" );
wifiInit(); // get WiFi connected
IP_info();
MAC = getMacAddress();
delay(2000); // let thing settle
} // END setup()
void loop()
{
if ( WiFi.status() == WL_CONNECTED )
{ // Main connected loop
// ANY MAIN LOOP CODE HERE
} // END Main connected loop()
else
{ // WiFi DOWN
// wifi down start LED flasher here
WFstatus = getWifiStatus( WFstatus );
WiFi.begin( PrefSSID.c_str() , PrefPassword.c_str() );
int WLcount = 0;
while ( WiFi.status() != WL_CONNECTED && WLcount < 200 )
{
delay( 100 );
Serial.printf(".");
if (UpCount >= 60) // keep from scrolling sideways forever
{
UpCount = 0;
Serial.printf("\n");
}
++UpCount;
++WLcount;
}
if( getWifiStatus( WFstatus ) == 3 ) //wifi returns
{
// stop LED flasher, wifi going up
}
delay( 1000 );
} // END WiFi down
} // END loop()
void wifiInit() //
{
WiFi.mode(WIFI_AP_STA); // required to read NVR before WiFi.begin()
// load credentials from NVR, a little RTOS code here
wifi_config_t conf;
esp_wifi_get_config(WIFI_IF_STA, &conf); // load wifi settings to struct comf
rssiSSID = reinterpret_cast<const char*>(conf.sta.ssid);
password = reinterpret_cast<const char*>(conf.sta.password);
// Serial.printf( "SSID = %s\n", rssiSSID ); // un-comment for debuging
// Serial.printf( "Pass = %s\n", password ); // un-comment for debuging
// Open Preferences with wifi namespace. Namespace is limited to 15 chars
preferences.begin("wifi", false);
PrefSSID = preferences.getString("ssid", "none"); //NVS key ssid
PrefPassword = preferences.getString("password", "none"); //NVS key password
preferences.end();
// keep from rewriting flash if not needed
if( !checkPrefsStore() ) // see is NV and Prefs are the same
{ // not the same, setup with SmartConfig
if( PrefSSID == "none" ) // New...setup wifi
{
initSmartConfig();
delay( 3000);
ESP.restart(); // reboot with wifi configured
}
}
// I flash LEDs while connecting here
WiFi.begin( PrefSSID.c_str() , PrefPassword.c_str() );
int WLcount = 0;
while (WiFi.status() != WL_CONNECTED && WLcount < 200 ) // can take > 100 loops depending on router settings
{
delay( 100 );
Serial.printf(".");
++WLcount;
}
delay( 3000 );
// stop the led flasher here
} // END wifiInit()
// match WiFi IDs in NVS to Pref store, assumes WiFi.mode(WIFI_AP_STA); was executed
bool checkPrefsStore()
{
bool val = false;
String NVssid, NVpass, prefssid, prefpass;
NVssid = getSsidPass( "ssid" );
NVpass = getSsidPass( "pass" );
// Open Preferences with my-app namespace. Namespace name is limited to 15 chars
preferences.begin("wifi", false);
prefssid = preferences.getString("ssid", "none"); //NVS key ssid
prefpass = preferences.getString("password", "none"); //NVS key password
preferences.end();
if( NVssid.equals(prefssid) && NVpass.equals(prefpass) )
{
val = true;
}
return val;
} // END checkPrefsStore()
void initSmartConfig()
{
// start LED flasher here
int loopCounter = 0;
WiFi.mode( WIFI_AP_STA ); //Init WiFi, start SmartConfig
Serial.printf( "Entering SmartConfig\n" );
WiFi.beginSmartConfig();
while (!WiFi.smartConfigDone())
{ // flash led to indicate not configured
Serial.printf( "." );
if( loopCounter >= 40 )
{
loopCounter = 0;
Serial.printf( "\n" );
}
delay(600);
++loopCounter;
}
loopCounter = 0;
// stopped flasher here
Serial.printf("\nSmartConfig received.\n Waiting for WiFi\n\n");
delay(2000 );
while( WiFi.status() != WL_CONNECTED )
{ // check till connected
delay(500);
}
IP_info();
preferences.begin("wifi", false); // put it in storage
preferences.putString( "ssid" , getSsid);
preferences.putString( "password", getPass);
preferences.end();
delay(300);
} // END SmartConfig()
void IP_info()
{
getSsid = WiFi.SSID();
getPass = WiFi.psk();
rssi = getRSSI( rssiSSID );
WFstatus = getWifiStatus( WFstatus );
MAC = getMacAddress();
Serial.printf( "\n\n\tSSID\t%s, ", getSsid.c_str() );
Serial.print( rssi); Serial.printf(" dBm\n" ); // printf??
Serial.printf( "\tPass:\t %s\n", getPass.c_str() );
Serial.print( "\n\n\tIP address:\t" ); Serial.print(WiFi.localIP() );
Serial.print( " / " ); Serial.println( WiFi.subnetMask() );
Serial.print( "\tGateway IP:\t" ); Serial.println( WiFi.gatewayIP() );
Serial.print( "\t1st DNS:\t" ); Serial.println( WiFi.dnsIP() );
Serial.printf( "\tMAC:\t\t%s\n", MAC.c_str() );
} // END IP_info()
int getWifiStatus( int WiFiStatus )
{
WiFiStatus = WiFi.status();
Serial.printf("\tStatus %d", WiFiStatus );
switch( WiFiStatus )
{
case WL_IDLE_STATUS : // WL_IDLE_STATUS = 0,
Serial.printf(", WiFi IDLE \n");
break;
case WL_NO_SSID_AVAIL: // WL_NO_SSID_AVAIL = 1,
Serial.printf(", NO SSID AVAIL \n");
break;
case WL_SCAN_COMPLETED: // WL_SCAN_COMPLETED = 2,
Serial.printf(", WiFi SCAN_COMPLETED \n");
break;
case WL_CONNECTED: // WL_CONNECTED = 3,
Serial.printf(", WiFi CONNECTED \n");
break;
case WL_CONNECT_FAILED: // WL_CONNECT_FAILED = 4,
Serial.printf(", WiFi WL_CONNECT FAILED\n");
break;
case WL_CONNECTION_LOST: // WL_CONNECTION_LOST = 5,
Serial.printf(", WiFi CONNECTION LOST\n");
WiFi.persistent(false); // don't write FLASH
break;
case WL_DISCONNECTED: // WL_DISCONNECTED = 6
Serial.printf(", WiFi DISCONNECTED ==\n");
WiFi.persistent(false); // don't write FLASH when reconnecting
break;
}
return WiFiStatus;
} // END getWifiStatus()
// Get the station interface MAC address.
// @return String MAC
String getMacAddress(void)
{
WiFi.mode(WIFI_AP_STA); // required to read NVR before WiFi.begin()
uint8_t baseMac[6];
esp_read_mac( baseMac, ESP_MAC_WIFI_STA ); // Get MAC address for WiFi station
char macStr[18] = { 0 };
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", baseMac[0], baseMac[1], baseMac[2], baseMac[3], baseMac[4], baseMac[5]);
return String(macStr);
} // END getMacAddress()
// Return RSSI or 0 if target SSID not found
// const char* SSID = "YOUR_SSID"; // declare in GLOBAL space
// call: int32_t rssi = getRSSI(SSID);
int32_t getRSSI( const char* target_ssid )
{
byte available_networks = WiFi.scanNetworks();
for (int network = 0; network < available_networks; network++)
{
if ( strcmp( WiFi.SSID( network).c_str(), target_ssid ) == 0)
{
return WiFi.RSSI( network );
}
}
return 0;
} // END getRSSI()
// Requires; #include <esp_wifi.h>
// Returns String NONE, ssid or pass arcording to request
// ie String var = getSsidPass( "pass" );
String getSsidPass( String s )
{
String val = "NONE"; // return "NONE" if wrong key sent
s.toUpperCase();
if( s.compareTo("SSID") == 0 )
{
wifi_config_t conf;
esp_wifi_get_config( WIFI_IF_STA, &conf );
val = String( reinterpret_cast<const char*>(conf.sta.ssid) );
}
if( s.compareTo("PASS") == 0 )
{
wifi_config_t conf;
esp_wifi_get_config( WIFI_IF_STA, &conf );
val = String( reinterpret_cast<const char*>(conf.sta.password) );
}
return val;
} // END getSsidPass()
I noticed this as well, but never narrowed it down, But I noticed that reconnect() and begin(ssid..) does not always reset dhcp, edge case I think
Begin(args) only redoes dhcp if config is not equal or not already connected, else it returns, which might be a problem.
wifi_config_t current_conf;
esp_wifi_get_config(WIFI_IF_STA, ¤t_conf);
if(!sta_config_equal(current_conf, conf)) {
if(esp_wifi_disconnect()){
log_e("disconnect failed!");
return WL_CONNECT_FAILED;
}
esp_wifi_set_config(WIFI_IF_STA, &conf);
} else if(status() == WL_CONNECTED){
return WL_CONNECTED;
}
// We do not always get here
if(!_useStaticIp) {
if(tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA) == ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED){
log_e("dhcp client start failed!");
return WL_CONNECT_FAILED;
}
} else {
tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA);
}
@mickeypop thanks for sharing code. But i have one doubt.
As you said:
I proved this once buy adding a UDP call in some test code. - I could talk to the AP by UDP but had no IP address. At the same time the MAC showed up on the AP connection list.
but as far i know, we can not make UDP connection without having an IP. UDP is built on IP layer.
@jjassar
UDP does not require any IP at all, just it's own MAC.
UDP is where the magic in the SmartConfig is. The app on your cell sends a specially formatted UDP packet just for the ESP32 with the AP credentials.
Because UDP is Connectionless, all WiFi devices on or off the AP can see it.
When the ESP32 sees this, it sends a different UDP to the AP to get a connection and the IP address from the AP. Remember before the connect there is no IP.
UDP is the under layer used in DHCP to get the IP in the first place but is also used in many other ways.
@mickeypop is it possible, that you are mixing TCP/UDP with broadcast/multicast? TCP and UDP both reside on transport layer, which is build on top of internet layer, where IP is.
@mickeypop @bedenko you both may be right, i think, it could be UDP broadcast on address 255.255.255.255. Anyway, i have found a new issue with latest repo. I was having an esp32 which was connected to AP, I switched off AP and Switched it back after some time. On disconnection if the reason code is 201(REASON_NO_AP_FOUND) then it connects automatically But sometimes the disconnection reason code 7(REASON_NOT_ASSOCED) then it never connects back, Only reconnect after hardware restart. Why reason code 7 is coming if I have switched off AP?
@jjassar @bedenko
Think about it for a moment. There has to be a protocol to connect BEFORE the device has an IP otherwise DHCP would not have any means to contact the DHCP server to "Get" an IP.
I was a Network Engineer for over 30 years and if UDP was not an integral part of TCP/IP you would have to re-setup IPs every time you moved to another network.
here's a little primer.
DHCP PROTOCOL
DHCP protocol is a connectionless protocol using UDP Port 68 and 67. It operates on client & server model. The DHCP client is our device ( traveller ) and the DHCP server is the one who shall provide us the IP ( The innkeeper ).
DHCP operates on UDP because DHCP client works on broadcasts, which can only be supported by UDP. This is needed because the client machine has still not received an IP address (this is the DHCP negotiation protocol purpose) and there would not be any way to establish a TCP stream without the IP address itself.
DHCP client starts by broadcasting the DHCP DISCOVER packet. The broadcast is received by the DHCP Server(s), which in turn replies with the DHCP OFFER message. The DHCP OFFER message contains the IP address offered by the server and the time period for which the IP address is allocated (The IP may be random, or based on an admin policy).
The DHCP client may receive multiple DHCP OFFER messages, however it chooses only one DHCP OFFER message based on the policy configured in the DHCP Client. Usually its on the first come first serve basis. However we can configure the DHCP Client to choose the DHCP OFFER having the longest lease time or some preferred subnet. The DHCP client now replies with the DHCP REQUEST message.
The DHCP REQUEST message is a broadcast message. When other DHCP servers receive this message, they withdraw any offers that they might have made to the client and return the offered address to the pool of available addresses. The intended DHCP server on receiving the message sends a DHCP ACK message, thus confirming the transaction and allocating the IP to the host for the specified amount of time.
@mickeypop: i agree with your explanation, except with the fact, that UDP can operate without IP address. All DHCP negotiation is done on broadcast IP 255.255.255.255 (info).
@bedenko You pretty much have to agree. I cut and pasted it directly from the official docs.
You are both right and wrong and here's why.
All network protocols use the same packet structure. AppleTalk, TCP/IP, Arpnet, AIX, etc... This let them coexist on the same ethernet without conflict.
The structure includes bits for protocol, type, checksum, destination etc... All look for the 24(255.255.255.255) bits in the destination identifier as a Special Identifier.
that said;
IP traffic is processed thru a Network Mask so all devices can determine if a packet is meant for them or not as well as routing.
UDP has no Network Mask. The 255.255.255.255 is not meant for the UDP sender or even used by them, it is so all other devices see the Special Identifier. It is not treated like an IP in this case at all.
NOTE: UDP sends by MAC not by IP.
Take DHCP for example, you don't have either IP or netmask yet, so the device goes into promiscuous mode looking for any packet with its own MAC address.
A DHCP DISCOVER packet is sent by UDP with the senders MAC address since the DHCP server must know who is requesting an IP.
The sender clearly cannot process it as IP traffic yet and to that end the DHCP server cannot use IP to send a response. Hence UDP.
The DHCP OFFER message returned by UDP must include the MAC for the client to know it is for them. Mind you all traffic is structured the same but it is not IP at all yet.
It is not until all negotiations are finished that any IP traffic is even possible.
===== Seperatly, i should note; I was on the team in 1968 - 70 developing the UNIX OS. There is where TCP/IP came to be. We used an early draft of UDP before TCP/IP even existed.
@mickeypop Thanks for your work! We can all touch the Sky because we stand on the Shoulders of Giants!
Chuck.
Hi. I use this code for this
if (WiFi.status() != WL_CONNECTED)
{
digitalWrite(26,0);
WIFI_Connect();
} else {
digitalWrite(26,1);
}
and, this is te function "WIFI_Connect"
void WIFI_Connect() { digitalWrite(26,HIGH); WiFi.disconnect(); Serial.println("Reconectando WiFi..."); WiFi.mode(WIFI_AP_STA); WiFi.begin(ssid, password); // Wait for connection for (int i = 0; i < 50; i++) { if ( WiFi.status() != WL_CONNECTED ) { delay ( 500 ); digitalWrite(26,0); Serial.print ( "." ); delay ( 500 ); digitalWrite(26,1); } } digitalWrite(26,0); }
For me this code work. Obs: The version 2.3
//this firebase project was deleted //you'll need to enter your own firebase info
void setup() {
pinMode(LED1,OUTPUT);
digitalWrite(LED1,0);
pinMode(LED2,OUTPUT);
digitalWrite(LED2,0);
pinMode(LED3,OUTPUT);
digitalWrite(LED3,0);
pinMode(LED4,OUTPUT);
digitalWrite(LED4,0);
pinMode(LED5,OUTPUT);
digitalWrite(LED5,0);
pinMode(LED6,OUTPUT);
digitalWrite(LED6,0);
pinMode(LED7,OUTPUT);
digitalWrite(LED7,0);
pinMode(LED8,OUTPUT);
digitalWrite(LED8,0);
Serial.begin(9600);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("connecting");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println();
Serial.print("connected: ");
Serial.println(WiFi.localIP());
Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
Firebase.setInt("LEDStatus",0);
}
void loop() {
if(Firebase.getInt("field1"))
{
digitalWrite(LED1,LOW);
}
else
{ digitalWrite(LED1,HIGH);
} if(Firebase.getInt("field2"))
{
digitalWrite(LED2,LOW);
}
else
{
digitalWrite(LED2,HIGH);
}
if(Firebase.getInt("field3"))
{
digitalWrite(LED3,LOW);
}
else
{ digitalWrite(LED3,HIGH);
}
if(Firebase.getInt("field4"))
{
digitalWrite(LED4,LOW);
}
else
{
digitalWrite(LED4,HIGH);
} if(Firebase.getInt("field5"))
{
digitalWrite(LED5,LOW);
}
else
{
digitalWrite(LED5,HIGH);
} if(Firebase.getInt("field6"))
{
digitalWrite(LED6,LOW);
}
else
{
digitalWrite(LED6,HIGH);
} if(Firebase.getInt("field7"))
{
digitalWrite(LED7,LOW);
}
else
{
digitalWrite(LED7,HIGH);
} if(Firebase.getInt("field8"))
{
digitalWrite(LED8,LOW);
}
else
{
digitalWrite(LED8,HIGH);
}
//Serial.println(Firebase.getInt("led1")); //Serial.println(Firebase.getInt("led2")); //Serial.println(Firebase.getInt("led3")); //Serial.println(Firebase.getInt("led4")); //Serial.println(Firebase.getInt("led5")); //Serial.println(Firebase.getInt("led6")); //Serial.println(Firebase.getInt("led7")); //Serial.println(Firebase.getInt("led8"));
Serial.println("..............."); if (Firebase.failed()) // Check for errors {
Serial.print("setting /number failed:");
Serial.println(Firebase.error());
return;
}
my nodemcu esp8226 not reconnect after connection lost til i re power it
This thread is for esp32. Are u using esp8266, or was it a typo?
esp82255 nodemcu
On Tue, 11 Sep 2018 1:45 PM Bedenko, notifications@github.com wrote:
This thread is for esp32. Are u using esp8266, or was it a typo?
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/espressif/arduino-esp32/issues/653#issuecomment-420196435, or mute the thread https://github.com/notifications/unsubscribe-auth/ApKpJ7SS4fk4KrHA1sVKmwV7brGVeh93ks5uZ3gxgaJpZM4PfOia .
Sorry this is esp8266
On Tue, 11 Sep 2018 1:48 PM Ijaz Ahmad, conceptualboy2@gmail.com wrote:
esp82255 nodemcu
On Tue, 11 Sep 2018 1:45 PM Bedenko, notifications@github.com wrote:
This thread is for esp32. Are u using esp8266, or was it a typo?
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/espressif/arduino-esp32/issues/653#issuecomment-420196435, or mute the thread https://github.com/notifications/unsubscribe-auth/ApKpJ7SS4fk4KrHA1sVKmwV7brGVeh93ks5uZ3gxgaJpZM4PfOia .
anyone here help me?
This thread is for a ESP32, not a 8266. Try a different repo.
can u help me please with 8226
@vseven how can i solve this problem?
@ijaz1122 look here if there is any issue that suits your problem. otherwise open a new one over there. you currently asking for a solution on a different device. this is the wrong repo for your problem.
Hey all finally I get this code working to connect and reconnect my wifi/portable hotspot multiple times
Thanks to @ThiagoCas for his codes
`/**** Include Libraries ****/
/**** Define Constants ****/
// constants won't change. Used here to set a pin number: const int ledPin = 2;// the number of the LED pin
/**** Define Variables ****/ // Variables will change: int ledState = LOW; // ledState used to set the LED
int interval = 100; // interval at which to blink (milliseconds)
// 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 LED was updated
/**** Auxiliar Functions ****/ void WIFI_Connect() { WiFi.disconnect(); Serial.println("Connecting to WiFi..."); WiFi.mode(WIFI_AP_STA); WiFi.begin(WIFISSID, PASSWORD);
for (int i = 0; i < 60; i++) { if ( WiFi.status() != WL_CONNECTED ) { delay ( 250 ); digitalWrite(ledPin, LOW); Serial.print ( "." ); delay ( 250 ); digitalWrite(ledPin, HIGH); } } if ( WiFi.status() == WL_CONNECTED ) { Serial.println(""); Serial.println("WiFi Connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } digitalWrite(ledPin, 0); }
/**** Main Functions ****/
void setup() { Serial.begin(115200);
// set the digital pin as output: pinMode(ledPin, OUTPUT); WIFI_Connect(); }
void loop() { unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) { if (WiFi.status() != WL_CONNECTED) { Serial.println("wifi disconnected "); WIFI_Connect(); } // save the last time you blinked the LED previousMillis = currentMillis; // if the LED is off turn it on and vice-versa: if (ledState == LOW) { ledState = HIGH; interval = 100; } else { ledState = LOW; interval = 2500; } // set the LED with the ledState of the variable: digitalWrite(ledPin, ledState); } }`
Newer firmware seems to help, gonna close this.
@vseven by newer firmware ... do you mean latest version from master of this library? I do not see new commits to master since Sep 26th so wonder if you are referring to something else.
Thanks for your clarification Gaston
I opened this over a year ago now so yes, newer as in the last couple months.
Great. Thanks for the clarification. I'm not sure when I updated last (2 months ago?) but I never saw this error after the last update (and it used to happen once every couple of months). I thought I was being lucky but I now see that it was more than luck. ;)
Great job. Gaston
Also this seems to help:
esp_wifi_set_ps(WIFI_PS_NONE);
@vseven
Newer firmware seems to help, gonna close this.
Hello there, I always thought platformio by updating the arduino-esp32 library was also able to update what you called the firmware. Am i wrong? I'm still suffering from this problem!
@vseven Newer firmware seems to help, gonna close this.
Hello there, I always thought platformio by updating the arduino-esp32 library was also able to update what you called the firmware. Am i wrong? I'm still suffering from this problem!
Same here. Would like to have a pointer to how to update firmware by platformio to get around the disconnect issue myself...
@vseven Platform IO setup instructions and update are addressed here https://github.com/espressif/arduino-esp32/blob/master/docs/platformio.md
a tid bit however: on both Arduino and Platform IO when i use git to update the SDK i have on some occasions found the update was not complete and had issues.
Rename the esp32 folder and re-install from a fresh git and i have always gotten a clean update.
Just follow their instructions.
@mickeypop: well, my platformio is on the latest stable version, but I still have the disconnect issue. Do you suggest using the stage or upstream versions instead? The stable was only updated a few days ago, by the way.
@Miq1 does this issue exist if only use IDF example?
I must confess that I am using the Arduino in Platformio environment only - I never dealt with the IDF. I will look into it today to see if I can set up a basic version of my application there.
Just for the records: I found that the workaround with disconnect() and subsequent begin() works for me if I do a mode(WIFI_OFF) and mode(WIFI_STA) in between. I am currently trying the reconnect 5 times in a row and would do an esp.restart() if all attempts failed, but so far no restart was necessary.
I observed a few restarts in the meantime, so the workaround seems not to be as effective.
Is there any update about this bug?
FWIW I see this often on ESP8266 units too - exact same symptoms. I've found I can change the connect quite drastically simply by orienting the unit differently - so it seems to be related to how the units (both ESP8266 and ESP32) respond to bad signal.
Given I am using NonOS and an ESP8266, the common denominator seems to be the low level networking below lwIP
(Using 1.0.4 version of Arduino-esp32)
I had the same problem here (using ESP32). Found that rebooting the router solves the problem... once. That is, after the reboot, the ESP32 is able to connect to the AP, get an IP address and stay connected, but if something causes the connection to fail (like rebooting the ESP32), the ESP32 then is never able to connect to the AP again.
The router is a TP-Link TL-MR2030 that I keep around for wired ethernet tests and has firmware that is hopelessly outdated by years and no newer official firmware exists.
However, if I try to use other APs, like some quite new Ubiquiti units at the office, the problem simply does not happen at all. I even raised some suspicion on the IT staff by forcing the board to purposely reboot and reconnect repeatedly as fast as possible for hours on end... and no trouble at all.
So, in the end, while it is possible that something is wrong or incomplete in the ESP32's libraries, I am ready to put all the blame on the old router's firmware. Time to get a new router for tests, not from TP-LINK, however.
I usually suspect dns for things like this. Or sometimes the router still thinks you are connected and never allows you to reconnect
No, the router is not to blame. At least in my case. Sure, it's not the newest (wnr2200) but with an up-to-date DD-WRT installed and several android, linux and windows devices working without issues.
To finally solve this issue for myself, I started over with a completely new implementation, based on WiFiClientEvents.ino - so it's event-based. I also read the newest commit messages of arduino-esp32 which revealed very recent but relevant commits. I had to do some debugging in WiFiGeneric.cpp and found that mode doesn't always do what's expected (https://github.com/espressif/arduino-esp32/issues/1306).
Final result: with a little patch on WiFiGeneric.cpp (see end of file), I was able to connect and disconnect several times to/from my AP - hurray :)
Let me know if you see something to improve.
/*
* This is a very stable example of repeated connecting and disconnecting to/from a wifi access point on STA32
* Unfortunately, it needs patching of the WiFiGeneric.cpp library file
* Author: Daniel Alder, based on the example WiFiClientEvents.ino
* Tested with Arduino 1.8.5 and 1.8.10 with ESP library from Nov 11 2019 (cec3fca4) + patch
*/
#include <WiFi.h>
#include "HomeWifiConfig.h" // use an extra include or uncomment the following 2 lines
//const char* ssid = "myssid"; // your network SSID (name of wifi network)
//const char* password = "****"; // your network password
typedef enum {
MYSTATE_OFFLINE = 0,
MYSTATE_CONNECTING,
MYSTATE_ONLINE,
MYSTATE_DISCONNECTING
} mystate_t;
mystate_t mystate = MYSTATE_OFFLINE;
long state_since = 0;
#define TIMEOUT_ONLINE 20 // reconnect after this [s] offline time
#define TIMEOUT_OFFLINE 20 // disconnect after this [s] online time
#define TIMEOUT_CONNECTING 20 // cancel connecting after this [s] without success
////////////////////////////////////////////////////////////////////////////////
long getUptime() {
return esp_timer_get_time() / 1000000L;
}
void changeState(mystate_t state) {
mystate = state;
state_since = getUptime();
}
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
{
Serial.printf("[WiFi-event] event: %d\n", event);
switch (event) {
case SYSTEM_EVENT_WIFI_READY:
Serial.println("WiFi interface ready");
break;
case SYSTEM_EVENT_SCAN_DONE:
Serial.println("Completed scan for access points");
break;
case SYSTEM_EVENT_STA_START:
Serial.println("WiFi client started");
break;
case SYSTEM_EVENT_STA_STOP:
Serial.println("WiFi client stopped");
changeState(MYSTATE_OFFLINE);
break;
case SYSTEM_EVENT_STA_CONNECTED:
Serial.println("Connected to access point");
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
Serial.println("Disconnected from WiFi access point");
break;
case SYSTEM_EVENT_STA_AUTHMODE_CHANGE:
Serial.println("Authentication mode of access point has changed");
break;
case SYSTEM_EVENT_STA_GOT_IP:
Serial.print("Obtained IP address: ");
//Serial.println(WiFi.localIP());
//Serial.println("WiFi connected");
//Serial.print("IP address: ");
Serial.println(IPAddress(info.got_ip.ip_info.ip.addr));
changeState(MYSTATE_ONLINE);
break;
case SYSTEM_EVENT_STA_LOST_IP:
Serial.println("Lost IP address and IP address is reset to 0");
//changeState(MYSTATE_OFFLINE);
break;
case SYSTEM_EVENT_STA_WPS_ER_SUCCESS:
Serial.println("WiFi Protected Setup (WPS): succeeded in enrollee mode");
break;
case SYSTEM_EVENT_STA_WPS_ER_FAILED:
Serial.println("WiFi Protected Setup (WPS): failed in enrollee mode");
break;
case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT:
Serial.println("WiFi Protected Setup (WPS): timeout in enrollee mode");
break;
case SYSTEM_EVENT_STA_WPS_ER_PIN:
Serial.println("WiFi Protected Setup (WPS): pin code in enrollee mode");
break;
case SYSTEM_EVENT_AP_START:
Serial.println("WiFi access point started");
break;
case SYSTEM_EVENT_AP_STOP:
Serial.println("WiFi access point stopped");
break;
case SYSTEM_EVENT_AP_STACONNECTED:
Serial.println("Client connected");
break;
case SYSTEM_EVENT_AP_STADISCONNECTED:
Serial.println("Client disconnected");
break;
case SYSTEM_EVENT_AP_STAIPASSIGNED:
Serial.println("Assigned IP address to client");
break;
case SYSTEM_EVENT_AP_PROBEREQRECVED:
Serial.println("Received probe request");
break;
case SYSTEM_EVENT_GOT_IP6:
Serial.println("IPv6 is preferred");
break;
case SYSTEM_EVENT_ETH_START:
Serial.println("Ethernet started");
break;
case SYSTEM_EVENT_ETH_STOP:
Serial.println("Ethernet stopped");
break;
case SYSTEM_EVENT_ETH_CONNECTED:
Serial.println("Ethernet connected");
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
Serial.println("Ethernet disconnected");
break;
case SYSTEM_EVENT_ETH_GOT_IP:
Serial.println("Obtained IP address");
break;
default: break;
}
}
#include "esp_wifi.h" // only for fixWifiPersistencyFlag()
/**
* Disable persistent mode, see https://github.com/espressif/arduino-esp32/issues/1393
*/
void fixWifiPersistencyFlag() {
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
Serial.printf("cfg.nvs_enable before: %d\n", cfg.nvs_enable);
cfg.nvs_enable = 0;
}
////////////////////////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(115200);
Serial.println("-----------------------------------------");
Serial.println("THIS IS: newWifiImplementationUsingEvents");
Serial.println("-----------------------------------------");
WiFi.persistent(false);
fixWifiPersistencyFlag();
//Serial.setDebugOutput(true);
//WiFi.printDiag(Serial);
// delete old config
WiFi.disconnect(true);
state_since = getUptime();
delay(1000);
// warning: only the last defined event handler gets events!
WiFi.onEvent(WiFiEvent);
Serial.println("End of setup");
}
bool firstTime = true;
void loop()
{
long uptime = getUptime();
if (mystate == MYSTATE_ONLINE && state_since + TIMEOUT_ONLINE < uptime) {
Serial.println("Disconnecting NOW");
changeState(MYSTATE_DISCONNECTING);
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
} else if (mystate == MYSTATE_OFFLINE && state_since+TIMEOUT_OFFLINE < uptime) {
Serial.println("Connecting NOW");
changeState(MYSTATE_CONNECTING);
if (firstTime) {
Serial.println("(firstTime)");
WiFi.begin(ssid, password);
firstTime = false;
} else {
// doesn't work without WiFiGeneric.cpp patch below
WiFi.mode(WIFI_STA);
WiFi.reconnect();
}
} else if (mystate == MYSTATE_CONNECTING && state_since+TIMEOUT_CONNECTING < uptime) {
Serial.println("Cancelling NOW after no connect success");
changeState(MYSTATE_DISCONNECTING);
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
}
delay(1000);
if (uptime % 10 == 0) {
Serial.printf("uptime %d\n", uptime);
}
}
/* PATH FOR LIBRARY
diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp
index e562921..aab5805 100644
--- a/libraries/WiFi/src/WiFiGeneric.cpp
+++ b/libraries/WiFi/src/WiFiGeneric.cpp
@@ -483,8 +483,10 @@ void WiFiGenericClass::enableLongRange(bool enable)
bool WiFiGenericClass::mode(wifi_mode_t m)
{
wifi_mode_t cm = getMode();
+ log_d("mode() cm=%d, m=%d", cm, m);
if(cm == m) {
- return true;
+ log_d("HACK: skip return true");
+ //return true;
}
if(!cm && m){
if(!wifiLowLevelInit(_persistent)){
*/
/* ISSUES:
*
* 1) The example WiFiClientEvents.ino says:
*
* WiFi.onEvent(WiFiEvent);
* WiFi.onEvent(WiFiGotIP, WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP);
*
* but the WiFiEvent function never receives a SYSTEM_EVENT_STA_GOT_IP!
*
* 2) I used code from https://github.com/espressif/arduino-esp32/issues/1393 to fix the persistent config issue
*
* 3) The list of events in WiFiClientEvents.ino (comment block) is missing an event. Same bug as fixed in 188560e7f33
*
* 4) Without pathing of WiFiGeneric.cpp, the mode() function doesn't do anything anymore once WiFi it was initialized (not even connected)
*
* see also: https://github.com/espressif/arduino-esp32/issues/1306 (but the this patch is not yet mentioned there)
*
* 5) just a note: there is a STA_LOST_IP event, 2 minutes after disconnecting.
* So if you want to make your code stable, you should also test with TIMEOUT_OFFLINE > 130
*/
Has anyone wiresharked this?
Had a similar issue with an arduino wifi rev 2 (different hardware, but issues negotiating between ap's and the device was eerily similar.)
@mrarmyant What do you expect to see using wireshark? I think we are talking about issues on OSI layers 1 and 2. Differently said: no SSID, no frequency, no packets
My code (above your post) runs stable since I posted it. But I don't think the problem is portable to something different than ESP* chips because it addresses issues of the ESP SDK, not Arduino
I blame issues like this on power supply
i wouldn't blame the PS, it's very unlikely unless you have a really weak supply this will not happen.
Wireshark is really useless here.
To understand you have to dig deep into the RTOS libraries where the real work is done, not the Arduino libs as they are a wrapper.
If you are using WiFi.reconnect() instead of WiFi.begin() you need to know a few things.
WiFi.begin() starts by setting all needed registers on the wifi chip and RTOS states before connecting, reconnect() does not. This was reported over 2 years ago.
WiFi.reconnect() often makes only half of the connection, establishing a chip level MAC connection with UDP but never making the TCP/IP connection as these are separate protocols. This is due to needed states not being preset by reconnect() it simply assumes they are there.
This is why some of you are not getting the SYSTEM_EVENT_STA_GOT_IP on reconnect.
Remember; reconnecting is needed because the states have already changed.
I ALWAYS reconnect with WiFi.begin() and have never failed.
======
as to a reset not connecting and saying there is already a connection you need to know DHCP.
DHCP IP address is commonly re-established every 15 seconds.
Now let's say 2 second after reestablishing you press the reset.
The DHCP server isn't going to release the IP for another 13 seconds and on trying to connect it will report it in use.
A simple delay on boot before connecting has fixed this for me every time.
If you are setting up multiple other libraries, set them all first before WiFi.begin().
A good start timer will help here.
take a long var = millis(); in the first line of setup() and Serial.print( millis()-var); just before WiFi.begin() and find out just how fast you are actually booting. Then adjust accordingly.
I have been using the ESP32 for over 6 years and this has always worked.
UPDATE; i see a lot of WiFiEvent used and for debugging its good but to simply detect wifi down and reconnect the IF/ELSE below works reliably every time.
this works because it takes about 18 seconds from down to reporting WL_CONNECTED change, this gives the DHCP server time to release the IP for a reliable re connect later.
It has been working for over 6 years and counting.
loop()
{
if ( WiFi.status() == WL_CONNECTED )
{
// WiFi is UP, do what ever
} else
{
// wifi down, reconnect here
WiFi.begin( );
int WLcount = 0;
while (WiFi.status() != WL_CONNECTED && WLcount < 200 )
{
delay( 100 );
Serial.printf(".");
if (UpCount >= 60) // just keep terminal from scrolling sideways
{
UpCount = 0;
Serial.printf("\n");
}
++UpCount;
++WLcount;
}
}
} // END loop()
take a look at the skeleton code i posted on https://github.com/espressif/arduino-esp32/issues/1100
though it was for setup with SmartConfig it just works.
@mrarmyant What do you expect to see using wireshark? I think we are talking about issues on OSI layers 1 and 2. Differently said: no SSID, no frequency, no packets
My code (above your post) runs stable since I posted it. But I don't think the problem is portable to something different than ESP* chips because it addresses issues of the ESP SDK, not Arduino
I wasn't referring really to arduino, but the wifi soc that is onboard that particular unit. It had issues with reconnect based on being hinky with dhcp. Someone reported that restarting their router fixed it, which is the problem we had (well restarting a windows dhcp server). There was an issue with the way it was acknowledging wether or not it had been disconnected. Just thought it might help with those issues up there, because neither unit would ever show as connected on the reconnects, and wireshark showed us why. Static IP's had no problem. It ended up being the wifi soc firmware that had to be fixed to handle the delay mentioned for DHCP issues. All of which were discovered via wireshark.
Board: ModeMCU ESP32 Dev Module Core Installation/update date: 15/Sep/2017 IDE name: Arduino IDE
It seems there is no auto reconnect logic allowing the ESP32 to reconnect when the connection drops or if there is its not working properly. I have had completely random results with my ESP32 board, sometimes its up for as little as 30 minutes and at most 18 - 20 hours. WiFi is dropping and doesn't want to reconnect.
The library I am using for WiFi is watching the WiFi event and on a disconnect its trying to reconnect which helps but sometimes it fails the reconnect and then that's it...I have to reboot. There is no sleep/low power mode at all involved and the device is constantly powered by 3.3v in. There was a case opened regarding this, https://github.com/espressif/arduino-esp32/issues/353, but its closed without any real answer (says auto connect is kind of implemented...not sure what that means).
I guess the question comes down to is auto reconnect implemented in the code itself, reliably, and if not what is the best Arduino code way of making sure it is connected?
-Allan