0

The board does reconnect from time to time, but there are times where it just disconnects and never reconnects again and I can't replicate the error because while I run it with Serial open and turn ON and OFF my WiFis it always reconnects as it should.

#include <ArduinoHttpClient.h>
#include <WiFiNINA.h>
#include <EmonLib.h>

EnergyMonitor emon1;
EnergyMonitor emon2;
EnergyMonitor emon3;
int INTERVAL = 60;
int last_code = 0;

char ssid[] = "MySSID";
char pass[] = "MyPW";

String ID = "Garden_Pump_Sensor";

int sequence = 0;
double kWh = 0.0;

char serverAddress[] = "192.168.1.108";  // server address
int port = 5005;

WiFiClient wifi;
HttpClient client = HttpClient(wifi, serverAddress, port);

int status = WL_IDLE_STATUS;

void setup() {
  Serial.begin(9600);
  analogReadResolution(9);
  emon1.current(0, 100);
  emon2.current(5, 100);
  emon3.current(6, 100);
  Connecting();
}

void Connecting() {
  int tries = 4;
  while ( (WiFi.status() != WL_CONNECTED && tries > 0) || last_code != 200) {
    Serial.print("Status #1: ");
    Serial.println(WiFi.status());
    WiFi.begin(ssid, pass);
    Serial.print("Status #2: ");
    Serial.println(WiFi.status());
    tries--;
    last_code = 200;
  }

  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
}

void reconnecting() {
  if (WiFi.status() != 3  || (WiFi.RSSI() <= -90) || (WiFi.RSSI() == 0) || last_code != 200) {
    WiFi.end();
    Connecting();
  }
}

void loop() {
  unsigned long delayTime = INTERVAL * 1000;
  unsigned long time_start = millis();

  DataMonitorAndSend();

  unsigned long time_final = millis() - time_start;
  unsigned long delay_value = delayTime - time_final;
  Serial.println(delay_value);
  if (delay_value < 1  || delay_value > delayTime) {
    return;
  } else {
    delay(delay_value);
  }

}

void DataMonitorAndSend() {
  reconnecting();

  Serial.println("making POST request");
  String contentType = "application/json";
  kWh = kWh + getKWH();
  String postData = "{\"ID\": \""+ID+"\",\"seq\": " + String(sequence) + ",\"kWh\": " + String(kWh, 6) + "}";
  Serial.print("data: ");
  Serial.println(postData);

  client.setHttpResponseTimeout(5 * 1000);
  client.post("/receivedata/", contentType, postData);

  // read the status code and body of the response
  int statusCode = client.responseStatusCode();
  String response = client.responseBody();

  Serial.print("Status code: ");
  Serial.println(statusCode);
  if (statusCode == 200) {
    kWh = 0;
    sequence++;
  }
  last_code = statusCode;
  Serial.print("Response: ");
  Serial.println(response);


}

double getKWH() {
  int LOOPS = 15;
  double kWh_Total = 0.0;
  unsigned long delayTime_kwh = 2 * 1000;
  for (int i = 0; i < LOOPS; i++) {
    unsigned long time_start_kwh = millis();

    double Irms1 = emon1.calcIrms(600);
    if (Irms1 < 0.3) Irms1 = 0;
    double Watt1 = (Irms1 * 230) / 1000;

    double Irms2 = emon2.calcIrms(600);
    if (Irms2 < 0.3) Irms2 = 0;
    double Watt2 = (Irms2 * 230) / 1000;

    double Irms3 = emon3.calcIrms(600);
    if (Irms3 < 0.3) Irms3 = 0;
    double Watt3 = (Irms3 * 230) / 1000;

    kWh_Total = kWh_Total + ((Watt1 + Watt2 + Watt3) / 60);

    unsigned long time_final_kwh = millis() - time_start_kwh;
    unsigned long delay_value_kwh = delayTime_kwh - time_final_kwh;
    if (delay_value_kwh < 0  || delay_value_kwh > delayTime_kwh) {
      delay(0);
    } else {
      delay(delay_value_kwh);
    }

  }

  return kWh_Total / LOOPS;
}

