When my nano eSP32-based Thing connects to WiFi, the number of loops per second decreases dramatically, from ca. 45,000 loops/sec to ca. 4,200. You can see that here:
More importantly, when it connects to the Arduino Cloud, there is a temporary hiccup of maybe three quarters of a second. This is not a problem at the start, but it is a big problem later, and this "drop cloud connection and reconnect" happens regularly - maybe on average every ten minutes. This is a showstopper in this circuit, because the circuit is an LED message scroller, and the scrolling totally stops during this time. See it here:
This circuit does not yet have any shared variables so presumably all it is telling the Cloud is "I am here"?
So my questions, and yes I have googled all over the place...:
Is there any reason the disconnect/reconnect happens regularly?
Or is there a way to NOT have the code halt while this happens?
The ArduinoCloud.update(); at the beginning of every loop: would it not be better if I did that, say, a few times a second, in a non time critical Thing? What is the Best Practice? I am still not quite clear on that.
Yes, helpful. An yes, that conversation was similar but not the same (and probably in the wrong forum).
I will do the "every second" update, although that will generate more traffic. Remember, the circuit I describe able does not yet have any cloud variables, so we are increasing the update frequency from zero to a lot.
And re the halt when it disconnects/connects: will doing the cloud update() time less frequently cause an improvement here? Is it only during these cloud update() events that it checks whether it is still connected? I'll try that tonight.
As for using millis(): I think that is a good idea, so that is why am asking if there is a Best Practice from Arduino's end. Would you prefer connects every second? Every 100 ms? Every 2 seconds? Etc? (If there is no preference I'll do it the way it suits me, probably no more than 10x/second).
So 10 ms between updates (or even slower) is fine. As is the rest.
But the frequent disconnect/reconnects to Arduino Cloud still happen regularly, at the same frequency. This leads me to suspect perhaps it is the Cloud end that is the issue?
I do not care of it disconnects/reconnects, but I DO care off the scroller pauses while this happens. That is a showstopper. So... any suggestions?
Thanks for any thoughts you may have. Important enough, because this means I can't use The Cloud for anything that is pretty much real time, like a text scroller...
/*=====================================================================
MINI PROJECT BY MICHAEL WILLEMS (michael@willems.ca)
Connected LED Message Scroller 32 x 8
DATE: 3 Nov 2023
VERSION: 0.1 Added IoT Cloud,
Modified code for Arduino ESP32.
=====================================================================*/
/*-----------------------------------------------------------------------
I. INCLUDES, DEFINITIONS ETC:
-----------------------------------------------------------------------*/
/*
Sketch generated by the Arduino IoT Cloud Thing "Untitled"
https://create.arduino.cc/cloud/things/8d9216ef-39aa-410c-9062-544bc032b28d
Arduino IoT Cloud Variables description
The following variables are automatically generated and updated when changes are made to the Thing
- No variables have been created, add cloud variables on the Thing Setup page
to see them declared here
Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
which are called when their values are changed from the Dashboard.
These functions are generated with the Thing and added at the end of this sketch.
*/
// For Arduino Cloud:
#include "thingProperties.h"
// The Rest:
#include <EEPROM.h> //for storing message nr.
// Include all the scrolling LED display stuff:
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// Define hardware type, size, and output pins:
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 3
// Create a new instance of the MD_Parola class with hardware SPI connection:
MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
int button=7; // for selecting future functions
long buttonTimer = 0; // to see how long the button has been pressed
boolean buttonActive = false; // to set if the button is currently pressed
long longPressTime = 500; // 500 - how long to push button before clock enters SET mode?
boolean longPressActive = false;
char *ScrollMsg[] = {"Passport Photos $20", "Film Developing", "Photo Restoration", "Photo Printing", "Portraits"};
byte messageNumber; //what message to display from above array
int brightnessValue; // pot setting for brightness
int ldrvalue; // reading the LDR
unsigned long oneseccounter; // to flash the heartbeat LED *2*x/sec
unsigned long cloudupdatecounter;
int heartbeatled = 10;
unsigned long loopcount; // to count the loops per second
/*-----------------------------------------------------------------------
II. THE SETUP: (executes once)
-----------------------------------------------------------------------*/
void setup() {
// Initialize serial and wait for port to open:
Serial.begin(9600);
// Delay allows wait for a Serial Monitor without blocking if none is found
delay(1500);
// Defined in thingProperties.h
initProperties();
// Connect to Arduino IoT Cloud
ArduinoCloud.begin(ArduinoIoTPreferredConnection);
/*
The following function allows you to obtain more information
related to the state of network and IoT Cloud connection and errors
the higher number the more granular information you’ll get.
The default is 0 (only errors).
Maximum is 4
*/
setDebugMessageLevel(2);
ArduinoCloud.printDebugInfo();
// Now my stuff:
// Allocate EEPROM memory:
EEPROM.begin(256);
delay(500);
// Intialize the object:
myDisplay.begin();
// Set the intensity (brightness) of the display (0-15):
brightnessValue = map(analogRead(A0),400,3500,10,0); // pot setting for brightness
myDisplay.setIntensity(brightnessValue);
//myDisplay.setIntensity(3); //TEST
// Clear the display:
myDisplay.displayClear();
// Display the message:
messageNumber = EEPROM.read(0);
if (messageNumber > 4) {messageNumber == 0;}
myDisplay.displayText(ScrollMsg[messageNumber], PA_CENTER, 55, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT); // was 65
// Misc:
pinMode(heartbeatled, OUTPUT);
pinMode(button,INPUT_PULLUP);
oneseccounter = millis();
cloudupdatecounter = millis();
loopcount = 0;
} // end of setup
/*-----------------------------------------------------------------------
II. THE LOOP: (executes continuously)
-----------------------------------------------------------------------*/
void loop() {
// The cloud update, every 10 ms:
if ((millis() - cloudupdatecounter) > 10) {
ArduinoCloud.update(); // Update the Cloud editor
cloudupdatecounter = millis();
}
//The once per half second stuff:
if ((millis() - oneseccounter) > 500) {
// Toggle the on-board LED on-off (heartbeat):
digitalWrite (heartbeatled, !(digitalRead(heartbeatled)));
// Measure the light and adjust display brightness:
ldrvalue = analogRead(A0); // LDR with 2 kOhm resistor in series
if (ldrvalue < 400) { ldrvalue = 400; } // just in case
if (ldrvalue > 3000) { ldrvalue = 3000; } // just in case
brightnessValue = map(ldrvalue,400,3000,10,0); // now scale it
myDisplay.setIntensity(brightnessValue); // now set it
// Print the loops per second count:
Serial.println(loopcount*2);
loopcount = 0;
// Finally, reset the half second counter:
oneseccounter = millis();
} // end of once per half second stuff
if (myDisplay.displayAnimate()) {
myDisplay.displayReset();
}
// Now check the button: is it pressed? If so, do something
if (digitalRead(button) == LOW) {
if (buttonActive == false) {
buttonActive = true;
buttonTimer = millis(); // i.e. start the timer
}
if ((millis() - buttonTimer > longPressTime) && (longPressActive == false)) {
longPressActive = true;
//Here, do the change of message...
messageNumber++;
if (messageNumber>4) {messageNumber = 0;}
EEPROM.write(0, messageNumber);
EEPROM.commit();
myDisplay.displayClear();
myDisplay.displayText(ScrollMsg[messageNumber], PA_CENTER, 55, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT); // 55 is speed
}
} else {
if (buttonActive == true) {
if (longPressActive == true) {
longPressActive = false;
}
}
buttonActive = false;
}
loopcount++;
} // end of loop
/*-----------------------------------------------------------------------
IV. FUNCTIONS: (if they exist: execute when called)
-----------------------------------------------------------------------*/