Comms not working

This is an odd one that has left me confused and not sure what to do next.

I have two nano IoT 33 boards. They happily accept a sketch I have written. There are some 4 bit warnings on compile which I understand are not to worry me. I can see that the nano is doing it’s stuff through the Serial Monitor. There are some LEDs that signify status of some sensors they work. I have MQTT Explorer running and can see the MQTT communications just fine. This is all good.

Then I unplug USB from my laptop and plug into another USB power outlet. Power light on the board comes on. The LEDs fail to light. I have no MQTT communications from the board. I have checked the router and board makes no WiFi connection.

This is for both boards. I have updated the firmware and believe everything is up to date. Boards only work pugged into a PC?

Any ideas?

Hi @BubbNL. Please post your full sketch.

I'll provide instructions you can follow to do that:

  1. If you are using Arduino IDE, select Tools > Auto Format from the menus to ensure your code is nicely formatted.
  2. Click on the window that contains your sketch code.
  3. Press the Ctrl+A keyboard shortcut (Command+A for macOS users).
    This will select all the text.
  4. Press the Ctrl+C keyboard shortcut (Command+C for macOS users).
    This will copy the selected text to the clipboard.
  5. Open a reply here on this forum topic by clicking the "Reply" button.
  6. Click the <CODE/> icon on the post composer toolbar.
    This will add the forum's code block markup (```) to your reply to make sure the error messages are correctly formatted.
  7. Press the Ctrl+V keyboard shortcut (Command+V for macOS users).
    This will paste the copied code into the code block.
  8. Move the cursor outside of the code block markup before you add any additional text to your reply.
  9. Repeat the above process if your sketch has multiple tabs.
  10. Click the "Reply" button to publish the post.

When your code requires a library that's not included with the Arduino IDE please post a link to where you downloaded that library from, or if you installed it using Library Manager (Sketch > Include Library > Manage Libraries... in Arduino IDE or Libraries > Library Manager in Arduino Cloud Editor) then say so and state the full name of the library.

/*
This sketch brings together a number of sensors to inform the volume and in flow status of a water tank
This information is then conveyed locally via RAG LEDs and communicated wider via MQTT broker
*/

#include <Arduino_ConnectionHandler.h>  //connection handler library is used to check WiFi connection and reconnect
#include "secrets.h"                    //loads secrets.h file (note "" v <>)
#include <ArduinoMqttClient.h>          //MQTT library

WiFiConnectionHandler conMan(SECRET_SSID, SECRET_PASS);  //Arduino_ConnectionHandler.h declaring the login info
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

//variables
unsigned long now = 0;          //global - now is used for multiple timers
unsigned long volumeTimer = 0;  //volume - initiates the timer for the volume polling
unsigned long flowTimer = 0;    //flow - initiates the timer for the volume polling
unsigned long flowTime = 0;     //flow - calculated time over which the flowcounts are poled
int level = 0;                  //volume - for the non contact to report 1/0
volatile int count = 0;         //flow - counts the intrrupt events from the hall effect flow meter
int flowcount = 0;              //flow - takes the counts while the interrupt is disabled
float duration = 0;             //volume - TOF of ultrasound used to calculate "distance"
float distance = 0;             //volume - distance calculated from TOF used to calculate "Volume"
float Volume = 0;               //volume - "Volume" is returned from the "volume()" function
float Flow = 0;                 //flow - "Flow" is returned from the "flow()" function
long unsigned testTimer = 0;    //LED - timer for LED case test: in LED state machine
byte blink = 0;                 //LED - blink 1 / 0
long unsigned ledTimer = 0;     //LED - timer for LED state machine update
long unsigned mqttTimer = 0;    //comms - timer
long unsigned tempTimer = 0;    //temp - timer
double volt_NTC = 0;            //temp - voltage over NTC from voltage divider (V)
double current = 0;             //temp - curnet in the temp circuit (A)
double resit_NTC = 0;           //temp - value of resitance mesured for NTC (ohm)
double temp = 0;                //temp - measured temp (K)

//constants
const unsigned long volumePeriod = 10000;  //volume - interval between volume polling (ms)
const unsigned long flowPeriod = 10000;    //flow - interval between flow polling (ms)
const long unsigned testPeriod = 60000;    //LED - period between LED tests (ms)
const long unsigned startPeriod = 10000;   //LED - light LEDs while initial readings are taken (ms)
const long unsigned ledPeriod = 1000;      //LED - this is the LED refresh rate, impacts the case ?blink: & test: (ms)
const long unsigned mqttPeriod = 20000;    //comms - MQTT update cadence (ms)
const long unsigned tempPeriod = 20000;    //temp - cadence (ms)
const float volumeThreshold = 2.6;         //LED - red / amber threshold for ultrasound value (m^3)
const float flowThreshold = 10;            //LED - red / amber threshold for ultrasound value (l/h)
const char broker[] = "192.168.0.10";      //setup - broker IP address
int port = 1883;                           //setup - port to broker
const char topicFlow[] = "water/flow";     //comms - publishes to topic "water/flow"
const char topicVolume[] = "water/volume"; //comms - publishes to topic "water/level"
const char topictemp[] = "water/temp";     //comms - publishes to topic "water/temp"

