WiFiNina "no socket available" on RP2040 Connect

Having looked at many posts and spending several days on this, I still have an issue.

I have a RP2040 Connect which I want to query a web server from time to time (this could be , say, 50 times a day). It will use a GET query to connect via WiFi to the server then diagnose the data returned by the server. This all works, however, for the purpose of testing I've cut my code down to just send the GET query and read the reply and ignore what's returned. I've run this in a loop with no added delays so I can emulate the long term traffic from the RP2040 Connect to my web server in a couple of days.

But it's stopping after a couple of hours with a "No Socket available" sent to the Serial output (note, I've seen in other posts that people have asked where this comes from - it's not something coded by me so must be coded in the WiFiNina library).

In order to analyse what's happening I decided to add a graph to the logged data on my web server. I count the number of connections to the server over a 300 second window and this is the results:

As can be seen, the speed drops off then dies for a while and starts up again. I'm guessing (though haven't witnessed) the board is crashing and rebooting.

I decided to update the WiFiNina firmware. I was using 1.4.5 as is the latest available on the IDE I'm using, but followed a simple idea to force the latest version (1.4.8) by copying the necessary file in place of the 1.4.5 version. However, the result was much worse:

I decided to revert to 1.4.5 again but still have the issue I had at the start.

After making the connection to the server and reading the data sent back I'm running, as suggested in a few posts:

while (client.available()) client.read();
client.stop();

