arduino-libraries / WiFiNINA

139 stars 105 forks source link

Non blocking WiFi.begin() & Client.connect() #273

Open tech9492 opened 8 months ago

tech9492 commented 8 months ago

Hi all,

Below is the code operating on an Arduino RP2040 Nano Connect. I am facing an issue with WiFi/MQTT reconnection portion of my code. When WiFi and MQTT are connected, the code functions as expected. In the event that one is missing, it obstruct void loop().

I am guessing WiFi.begin() and Client.connect() are both blocking. Is there any workaround I can apply?

Thank you.

#include <SPI.h>
#include <WiFiNINA.h>
#include <ArduinoMqttClient.h>
#include "arduino_secrets.h"

const int PSON = A3;
const int SSR = 8;
const int FAN = 6;

unsigned long ssrTimer = 0;  // SSR timer
unsigned long fanTimer = 0;  // Fan timer

int psState = 0;   // PSON status
int ssState = 0;   // SSR status
int fnState = 0;   // FAN status

//Enter data in secret tab(arduino_secrets.h)
char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

const char broker[] = "10.0.0.2";
int port = 1883;
const char topic[] = "RP2040Nano/PSon";
const char topic2[] = "RP2040Nano/SSR";
const char topic3[] = "RP2040Nano/FAN";

void setup() {
  pinMode(PSON, INPUT);  // analog pin A3 as input
  pinMode(SSR, OUTPUT);  // digital pin 8 as output
  pinMode(FAN, OUTPUT);  // digital pin 6 as output

  digitalWrite(SSR, LOW);
  digitalWrite(FAN, LOW);

  // Attempt to connect to WiFi network:
  WiFi.begin(ssid, pass);

  mqttClient.setKeepAliveInterval(0);
  // Username and Password for MQTT authentication
  mqttClient.setUsernamePassword(SECRET_MQTT_USER, SECRET_MQTT_PASS);
  mqttClient.connect(broker, port);
}

void loop() {
  psState = analogRead(PSON);  // read analog input status
  ssState = digitalRead(SSR);  // read digital output status
  fnState = digitalRead(FAN);  // read digital output status

  // call poll() regularly to allow the library to send MQTT and prevent disconnection by the broker
  mqttClient.poll();

  if (psState > 50) {
    ssrTimer = 100;  // delay SSR for 10 seconds
  }

  psOFF();

  if (ssState == 1) {
    fanTimer = 100;  // delay Fan for 10 seconds
  }

  fnOFF();

  if (WiFi.status() != WL_CONNECTED) {
    WiFi.end();
    WiFi.begin(ssid, pass);
  }

  if (WiFi.status() == WL_CONNECTED && !mqttClient.connected()) {
    mqttClient.stop();
    mqttClient.connect(broker, port);
  }

  if (WiFi.status() == WL_CONNECTED && mqttClient.connected()) {
    tele();
  }
}

void psOFF() {
  static unsigned long sspreviousTime;
  unsigned long sscurrentTime = millis();  // return time since board active

  // move forward if 100 ms has elapsed
  if (sscurrentTime - sspreviousTime < 100) {
    return;
  }

  sspreviousTime = sscurrentTime;

  if (!ssrTimer) {
    digitalWrite(SSR, LOW);  // if timer is done or still 0, set digital output LOW
  } else {
    digitalWrite(SSR, HIGH);  // set digital output HIGH
    digitalWrite(FAN, HIGH);  // set ditigal output HIGH
    ssrTimer--;
  }
}

void fnOFF() {
  static unsigned long fnpreviousTime;
  unsigned long fncurrentTime = millis();  // return time since board active

  // move forward if 100 ms has elapsed
  if (fncurrentTime - fnpreviousTime < 100) {
    return;
  }

  fnpreviousTime = fncurrentTime;

  if (!fanTimer) {
    digitalWrite(FAN, LOW);  // if timer is done or still 0, set digital output LOW
  } else {
    digitalWrite(FAN, HIGH);  // set digital output HIGH
    fanTimer--;
  }
}

void tele() {
  static unsigned long previousMillis;
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= 10000) {

    previousMillis = currentMillis;

    // send message, the Print interface can be used to set the message contents
    mqttClient.beginMessage(topic);
    mqttClient.print(psState);
    mqttClient.endMessage();

    mqttClient.beginMessage(topic2);
    mqttClient.print(ssState);
    mqttClient.endMessage();

    mqttClient.beginMessage(topic3);
    mqttClient.print(fnState);
    mqttClient.endMessage();

    mqttClient.beginMessage(topic4);
    mqttClient.print(temp_deg);
    mqttClient.endMessage();
  }
}
JAndrassy commented 8 months ago

https://github.com/arduino-libraries/WiFiNINA/pull/252

tech9492 commented 8 months ago

@JAndrassy thank you very much for your quick response. I did come across #252 but was not sure if that was the solution.

Regarding WiFi.begin(), would WiFi.setTimeout() be the solution?

Thank you.

JAndrassy commented 8 months ago

Regarding WiFi.begin(), would WiFi.setTimeout() be the solution?

what can your sketch do without WiFi connected to AP?

as first remove the useless wait time in WiFiClient.connect. this

while (!connected() && millis() - start < 10000)
            delay(1);

it jus wastes 10 seconds if the connection ended with timeout in firmware

tech9492 commented 8 months ago

what can your sketch do without WiFi connected to AP?

It reads the value of input pin A3 and controls 2 pins(output). When pin A3 is LOW, it will activate a timer to switch outputs LOW. This portion of the code should be able to execute even without WiFi.

JAndrassy commented 8 months ago

you can do 3 things with WiFi.begin: 1) don't try to connect every loop 2) run wifi scan before attempting to connect

maybe you can control the pins with MCU events/timers/interrupts so that they are independent from loop

tech9492 commented 8 months ago

you can do 3 things with WiFi.begin:

  1. don't try to connect every loop
  2. run wifi scan before attempting to connect

Thank you for the suggestions. Wifi scan before connecting seem to be a good workaround.

Regarding Client.connect(), I applied all the required changes from #252 to my WiFiNINA library. I tried a timeout of 1000(1 second), it does not solve the issue.

Thank you.

JAndrassy commented 8 months ago

applied all the required changes from https://github.com/arduino-libraries/WiFiNINA/pull/252 to my WiFiNINA library

the firmware too?

tech9492 commented 8 months ago

By firmware, do you mean server_drv.h?

I have modified the 4 files listed in #252. Did I miss something?

JAndrassy commented 8 months ago

there are changes in the nina-fw for the NINA Esp32 module as linked in the description of the PR

tech9492 commented 8 months ago

there are changes in the nina-fw for the NINA Esp32 module as linked in the description of the PR

Just to confirm, is it Client connect timeout support #89?

JAndrassy commented 8 months ago

Just to confirm, is it https://github.com/arduino/nina-fw/pull/89?

yes that is the PR for the firmware

tech9492 commented 8 months ago

I am a little lost now.

Where are firmware files located? Could you please guide me how to carry out this procedure.

Thank you.

JAndrassy commented 8 months ago

Where are firmware files located?

in the repository with the PR of course

https://github.com/arduino/nina-fw/blob/master/README.md