//hardware
int levelPin = 3;   //Sets pin 3 to be 'int & levelPin'
int flowPin = 2;    //Sets pin 2 to be 'int & flowPin'  (which is interrupt 0)
int trigPin = 8;    //sets pin 8 to be 'int & trigPin'
int echoPin = 9;    //sets pin 8 to be 'int & echoPin'
int ledIndicators;  //State machine 'sort of hardware'
int ledGreen = 4;   //sets pin 4 to be green LED
int ledAmber = 5;   //sets pin 5 to be yellow LDE
int ledRed = 6;     //sets pin 6 to be red LDE

enum ledIndicators { test,
                     green,
                     amber,
                     red,
                     greenBlink,
                     amberBlink,
                     redBlink };

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);  //serial connection
  while (!Serial) {
  }

  setDebugMessageLevel(DBG_INFO);  //conMan - one of 5 levels of debug messages

  conMan.addCallback(NetworkConnectionEvent::CONNECTED, onNetworkConnect);        //conMan = callback notified of network connection events
  conMan.addCallback(NetworkConnectionEvent::DISCONNECTED, onNetworkDisconnect);  //conMan = callback notified of network connection events
  conMan.addCallback(NetworkConnectionEvent::ERROR, onNetworkError);              //conMan = callback notified of network connection events

  pinMode(trigPin, OUTPUT);                                      //sets trigPin (pin 8) to output
  pinMode(echoPin, INPUT_PULLUP);                                //sets echoPin (pin 9) to output
  pinMode(flowPin, INPUT);                                       //sets flowPin (pin 2) to input
  pinMode(ledGreen, OUTPUT);                                     //sets ledgreen (pin 4) to output
  pinMode(ledAmber, OUTPUT);                                     //sets ledamber (pin 5) to output
  pinMode(ledRed, OUTPUT);                                       //sets ledred (pin 6) to output
  attachInterrupt(digitalPinToInterrupt(2), FlowCount, RISING);  //configures interrupt 0 (apparently pin 2 on nano / uno?) to run function 'FlowCount' on a rising pulse
}

void loop() {
  volume();
  flow();
  LEDs();
  temperature();
  Comms();
}


/*
*uses LEDs (RAG) to indicate:
*remaining volume, above and below two thresholds
*if water flow has fallen below a threshold
*/

void LEDs() {
  now = millis();
  if ((now - ledTimer) >= ledPeriod) {
    //green
    if ((level == 1) && (Flow >= flowThreshold)) {
      ledIndicators = green;
    }
    //amber
    if ((level == 0) && (Volume >= volumeThreshold) && (Flow >= flowThreshold)) {
      ledIndicators = amber;
    }
    //red
    if ((level == 0) && (Volume < volumeThreshold) && (Flow >= flowThreshold)) {
      ledIndicators = red;
    }
    //green blink
    if ((level == 1) && (Flow < flowThreshold)) {
      ledIndicators = greenBlink;
    }
    //amber blink
    if ((level == 0) && (Volume >= volumeThreshold) && (Flow < flowThreshold)) {
      ledIndicators = amberBlink;
    }
    //red blink
    if ((level == 0) && (Volume < volumeThreshold) && (Flow < flowThreshold)) {
      ledIndicators = redBlink;
    }
    //test
    if ((now - testTimer) >= testPeriod) {
      testTimer = now;
      ledIndicators = test;
    }
    //start
    if (now < startPeriod) {
      ledIndicators = test;
    }

    switch (ledIndicators) {

      case test:  //turns all LEDs on for ledPeriod after testPeriod
        digitalWrite(ledGreen, HIGH);
        digitalWrite(ledAmber, HIGH);
        digitalWrite(ledRed, HIGH);
        break;

      case green:  //full with flow
        gr();
        break;

      case amber:  //half full with flow
        am();
        break;

      case red:  //empty with flow
        re();
        break;

      case greenBlink:  //full with no flow
        gr();
        bl();
        break;

      case amberBlink:  //half full with no flow
        am();
        bl();
        break;

      case redBlink:  //half full with no flow
        re();
        bl();
        break;
    }
    ledTimer = now;
  }
}

