Internet disconnection from IoT Cloud App always at around 5pm

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!

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