ARDUINO NANO 33 IoT BOARD ArduinoMqttClient RTCZero WiFiNINA

Hi Gang

I'm sending MQTT data periodically to a broker. I'm using the WiFiNina and ArduinoMqttClient Libraries to publish data and the RTCZero Library to put the ARDUINO NANO 33 IoT BOARD periodically into standby to conserve power.

If I simply use the RTCZero Library my Sketch works.

//TEST RTCZERO BY JWTFPV V1
#include <RTCZero.h>

bool staAla = false;
byte minAla = 0;

RTCZero rtcZer;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);

  rtcZer.begin();
  rtcZer.setDate(1, 1, 20);
  rtcZer.setTime(0, 0, 0);
  rtcZer.setAlarmMinutes(minAla);
  rtcZer.enableAlarm(rtcZer.MATCH_MMSS);
  rtcZer.attachInterrupt(isrAla);

  delay(10000);
}

void loop() {
  if (staAla) {
    staAla = false;

    minAla += 1;
    minAla %= 60;
    rtcZer.setAlarmMinutes(minAla);

    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);
    delay(1000);

    rtcZer.standbyMode();
  }
}

void isrAla() {
  staAla = true;
}

If I combine the ArduinoMqttClient, RTCZero & WiFiNina Libraries my Sketch doesn't work.

//TEST RTCZERO BY JWTFPV V2
#include <ArduinoMqttClient.h>
#include <RTCZero.h>
#include <SPI.h>
#include <WiFiNINA.h>

const char mqttBroker[] = "xxxxxx";
const char mqttPassword[] = "xxxxxx";
const char mqttUser[] = "xxxxxx";
const char topic0[]  = "xxxxxx";
const char wifiPassword[] = "xxxxxx";
const char wifiSSID[] = "xxxxxx";
const int mqttPort = xxxxxx;

bool staAla = false;
byte minAla = 0;

WiFiSSLClient wifiClient;
MqttClient mqttClient(wifiClient);
RTCZero rtcZer;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);

  rtcZer.begin();
  rtcZer.setDate(1, 1, 20);
  rtcZer.setTime(0, 0, 0);
  rtcZer.setAlarmMinutes(minAla);
  rtcZer.enableAlarm(rtcZer.MATCH_MMSS);
  rtcZer.attachInterrupt(isrAla);

  delay(10000);
}

void loop() {
  if (staAla) {
    digitalWrite(LED_BUILTIN, HIGH);

    staAla = false;

    minAla += 1;
    minAla %= 60;
    rtcZer.setAlarmMinutes(minAla);

    while (WiFi.begin(wifiSSID, wifiPassword) != WL_CONNECTED) delay(10000);

    mqttClient.setUsernamePassword(mqttUser, mqttPassword);
    if (!mqttClient.connect(mqttBroker, mqttPort)) while (1);

    mqttClient.poll();

    mqttClient.beginMessage(topic0);
    mqttClient.print(1);
    mqttClient.endMessage();

    WiFi.end();

    digitalWrite(LED_BUILTIN, LOW);

    rtcZer.standbyMode();
  }
}

void isrAla() {
  staAla = true;
}

If I use a simple 'BlinkWithoutDelay' approach along with putting the critical WiFi.begin and mqttClient.connect in void setup() my Sketch does work.

//TEST RTCZERO BY JWTFPV V3
#include <ArduinoMqttClient.h>
#include <SPI.h>
#include <WiFiNINA.h>

const char mqttBroker[] = "xxxxxx";
const char mqttPassword[] = "xxxxxx";
const char mqttUser[] = "xxxxxx";
const char topic0[]  = "xxxxxx";
const char wifiPassword[] = "xxxxxx";
const char wifiSSID[] = "xxxxxx";
const int mqttPort = xxxxxx;
const unsigned long milPer = 1 * 60 * 1000;

unsigned long milOld = 0;

WiFiSSLClient wifiClient;
MqttClient mqttClient(wifiClient);

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);

  while (WiFi.begin(wifiSSID, wifiPassword) != WL_CONNECTED) delay(10000);

  mqttClient.setUsernamePassword(mqttUser, mqttPassword);
  if (!mqttClient.connect(mqttBroker, mqttPort)) while (1);
}

void loop() {
  unsigned long milNew = millis();
  if (milPer <= milNew - milOld) {
    digitalWrite(LED_BUILTIN, HIGH);

    milOld = milNew;

    mqttClient.beginMessage(topic0);
    mqttClient.print(1);
    mqttClient.endMessage();

    digitalWrite(LED_BUILTIN, LOW);
  }

  mqttClient.poll();
}

The problem with this last approach is twofold.

  1. I'm unable to put the board into standby thus saving power.

  2. If I lose internet I will have to perform a manual reset.

I'm wondering if anyone could shed some light as to where I might be going wrong?

Cheers

Jase :slight_smile:

I guess "doesn't work" means the topic doesn't get a message.

Remove the while(1)! Do an error handling there.

Remove this line:

Check the return value of mqttClient.endMessage().

Call mqttClient.disconnect() before WiFi.end().

Call WiFi.disconnect() before WiFi.end() and check the return value.

Call WiFi.init() before WiFi.begin().

Post results.

Hi pylon

Thanks for getting back to me. I've made the changes you suggested.

I've changed the mqttClient.connect to retry connecting to the Broker if it fails.

while (!mqttClient.connect(mqttBroker, mqttPort)) delay(1000);

I've removed mqttClient.poll(). I assume given I'm Publishing very briefly it's not required?

I've tried adding the following line.

mqttClient.disconnect();

I get the following error.

'void MqttClient::disconnect()' is private within this context

I cannot see it used in the examples?

I've added the following line.

WiFi.disconnect();

I've tried adding the following line.

WiFi.init() ;

I get the following error.

'static void WiFiClass::init()' is private within this context

Again, I cannot see it used in the examples?

The code in full.

//TEST RTCZERO BY JWTFPV V2
#include <ArduinoMqttClient.h>
#include <RTCZero.h>
#include <SPI.h>
#include <WiFiNINA.h>

const char mqttBroker[] = "xxxxxx";
  const char mqttPassword[] = "xxxxxx";
  const char mqttUser[] = "xxxxxx";
  const char topic0[]  = "xxxxxx";
  const char wifiPassword[] = "xxxxxx";
  const char wifiSSID[] = "xxxxxx";
  const int mqttPort = xxxxxx;

bool staAla = false;
byte minAla = 0;

WiFiSSLClient wifiClient;
MqttClient mqttClient(wifiClient);
RTCZero rtcZer;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);

  rtcZer.begin();
  rtcZer.setDate(1, 1, 20);
  rtcZer.setTime(0, 0, 0);
  rtcZer.setAlarmMinutes(minAla);
  rtcZer.enableAlarm(rtcZer.MATCH_MMSS);
  rtcZer.attachInterrupt(isrAla);

  delay(10000);
}

void loop() {
  if (staAla) {
    digitalWrite(LED_BUILTIN, HIGH);

    staAla = false;

    minAla += 1;
    minAla %= 60;
    rtcZer.setAlarmMinutes(minAla);

    //WiFi.init();

    while (WiFi.begin(wifiSSID, wifiPassword) != WL_CONNECTED) delay(10000);

    mqttClient.setUsernamePassword(mqttUser, mqttPassword);
    while (!mqttClient.connect(mqttBroker, mqttPort)) delay(1000);

    mqttClient.beginMessage(topic0);
    mqttClient.print(1);
    mqttClient.endMessage();

    //mqttClient.disconnect();

    WiFi.disconnect();

    WiFi.end();

    digitalWrite(LED_BUILTIN, LOW);

    rtcZer.standbyMode();
  }
}

void isrAla() {
  staAla = true;
}

On a positive the code is executing every minute as the LED is flashing periodically. This suggests the code is not getting stuck anywhere.

I really appreciate your help.

Cheers

Jase :slight_smile:

My fault, replace it by the stop() method, that should be public and calls disconnect().

That definition is actually private although that doesn't make sense as it isn't called in the complete library and it does some stuff that seems to be important after sleeping.

I think I found a better solution, although I haven't found documentation for it. Replace the WiFi.init() by a call to WiFi.noLowPowerMode() and WiFi.end() by WiFi.lowPowerMode(). That's because without being able to call WiFi.init() you shouldn't call WiFi.end().

Hi pylon

Thanks for getting back to me. I'll make these changes and keep you updated. Much appreciated.

Cheers

Jase :slight_smile:

Hi pylon

Sorry for the late reply. I got a chance to implement the changes you suggested over the weekend. It works!

//TEST RTCZERO BY JWTFPV V3
#include <ArduinoMqttClient.h>
#include <RTCZero.h>
#include <SPI.h>
#include <WiFiNINA.h>

const char mqttBroker[] = "xxxxxx";
  const char mqttPassword[] = "xxxxxx";
  const char mqttUser[] = "xxxxxx";
  const char topic0[]  = "xxxxxx";
  const char wifiPassword[] = "xxxxxx";
  const char wifiSSID[] = "xxxxxx";
  const int mqttPort = xxxxxx;

bool staAla = false;
byte minAla = 0;

WiFiSSLClient wifiClient;
MqttClient mqttClient(wifiClient);
RTCZero rtcZer;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);

  rtcZer.begin();
  rtcZer.setDate(1, 1, 20);
  rtcZer.setTime(0, 0, 0);
  rtcZer.setAlarmMinutes(minAla);
  rtcZer.enableAlarm(rtcZer.MATCH_MMSS);
  rtcZer.attachInterrupt(isrAla);

  delay(10000);
}

void loop() {
  if (staAla) {
    digitalWrite(LED_BUILTIN, HIGH);

    staAla = false;

    minAla += 1;
    minAla %= 60;
    rtcZer.setAlarmMinutes(minAla);

    while (WiFi.begin(wifiSSID, wifiPassword) != WL_CONNECTED) delay(10000);

    mqttClient.setUsernamePassword(mqttUser, mqttPassword);
    while (!mqttClient.connect(mqttBroker, mqttPort)) delay(1000);

    mqttClient.beginMessage(topic0);
    mqttClient.print(1);
    mqttClient.endMessage();

    delay(1000);

    mqttClient.stop();

    WiFi.end();

    digitalWrite(LED_BUILTIN, LOW);

    rtcZer.standbyMode();
  }
}

void isrAla() {
  staAla = true;
}

The key seems to be starting the connection to the internet then broker.

    while (WiFi.begin(wifiSSID, wifiPassword) != WL_CONNECTED) delay(10000);

    mqttClient.setUsernamePassword(mqttUser, mqttPassword);
    while (!mqttClient.connect(mqttBroker, mqttPort)) delay(1000);

And to stop the connection to the broker followed by the internet.

    mqttClient.stop();

    WiFi.end();

These seem to be the slices of bread and the rest is meat in the sandwitch.

    mqttClient.beginMessage(topic0);
    mqttClient.print(1);
    mqttClient.endMessage();

Occasionally my data is not published. I'm not sure whether this is to do with shutting down the broker then internet immediately after publishing (hence the delay)? Alternatively is it because the data hasn't changed?

Regardless I wanted to say thanks for your help. It's much appreciated.

Cheers

Jase :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.