Feel free to ignore the getkWH(), it's code related to power consumption. Also the firmware is up to date and the server is using a static IP.

2
  • A quick answer (so take it for what it is worth): If using Windows, I have had different versions of Windows decide on their own a particular network was bad, stop communicating over it and not say a word about it. Switching to Linux the network problems all became clear and, finally, problems could be easily solved.
    – st2000
    Jul 4, 2019 at 12:51
  • Thank you, but for the server, I'm using a raspberry pi / raspbian OS running a simple Flask Server. I have actually this server for other projects and had no issues, I think the issue is that the mkr is not sending /hangs somewhere and not a case of the server not receiving since I sent requests from other sources into it and it works fine.
    – BryceSoker
    Jul 4, 2019 at 13:06

2 Answers 2

1

Since you only send a data every 60s, it is better to only establish a WiFi when you need it, AND only create an instance of HttpClient after that. That's means that it only creating the wifi and client instances when you need it instead of using a global instances. Here is a way I usually do for such an application that I modified based on your sketch, you could give it a try. Please noted that only the changes that I made are highlighted in my code snippet, please fill-in the rest of your code:

unsigned long INTERVAL = 60000;  // in milliseconds
unsigned long time_start = millis() + INTERVAL;    // noted that I changed this to a global variable and to unsigned long

// WiFiClient wifi;
// HttpClient client = HttpClient(wifi, serverAddress, port);

void Connecting() {
  WiFi.disconnect();
  WiFi.begin(ssid, pass);
  Serial.print("Connecting to ");
  Serial.print(ssid);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println(" Connected");

  // your code for printing localIP
}

void loop() {
  
  if (WiFi.status() != WL_CONNECTED)
    connecting();

  // send data when INTERVAL is reached
  if (millis() - time_start > INTERVAL) {
    DataMonitorAndSend();
    time_start = millis();
  }

  yield();

}

void DataMonitorAndSend() {
  // reconnecting();

  WiFiClient wifi;
  HttpClient client = HttpClient(wifi, serverAddress, port);

  // rest of your DataMinitorAndSend() code

  client.end();

}
0

I found that before using WiFi.begin() to re-connect, one needs to use WiFi.disconnect() first. At least that keeps my set-up reliably re-connecting, when its battery is empty or my router is out for a moment. Also, testing for WL_CONNECTED or 3 only means that one's set-up is connected to the router, but the router not necessarily yet to the internet; in case of a restart of the router after a power outage. On one of my routers, one has to wait 10 seconds, on another 18 seconds.

void connectToWLAN()
{
  // Check if the AirLift FeatherWing's WLAN module works
  if (WiFi.status() == WL_NO_MODULE)
  {
    Serial.println("Connection to AirLift FeatherWing WLAN module failed");

    // If not, indicate there is a WLAN module malfunction
    WiFi.setLEDs(0, 255, 0); // Red

    // And stop forever
    while (true);
  }

  // Return to loop() if already connected to the WLAN router
  if (WiFi.status() == WL_CONNECTED)
  {
    return;
  }

  Serial.println("Trying to connect to WLAN router");

  // Indicate there is no WLAN router connection just yet
  WiFi.setLEDs(192, 255, 0); // Yellow

  do
  {
    // Start connection to WLAN router and print a status value
    WiFi.disconnect();
    delay(1000);

    status = WiFi.begin(WLAN_SSID, WLAN_PASS);
    // WL_IDLE_STATUS     = 0
    // WL_NO_SSID_AVAIL   = 1
    // WL_SCAN_COMPLETED  = 2
    // WL_CONNECTED       = 3
    // WL_CONNECT_FAILED  = 4
    // WL_CONNECTION_LOST = 5
    // WL_DISCONNECTED    = 6
    Serial.println(WiFi.status());
    delay(10000);
  }
  while (status != WL_CONNECTED);

  Serial.println("Connection to WLAN router successful");

  // Indicate that the WLAN router connection was established
  WiFi.setLEDs(255, 0, 0); // Green

  // To better see the status indicating RGB LED's state
  delay(2000);
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.