void gr() {
  digitalWrite(ledGreen, HIGH);
  digitalWrite(ledAmber, LOW);
  digitalWrite(ledRed, LOW);
}
void am() {
  digitalWrite(ledGreen, LOW);
  digitalWrite(ledAmber, HIGH);
  digitalWrite(ledRed, LOW);
}
void re() {
  digitalWrite(ledGreen, LOW);
  digitalWrite(ledAmber, LOW);
  digitalWrite(ledRed, HIGH);
}
void bl() {
  if (blink == 0) {
    digitalWrite(ledRed, HIGH);
    blink = 1;
    //Serial.println("High");
  } else {
    if (blink == 1) {
      digitalWrite(ledRed, LOW);
      blink = 0;
      //Serial.println("Low");
    }
  }
}


/*
 * checks WiFi connection and reconnects if it has dropped 
 * maintains the mqtt broker connection
 * sends packets to the mqtt broker
 */

void Comms() {

/*
* call poll() regularly to allow the library to send MQTT 'keep alive' which avoids being disconnected by the broker
* this is very frequent and probablly wants a timer on this.  need to look at the MQTT documentation and see how frequent a connection / pole needs to be?
*/
  mqttClient.poll();  

  now = millis();
  if ((now - mqttTimer) >= mqttPeriod) {
    mqttTimer = now;

    //WiFi connection check reconnecting if connection is lost ConnectionHandler then connects to MQTT broker
    conMan.check();
    Serial.print("Checking WiFi connection ");
    //MQTT connection
    Serial.print("Attempting to connect to the MQTT broker: ");
    Serial.println(broker);
    if (!mqttClient.connect(broker, port)) {
      Serial.print("MQTT connection failed! Error code = ");
      Serial.println(mqttClient.connectError());
    }

    Serial.println("You're connected to the MQTT broker!");
    //'Flow' serial.print & MQTT update
    Serial.print("Sending message to topic: ");
    Serial.print("water/flow ");
    Serial.println(Flow);
    mqttClient.beginMessage(topicFlow);
    mqttClient.print(Flow);
    mqttClient.endMessage();
    //'Volume' serial.print & MQTT update
    Serial.print("Sending message to topic: ");
    Serial.print("water/volume ");
    Serial.println(Volume);
    mqttClient.beginMessage(topicVolume);
    mqttClient.print(Volume);
    mqttClient.endMessage();
    //'Temperature' serial.print & MQTT update
    Serial.print("Sending message to topic: ");
    Serial.print("water/temp ");
    Serial.println(temp);
    mqttClient.beginMessage(topictemp);
    mqttClient.print(temp);
    mqttClient.endMessage();

  }
}

//invokes the ConnectionHandler library
void onNetworkConnect() {
  Serial.println(">>>> CONNECTED to network");
}
//invokes the ConnectionHandler library
void onNetworkDisconnect() {
  Serial.println(">>>> DISCONNECTED from network");
}
//invokes the ConnectionHandler library
void onNetworkError() {
  Serial.println(">>>> ERROR");
}


/*
*measures flow of water into the tank using a pulse meter.
*/

void FlowCount() {
  count++;  //increments count, called in the attachInterrupt()
}

void flow() {  //calculates the flow of water to the tank
  now = millis();
  if (now - flowTimer >= flowPeriod) {
    int localCount = 0;  //local counter for this function only used in calculation
    noInterrupts();      //disable interrupts
    localCount = count;  //takes the volatile count and stored it in the localcount
    count = 0;           //resets the counter
    interrupts();        //enable interrupts
    //calculation
    Serial.print("number of puleses = ");
    Serial.println(localCount);
    flowTime = ((now - flowTimer) / 1000);  //calculated period pulses were measured (s)
    Serial.print("time over which flow is measured = ");
    Serial.print(flowTime);
    Serial.println(" s");
    Flow = ((localCount * 3600) / (flowTime * 23));  //l/h, the odd structure of the equation maintains integer values whilst processing
    Serial.print("flow = ");
    Serial.print(Flow);
    Serial.println(" l/h");
    flowTimer = now;
  }
}


/*
*using initally a non contact sensor and if 1/0 == 0 then a ultrasonic sensor to determin the level of the water in the tank
*then calculates the volume of the water remaining in the tank
*/