So here are my questions:

  1. Can anyone think why the sockets aren't the sockets being released?
  2. Is there a way to force all sockets to be released?
  3. Is there a software way to reboot the RP2040 Connect (the methods used to reboot the Uno/Nano don't work)?
  4. Why can't the IDE check the latest firmware directory for the latest firmware?

My testing code:

#include <SPI.h>
#include <WiFiNINA.h>
#include <String.h>

#define RLA 9
char ssid[] = "NETY";        //  your network SSID (name)
char pass[] = "abcdefghi"; // your network password
String SerialNo = "123";
char* hostname = "AP_1";
char servername[] = "192.168.0.100";
String URLBase = "/go.php";


IPAddress dns1(8, 8, 8, 8);
IPAddress dns2(8, 8, 4, 4);
String MyIP;
int count = 0;
int status = WL_IDLE_STATUS;
String ret;
int ind1;
int ind2;
WiFiClient client;


/////////////////////////////////////////////////////////////
void setup() {
  Serial.begin(9600);
  Serial.println("Booting...");
  ConnectToWifi();
}


/////////////////////////////////////////////////////////////
void loop() {
  Serial.println();
  String MyURL = URLBase + "serial=" + SerialNo + "&code=boot&lan=" + MyIP + "&debug=1&info=COUNT:" + count;
  ReadWebPage(MyURL);
  //delay(10);
}


/////////////////////////////////////////////////////////////
void TestWiFiConnection() {
  int StatusWiFi = WiFi.status();
  if (StatusWiFi == WL_CONNECTION_LOST || StatusWiFi == WL_DISCONNECTED || StatusWiFi == WL_SCAN_COMPLETED) {
    Serial.println("WiFi connection not up!!");
    ConnectToWifi();
  }
}


/////////////////////////////////////////////////////////////
void ConnectToWifi() {
  WiFi.disconnect();
  WiFi.setHostname(hostname);
  status = WiFi.status();
  if (ScanSSIDs()) {
    while ( status != WL_CONNECTED) {
      Serial.print("Not connected, will try to connect to: "); Serial.println(ssid);
      status = WiFi.begin(ssid, pass);
      delay(500);
      if (status == WL_CONNECTED) {
        Serial.print("Connected to: "); Serial.println(ssid);
        WiFi.setDNS(dns1, dns2);
        printWifiData();
        printCurrentNet();
        MyIP = IPAddress2String(WiFi.localIP());
        Serial.println("Connected to WiFi (" + String(MyIP) + ")");
        String MyURL = URLBase + "serial=" + SerialNo + "&code=boot&lan=" + MyIP + "&info=WiFi_CONNECTED-COUNT=" + count;
        Serial.println(MyURL);
        ReadWebPage(MyURL);
      } else {
        delay(100);
      }
    }
  }
  count = 0;
}

/////////////////////////////////////////////////////////////
void ReadWebPage(String ToGet) {
  count++;
  Serial.print("COUNT: "); Serial.println(count);
  Serial.print("URL: "); Serial.println(ToGet);
  Serial.println("\nStarting connection...");
  if (client.connectSSL(servername, 443)) {
    Serial.print("Connected to: ");
    Serial.println(servername);
    client.print("GET ");
    client.print(ToGet);
    client.println(" HTTP/1.1");
    client.print("Host: ");
    client.println(servername);
    client.println("Connection: close");
    client.println();
    client.println();
    ret = "";
    char c;
    while (client.connected()) {
      while (client.available()) {
        c = client.read();
        ret += c;
      }
    }

    client.flush();
    Serial.println("Disconnecting...");
    while (client.available()) client.read();
    client.stop();
  } else {
    Serial.print("Countn't connect to: ");
    Serial.println(servername);
  }

  Serial.println(ret);
}




/////////////////////////////////////////////////////////////
char ScanSSIDs() {
  char score=0;
  Serial.print("Scanning SSID's, looking for: "); Serial.println(ssid);
  int numSsid = WiFi.scanNetworks();
  if (numSsid == -1) {
    Serial.println("No SSID's can be seen...");
    return (0);
  }
  for (int thisNet = 0; thisNet<numSsid; thisNet++) {
    if (strcmp(WiFi.SSID(thisNet),ssid)==0) {
      score=1;
      Serial.print("SSID found: "); Serial.println(ssid);
      return (score);
    }
  }
  Serial.print("SSID NOT found: "); Serial.println(ssid);
  return (score);
}


/////////////////////////////////////////////////////////////
void printWifiData() {
  IPAddress ip=WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  byte mac[6];
  WiFi.macAddress(mac);
  Serial.print("MAC address: ");
  printMacAddress(mac);
}

/////////////////////////////////////////////////////////////
void printCurrentNet() {
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  byte bssid[6];
  WiFi.BSSID(bssid);
  Serial.print("BSSID: ");
  printMacAddress(bssid);
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.println(rssi);
  byte encryption = WiFi.encryptionType();
  Serial.print("Encryption Type:");
  Serial.println(encryption, HEX);
  Serial.println();
}

/////////////////////////////////////////////////////////////
void printMacAddress(byte mac[]) {
  for (int i=5; i>=0; i--) {
    if (mac[i]<16) {
      Serial.print("0");
    }
    Serial.print(mac[i],HEX);
    if (i > 0) {
      Serial.print(":");
    }
  }
  Serial.println();
}

/////////////////////////////////////////////////////////////
String IPAddress2String(const IPAddress& ipAddress) {
  return String(ipAddress[0]) + String(".") + \
         String(ipAddress[1]) + String(".") + \
         String(ipAddress[2]) + String(".") + \
         String(ipAddress[3]);
}

I believe the most simple is to make this call:

NVIC_SystemReset();

The situation with the Arduino IDE and the NINA firmware updates is certainly not great. The firmware release frequency has greatly increased as Arduino IoT Cloud development demands additional functionalities from the connected boards. The release frequency of the classic Arduino IDE is nowhere near that of the firmware, meaning the previous strategy of distributing new firmware versions via the IDE releases is not effective.

Work is in progress to provide for this properly. There have been some very nice developments on the "Arduino Firmware Uploader" command line tool, one of which is to be able to download the full range of firmware versions, rather than being stuck with a fixed collection bundled with the tool. Even if you don't care for command line tools, this is still relevant because the GUI tools will use Arduino Firmware Uploader under the hood. It is already used in Arduino IoT Cloud and is in the process of being integrated into Arduino IDE 2.x's upcoming firmware upload capabilities:

As an interim measure, the range of firmware versions bundled with the classic Arduino IDE was updated earlier today and so you can now use the hourly build of the IDE to install the NINA firmware version 1.4.8:
https://www.arduino.cc/en/software#hourly-builds

This also means that the next production release of the classic IDE will have the latest firmware.

Excellent, I will try the reset function. It shouldn't be necessary but will suffice for what I’m doing.

As for the firmware library, I think rather than hard programming the latest version, a simple scan of the directories in C:\Program Files (x86)\Arduino\tools\WiFi101\tool\firmwares\NINA could then be used to generate the drop down list. This means for people to manually add a later version they simply drop the directory in place. This could also be used as a location for a tool to automatically download to. Just a simple idea to improve the flexibility of a brilliant IDE.

These are the main questions for which I'm seeking answers, if I can find a solution to either of these I won't need to do a reset on the board.

Having tested on my cut down software version, this works. It does introduce a 10 second delay, which will cause issues, though if I set it to only do it every 2500 iterations I can live with it.

So, after leaving my code running for about 5 days, the reset function seems to have helped. The reboot time is about 10s which I can live with. However, there seems to be an issue with the WiFi module.

  1. I still see outages that are lasting for an hour or so, this is not acceptable for what I'm trying to do. The outages are NOT an issue with the WiFi access point.

  1. The time between my loop processing slows down after each and every connection - this seems to be a case of the socket not being closed soI'm guessing finding the next available socket is taking longer with every connection attempt? Any thoughts?

  1. The update of firmware for the WiFi module made it worse - I get better results on v1.4.5 than I do on v1.4.8 and, in general, find the WiFi connections more stable on the earlier version.

A second Arduino Nano RP2040 Connect arrived yesterday. I updated the firmware and certificates on both, installed the same software, plugged them into a dual outlet phone charger and turned them on at the same time.

The server log of connections for each device:


As mentioned above, the devices are making a connection in the loop function and running continuously. The graph shows the number of connections in a 300 second window. Fluctuation is expected as the connection is over a network, but total blackouts are not expected and as can be seen they happened at different times so it's nothing to do with the WiFi access point, network or server.

Sadly the connection is dropping on both. It seems there is a bug or fault on these devices and it's starting to look like time to give up on them. Hopefully one day they will be more stable as they have fantastic (theoretical) features.

I can't believe I'm the only person seeing this problem...

I had a look at the library source code and agree it looks like a firmware issue. I saw an issue on Github. Was that posted by you under a different user name?

If you want to query a server 50 times a day why do you need the system to survive a test where you connect every second or so? While this might not be the ideal scenario, it sounds like you could easily restart the entire system before every connection.

Hi Klaus, thanks for confirming. Indeed the post on Github is (most likely) mine - I did do a similar style post on there.

I don't think this is relevant, though the only reason I speeded up the queries was to test reliability - why spend weeks or months testing at 50 per day? What I need is a board I can install and forget - so I don't want to have to go and physically turn the power off every few weeks to make sure it continues to work. I don't see the speed of my queries causing the issue, if so, then why? However, what is clear from my experiments is the speed of the queries slows down with each successful connection. It seems to me the firmware is looking for an available socket so if sockets aren't being closed/released it has to look for longer - just my guess.

I'm happy to do that and have indeed tried - if a connection fails a few times in a row I'm rebooting the RP2040, however, this doesn't (so it seems) restart the WiFi module. Do you know a way of restarting the WiFi module? I've looked but can't see.

The WiFi module has a reset line connected to the RP2040 pin D24 (see variant.cpp). The pin is also defined as NINA_RESETN in pins_arduino.h.

I did a short test with a BLE sketch. The pin is already set as output. With that you should be able to create a clean reset with:

digitalWrite( NINA_RESETN, LOW );  // Reset NINA module
delay( 10 );  // just making sure we get a clean pulse at the NINA_RESETN pin
NVIC_SystemReset();  // Reset RP2040

The NINA reset pin is automatically released when the RP2040 resets. It may be possible to write the sketch in a way that the RP2040 reset in not needed but this way ensures both the WiFi or BLE code on the RP2040 and the NINA module start clean.
If for some reason the pin is not an output you need to call pinMode( NINA_RESETN, OUTPUT ) first.

I just wanted to make sure you have a good reason. I agree with your method and observation. Because I do not know how many resources at Arduino are available to debug and fix issues like that, I thought a solution like the one I proposed above would be robust and better than waiting for a fix that may not come for some time.

Excelent, thanks for that. I've added the WiFi reset/delay to my code, cleared my log and kicked it off running. I am still seeing the response slowing down but I'm not worried about that as it's not significant enough to cause me a big problem.

If this works (I should know tomorrow) I will try just resetting the WiFi module (and return the pin to high). Not sure if I will have time to play tomorrow though but will hopefully get to post an update on the overnight testing.

Thanks again, this is (hopefully) the bodge I was looking for :slight_smile: