Hi all,
I am having a frustrating problem with my Arduino IoT Cloud project's internet connection. My Arduino UNO R4 Wifi with Arduino Cloud device consistently disconnects from the cloud app around 5:00 PM every day. It happened around the same time yesterday and today.
I am using the following libraries (in addition to the standard ones):
thingProperties.h<Wire.h><Adafruit_Sensor.h><Adafruit_ADXL345_U.h><NTPClient.h><WiFiUdp.h><TimeLib.h>
Here is my code:
#include "thingProperties.h"
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <TimeLib.h> // Required for accessing date components
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);
#define RPWM 5
#define LPWM 6
#define R_EN 7
#define L_EN 8
WiFiUDP udp;
NTPClient timeClient(udp, "pool.ntp.org", 3600, 60000);
// Define the target angles for each 7-day period
float TARGET_ANGLE_MORNING_VALUES[43] = {52.5, 49.7, 47.0, 44.3, 41.7, 39.3, 37.0, 34.8, 33.0, 31.5, 30.1, 29.0, 28.0, 27.9, 28.1, 28.7, 29.6, 30.8, 32.3, 33.9, 35.9, 38.1, 40.4, 42.9, 45.5, 48.1, 50.9, 53.6, 56.4, 59.1, 61.6, 64.1, 66.4, 68.5, 70.3, 71.5, 71.5, 71.5, 71.5, 71.5, 71.5, 71.5, 71.5 /* Aggiungi qui i tuoi valori per ogni 7 giorni */};
const int NUM_WEEKS = sizeof(TARGET_ANGLE_MORNING_VALUES) / sizeof(TARGET_ANGLE_MORNING_VALUES[0]);
const float TARGET_ANGLE_EVENING = 14.0;
// float targetAngle = 0.0; // Rimosso perché già dichiarato in thingProperties.h
bool moveToTarget = false;
bool sensorActive = false; // Indica se il sensore è acceso
// Giorno dell'anno in cui inizia il ciclo degli angoli (17 Marzo 2025)
const int START_DAY_OF_YEAR = 76; // Calcolato come: 31 (Gen) + 28 (Feb 2025) + 17 (Mar)
void setup() {
Serial.begin(9600);
pinMode(RPWM, OUTPUT);
pinMode(LPWM, OUTPUT);
pinMode(R_EN, OUTPUT);
pinMode(L_EN, OUTPUT);
digitalWrite(R_EN, HIGH);
digitalWrite(L_EN, HIGH);
timeClient.begin();
setSyncProvider(getNtpTime); // Set NTP time provider for TimeLib
// Inizializza l'ora di sistema con un timestamp valido (anche se verrà aggiornato nel loop)
setTime(1672531200); // Timestamp di esempio (1 Gennaio 2023)
Serial.println("Inizializzazione completata.");
initProperties();
ArduinoCloud.begin(ArduinoIoTPreferredConnection);
setDebugMessageLevel(2);
ArduinoCloud.printDebugInfo();
}
time_t getNtpTime() {
if (!timeClient.update()) {
Serial.println("Failed to get NTP time");
return 0;
}
return timeClient.getEpochTime();
}
bool isTimeToActivateSensor(int currentHour, int currentMinute) {
// Restituisce true se l'orario attuale è tra quelli configurati
return ( (currentHour == 5 && currentMinute >= 50) ||
(currentHour == 6 && currentMinute <= 10) ||
(currentHour == 19 && currentMinute >= 50) ||
(currentHour == 20 && currentMinute <= 10) );
}
void tryActivateSensor() {
if (sensorActive) return; // Se il sensore è già attivo, non fare nulla
Serial.println("Attivazione del sensore ADXL345...");
if (accel.begin()) {
Serial.println("Sensore ADXL345 attivato con successo.");
accel.setRange(ADXL345_RANGE_2_G);
accel.setDataRate(ADXL345_DATARATE_50_HZ);
sensorActive = true;
} else {
Serial.println("Errore nell'inizializzazione del sensore ADXL345.");
}
}
void tryDeactivateSensor() {
if (!sensorActive) return; // Se il sensore è già spento, non fare nulla
Serial.println("Sensore ADXL345 spento.");
sensorActive = false;
}
void moveActuator(int direction) {
if (direction == 1) {
analogWrite(RPWM, 255);
analogWrite(LPWM, 0);
} else if (direction == -1) {
analogWrite(RPWM, 0);
analogWrite(LPWM, 255);
} else {
analogWrite(RPWM, 0);
analogWrite(LPWM, 0);
}
}
int calculateDayOfYear() {
int m = month();
int d = day();
int dayOfYear = 0;
switch (m) {
case 1: dayOfYear = d; break;
case 2: dayOfYear = 31 + d; break; // Assumiamo il 2025 non sia bisestile
case 3: dayOfYear = 31 + 28 + d; break;
case 4: dayOfYear = 31 + 28 + 31 + d; break;
case 5: dayOfYear = 31 + 28 + 31 + 30 + d; break;
case 6: dayOfYear = 31 + 28 + 31 + 30 + 31 + d; break;
case 7: dayOfYear = 31 + 28 + 31 + 30 + 31 + 30 + d; break;
case 8: dayOfYear = 31 + 28 + 31 + 30 + 31 + 30 + 31 + d; break;
case 9: dayOfYear = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + d; break;
case 10: dayOfYear = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + d; break;
case 11: dayOfYear = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + d; break;
case 12: dayOfYear = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + d; break;
}
return dayOfYear;
}
void loop() {
ArduinoCloud.update();
timeClient.update(); // Aggiorna l'ora dal server NTP
setTime(timeClient.getEpochTime()); // Imposta l'ora di sistema per TimeLib
int currentHour = hour(); // Ottiene l'ora corrente da TimeLib
int currentMinute = minute(); // Ottiene i minuti da TimeLib
int currentYear = year(); // Ottiene l'anno da TimeLib
int currentDayOfYear = calculateDayOfYear(); // Calcola manualmente il giorno dell'anno
// Formatta la data e l'ora
String formattedDateTime = timeClient.getFormattedTime();
Serial.print("Ora attuale (formattata): ");
Serial.println(formattedDateTime);
// Controllo accensione/spegnimento del sensore
if (isTimeToActivateSensor(currentHour, currentMinute)) {
tryActivateSensor(); // Tentativo di attivazione del sensore solo se è l'orario giusto
} else {
tryDeactivateSensor(); // Spegni il sensore
}
// Se il sensore è spento, non eseguire letture
if (!sensorActive) {
delay(1000); // Aspetta 1 secondi prima di riprovare
return;
}
// Leggi il sensore se attivo
sensors_event_t event;
accel.getEvent(&event);
if (isnan(event.acceleration.x)) {
Serial.println("Errore nella lettura del sensore!");
return;
}
// Calcola l'inclinazione
float inclinationX = abs(atan2(event.acceleration.y, event.acceleration.z) * 180 / M_PI);
inclinationXCloud = 0.1 * inclinationX + 0.9 * inclinationXCloud;
Serial.print("Ora attuale (solo ora e minuti): "); Serial.print(currentHour); Serial.print(":"); Serial.println(currentMinute);
Serial.print("Inclinazione X: "); Serial.println(inclinationXCloud);
if (currentHour == 6 && currentMinute == 0) {
if (sensorActive) {
// Calcola il giorno dell'anno corrente rispetto all'inizio del ciclo
int daysSinceStart = currentDayOfYear - START_DAY_OF_YEAR;
// Calcola l'indice della settimana basato sui giorni trascorsi dall'inizio del ciclo
int weekIndex = daysSinceStart / 7;
// Usa l'indice della settimana per selezionare l'angolo target dall'array
int angleIndex = weekIndex % NUM_WEEKS;
targetAngle = TARGET_ANGLE_MORNING_VALUES[angleIndex];
Serial.print("Anno corrente: "); Serial.println(currentYear);
Serial.print("Giorno dell'anno: "); Serial.println(currentDayOfYear);
Serial.print("Giorni dall'inizio del ciclo: "); Serial.println(daysSinceStart);
Serial.print("Indice della settimana: "); Serial.println(weekIndex);
Serial.print("Indice dell'angolo: "); Serial.println(angleIndex);
Serial.print("Nuovo TARGET_ANGLE_MORNING: "); Serial.println(targetAngle);
moveToTarget = true;
} else {
Serial.println("ATTENZIONE: Tentativo di avvio motore mattutino con sensore NON attivo!");
}
}
else if (currentHour == 20 && currentMinute == 0) {
targetAngle = TARGET_ANGLE_EVENING;
moveToTarget = true;
}
// Se dobbiamo raggiungere una posizione specifica
if (moveToTarget) {
if (abs(inclinationXCloud - targetAngle) > 1.0) { // Tolleranza di ±1 grado
if (inclinationXCloud < targetAngle) {
moveActuator(1); // Muove avanti
} else {
moveActuator(-1); // Muove indietro
}
} else {
moveActuator(0); // Ferma il motore quando raggiunge la posizione
moveToTarget = false;
}
}
// Controllo comandi seriali
if (Serial.available() > 0) {
String command = Serial.readStringUntil('\n');
command.trim();
if (command == "Avanti") {
moveActuator(1);
} else if (command == "Indietro") {
moveActuator(-1);
} else if (command == "Stop") {
moveActuator(0);
}
}
delay(100);
}
File thingProperties.h
#include <ArduinoIoTCloud.h>
#include <Arduino_ConnectionHandler.h>
const char SSID[] = SECRET_SSID; // Network SSID (name)
const char PASS[] = SECRET_OPTIONAL_PASS; // Network password (use for WPA, or use as key for WEP)
// Dichiarazione delle funzioni di callback
void onAvantiButtonChange();
void onIndietroButtonChange();
void onStopButtonChange();
void moveActuator(int direction);
// Variabili globali per i dati da inviare al Cloud
float inclinationXCloud;
float targetAngle;
bool avantiButton;
bool indietroButton;
bool stopButton;
String currentDateTime; // Dichiarazione della variabile globale per la data e ora
// Funzione di inizializzazione delle proprietà IoT Cloud
void initProperties() {
ArduinoCloud.addProperty(inclinationXCloud, READ, ON_CHANGE, NULL);
ArduinoCloud.addProperty(targetAngle, READ, ON_CHANGE, NULL);
ArduinoCloud.addProperty(avantiButton, READWRITE, ON_CHANGE, onAvantiButtonChange);
ArduinoCloud.addProperty(indietroButton, READWRITE, ON_CHANGE, onIndietroButtonChange);
ArduinoCloud.addProperty(stopButton, READWRITE, ON_CHANGE, onStopButtonChange);
}
// Gestore della connessione Wi-Fi per IoT Cloud
WiFiConnectionHandler ArduinoIoTPreferredConnection(SSID, PASS);
My Arduino IoT Cloud configuration includes the inclinationXCloud and targetAngle variables, and the avantiButton, stopButton and indietroButton buttons. I use the Arduino Web Editor.
My internet connection is Tim business fiber.
I noticed this disconnection problem both yesterday and today, always around 5 pm. I noticed that the only way to get the connection back after the 5 pm disconnection is to completely unplug the Arduino and then plug it back in.
Has anyone else encountered a similar hourly disconnection problem with Arduino IoT Cloud? Are there any specific settings in the Arduino Cloud that could cause a temporary disconnection? Could there be a problem in my code that leads to a connection interruption around that time? Are there any libraries or Wi-Fi configurations that could cause this behavior? What tools or debugging methods can I use to better understand what happens at 5 pm?
Thank you very much for your help!