esp8266 / Arduino

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

ESP8266 MultiWifi run blocks the code execution, can it be run asynchronously? #8489

Open shrynshjn opened 2 years ago

shrynshjn commented 2 years ago

I am using ESP8266 for my project, in it a do multiple operations, some of them are dependent on wifi/internet and other are not. On the latest core sdk (3.0.2), the wifi multi.run() takes 7 seconds to execute, and this is happening synchronusly, which means my code loop is blocked for a good 7 seconds. I process data incoming on the serial but this 7 second block, causes me to loose some serial data too. Is there some way to run this asynchronously? I call wifimulti.run() at the start of my loop. so its executed in every loop. I have made it so, that the wifi loop is only called every one minute or so, but it still blocks my code loop for 7 seconds after that minute. Any help or guidance will be great.

Bighoneypot commented 2 years ago

Dear @shrynshjn Hi, because you always call the wifi. You have to call up the Wifi only if it is disconnected (always check the status of the wifi WiFI.Status ()) What type of ESP8266 are you using? I advise you to increase the cpu to 160 Mhz for a faster board speed. If your data arrives after the connection you have to save your data in the eeprom and then when you are connected to WiFi, you can send the saved data. Without having the code it is a bit difficult for me to understand what kind of operation you need to do. What kind of data are you reading? Where are you reading them from?

shrynshjn commented 2 years ago

Hello @Bighoneypot Thanks you for replying.

I'm getting some data over UART. As there is a limit on the amount of data that can be kept in the buffer, when there are multiple commands, it misses some.

I have to read the data on uart process and store in the flash.

Secondly this problem is happening only when not connected to the wifi. I do stop the wifi loop when it's connected. I guess the scan function takes up the time. When i tried to reduce the time, by passing the parameter into run. It was not connecting to the wifi .

The CPU frequency is already 160Mhz.

I hope this answers your questions. I'll make a small snippet of the code and share here too if that helps.

Thank you

shrynshjn commented 2 years ago
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266mDNSCustom.h>
#include <EEPROM.h>
#include <Base64.h>
#include <Arduino.h>
#include <WebSocketsClient.h> 
#include <SocketIOclient.h>

#ifdef DEBUG_ESP_PORT
#define DEBUG_MSG(...) DEBUG_ESP_PORT.printf( __VA_ARGS__ )
#else
#define DEBUG_MSG(...)
#endif

#define USE_SERIAL Serial
/**
 * the fallback wifi credentials, if the saved wifi credentials are not found,
 * esp tries to connect to defaultSSID and defaultPasswword
 * */
const static char* defaultSSID =  "defaultSSID";
const static char* defaultPassword = "defaultPass";

// wifi ssid and password
#pragma region
// the wifi ssid currently being used
char WIFI_SSID[32];
// the wifi password currently being used
char WIFI_PASSWD[64];
ESP8266WiFiMulti wifiMulti;
bool wifi_connected_once = false;
wl_status_t wifi_status;
#pragma endregion

#define SERIAL_DELAY 1
bool credentials_loaded = false;
unsigned long connected_at = 0;

WiFiClient client;

/**
 * sendCommand
*/
void sendCommand() {
  // send data on serial
}

void socketIOEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) {
  switch (type) {
    case sIOtype_DISCONNECT:

      break;

    case sIOtype_CONNECT:
      break;

    case sIOtype_EVENT:
      break;
    case sIOtype_ACK:
      // hexdump(payload, length);
      break;
    case sIOtype_ERROR:
      // hexdump(payload, length);
      break;
    case sIOtype_BINARY_EVENT:
      // hexdump(payload, length);
      break;
    case sIOtype_BINARY_ACK:
      // hexdump(payload, length);
      break;
  }
}

void load_credentials() {
 // load credentials into the wifi
}

bool newCommand = false;
void readCommands () {
  while (newCommand == false && Serial.available() > 0) {
    char rc = Serial.read();
    // read the incomming command
    // do some check and set new command to true for execution
    newCommand = true;
  }
}

void executeCommand() {
  if (newCommand == true) {
    // process the command do stugg
    newCommand = false;
  }
}
unsigned long now;

void wifiLoop() {
  wifi_status = wifiMulti.run();
  if (wifi_status != WL_CONNECTED) {
    if (wifi_connected_once) {
      ESP.reset();
    }
  } else {
    if (wifi_connected_once == false) {
      wifi_connected_once = true;
      // setup_mqtt_broker();
    }
  }
}

void setup() {
  Serial.begin(115200);
  while (!Serial) {};
  Serial.setDebugOutput(false);
  EEPROM.begin(60);
  // read data
  EEPROM.end();
  // set pins
  WiFi.mode(WIFI_STA);

  if (WiFi.getMode() & WIFI_AP) {
    WiFi.softAPdisconnect(true);
  }
  load_credentials();
  wifiMulti.addAP(defaultSSID, defaultPassword);
  WiFi.persistent(false);
  // websocket
}

void loop() {
  now = millis();
  wifiLoop(); // when offline this loop takes about 7s to execute
  readCommands(); // which means i am not able to read all thats happening over here
  executeCommand(); // and thus cant process it all on here
  // i also want to read some gpio pins, and those functions are timesensitive i cant afford a 7s delay
  if (wifi_status == WL_CONNECTED) {
    // webSocket.loop();
  }
}

Here is a stripped out code, for your reference

Bighoneypot commented 2 years ago

@shrynshjn Other info:

your type esp8266 board

how many characters does your wifi password have?

shrynshjn commented 2 years ago

Esp8266 nodemcu 12E

8 characters password 4 characters name. Again i believe the issue is related to the scaning time. Cause this happens when the device is not able to connect to the wifi.

Bighoneypot commented 2 years ago

@shrynshjn

try this: wifi_set_sleep_type(NONE_SLEEP_T);

shrynshjn commented 2 years ago

I am using this in the code already, the problem still persists.

Bighoneypot commented 2 years ago

@shrynshjn please, set a serial print millis when WiFi.status() == 3 and send me value

shrynshjn commented 2 years ago

You want me to time the status check call?

Bighoneypot commented 2 years ago

You want me to time the status check call?

Yes.

shrynshjn commented 2 years ago

[wifiStatus] start: 446026 [wifiStatus] end: 446027 [wifiStatus] took 1 ms to run

takes one ms to run.

I timed the run function too The run function used 7 seconds

Bighoneypot commented 2 years ago

I suggest you do a clean sketch where you just connect your board and measure the connection time again. Use simple WiFi.Begin();

shrynshjn commented 2 years ago

Okay let me give it try.

Bighoneypot commented 2 years ago

News?