void volume() {  //calculates the volume of water in the tank
  now = millis();
  if ((now - volumeTimer) >= volumePeriod) {  //timer for volume poll
    volumeTimer = now;                        //updates levelPrevMillis
    level = digitalRead(3);                   //updates fullLevel variable with sensor reading
    Serial.print("water level = ");
    Serial.println(level);

    if (level == 1) {
      Volume = 3.6;
    }

    if (level == 0) {                     //"level == 0" this section of code has delays as they are necessary in-order to mesure the US signal
      digitalWrite(trigPin, LOW);         //sets trigger pin is LOW double check
      delayMicroseconds(2);               //waits
      digitalWrite(trigPin, HIGH);        //sets trigger pin HIGH starts US ping
      delayMicroseconds(20);              //waits, there is some question as to how long
      digitalWrite(trigPin, LOW);         //sets trigger pin LOW
      duration = pulseIn(echoPin, HIGH);  //sets duration as TOF
      distance = duration * 0.34 / 2;     //calculates distance from TOF
      Serial.print("TOF = ");
      Serial.println(duration);
      Serial.print("Distance = ");
      Serial.print(distance);
      Serial.println(" mm");
      Volume = ((1700 - distance) * 2.27 / 1000);  //needs equation for volume
    }
    Serial.print("water remaining ");
    Serial.print(Volume);
    Serial.println(" m3");
  }
}


/*
*Tmepartature of the tank side / water in tank.  Measured using a 10k 1 % b = 3950 (W1209 W1401) NTC
*/

void temperature() {
  now = millis();
  if (now - tempTimer >= tempPeriod) {

//check which analoug port is being used on the Nano iot33

    volt_NTC = 5.0/1023 * analogRead(A0);
    current = (5.0 - volt_NTC) / 10000.0;
    resit_NTC = volt_NTC / current;
    temp = (1 / (log(resit_NTC / 10000.0) / 3950.0 + 1 / (25.0 + 273.15)));
    Serial.print("temperature = ");
    Serial.println(temp);
    tempTimer = now;
  }
}

Thanks, I have posted the sketch above. This produces a few 4 bit warning messages. I understand that these are not actually and issue. I have a reduced (no NTC sensor) which loses the line with the log() function which produces the warnings this behaves in the same way. This is V 2.0 there were many V 1.?s and and and early one did work way back.

On boards with native USB this will block till a communication channel is opened. E.g. serial monitor.

If you remove it the code will behave ad expected.

cool I will try that.

Not sorted out :frowning:

[ed] I think I jumped the gun with this statement: “Brilliant it now works on a plain USB supply I will go and plug the sensors in in a bit… A trip into the field.”

The sketch certainly runs more than it did, in that the sensors (all be it not connected) are being read, values calculated and LEDs displaying appropriately. However, WiFi appears to be down. The while (!Serial) {} is part of the Arduino_ConnectionHandler. The script I have used is from the “How-to-use” part of the ReadMe file for that library. Both boards are now on power only USB one is attached to sensors. Neither are connecting to WiFi. I will try the conman on it’s own. In testing the boards were only ever connected to a PC / monitor so I have not seen this before.

I’ve been reviewing the ‘conman’ library examples etc. It looks patent that I have not fully understood the implementation and I will go back to the sketch. I think that my concatenating WiFi handling and mqtt was not a good thing to do and I will tease that function apart into two separate functions. As to why the sketch works whilst plugged into a PC/monitor and not when simply powered???

This is often an indicator that the stand-alone power arrangement is inadequate; USB is powering your circuit when plugged in, but when stand alone, the supply must meet certain criteria.

Hi, I asked chatGPT and checked;

If you power the Nano 33 IoT and enable WiFi, with moderate data transmissions, you might see something on the order of ~ 80–120 mA (3.3 V supply) during “active WiFi use” — but that’s a rough, ballpark guess based on anecdotal evidence.

If you want a firmer figure, the only reliable way is to hook up a good-quality ammeter or current monitor to the 3.3 V rail (or VIN/USB input) and measure the board while you run your actual code including WiFi transmit bursts. That’ll catch regulator inefficiencies, load from the CPU and peripherals, and the real-world transmit power and duty cycle you’re using.

The last paragraph says it all, MEASURE the current consumption and measure the voltage of your power supply when you have WiFi activated.
WiFi is quite active during setup as it attempts a connection.

Tom.... :smiley: :+1: :coffee: :australia:
PS. I'm training my chatGPT (Max), and he is learning!

I think I was coming to this conclusion too. I was using USB A outlets from UK mains sockets then I tried an Amazon echo power supply, no idea what Amp either is off the top of my head . I have quite a few sensors running which will draw. I currently have the spare board running a simple sketch with a value being published to mqtt broker. That has worked ok all night. The board in the field started displaying the amber LED and the flashing red went off (there is no pulse meter connected to that is a false reading. I restarted the system this morning and it went back to flashing red with constant amber… However… BIG however, the WiFi connected. I’m now getting mqtt from that board. I need to review the sensor set up as I get around to trailing the pulse meter wire out of the meter chamber. But with another sensor up goes the power draw. I think I will need to use a bigger Amp supply.

I’m still going to separate the conman and mqtt functions so I can follow them better.


Update: The power issue may have been down to a not so good USB cable connection. Now on to other issues but this is resolved.