Problema di stampa su monitor seriale a intervalli regolari tramite RTC

Buona sera a tutti. Ho un problema di stampa a intervalli regolari con rtc.
Nello specifico devo stampare alcune informazioni a intervalli di 15 minuti e altre informazioni a intervalli di 1 secondo. Se le due parti le scrivo su due sketch separati funzionano. Se invece le unisco inizia la stampa a intervalli di 1 secondo, arriva al 15mo minuto, stampa le informazioni del 15mo minuto e si blocca la stampa.
Come posso risolvere?

senza vedere il programma è un po' difficile...

Scusate il ritardo. Vi giro il codice semplificato. Il codice stampa a intervalli di 1 secondo l'ora, minuti e secondi. Poi se l'orario è compreso tra "StartTimeWork" e "FinishTimeWork"
fa un'altra stampa, se arriva al 15mo minuto fa la successiva stampa, ma poi si blocca.
A dopo!!!

void loop() {

DateTime now = rtc.now();

if (correntMillis - previousMillis >= intervalRead) {
previousMillis = correntMillis; 

 Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println(" ");

if (now.hour() >= StartTimeWork && now.hour() < FinishTimeWork) {
 Serial.print("    ");

if(now.hour()>=0 && now.minute()==0 | now.minute() ==15 | now.minute() ==30 | now.minute() ==45 && now.second()==0) {

Serial.print("   ");
}
}
}

scusa ma questo non è il codice che ti da il problema che riporti...questo codice è incompleto e sbagliato per altri motivi.
posta quello "corretto" o non ne usciamo.

1 Like

In realtà è questo il codice con la differenza che ho tolto le letture del sensore di temperatura e le ho sostituite con un semplice serial print. Il problema è proprio nella stampa dell'ultima parte. Mi spunta un punto interrogativo sul serial monitor.

Ci sono alcuni errori, tra i quali l'uso dello or sbagliato e il mancato aggiornamento di currentmillis

Dubito che quel programma abbia i problemi che dici, ne ha altri peggiori
Inoltre siamo convinti che tu abbia copiato in tutto o in parte da vecchi siti o pubblicazioni

Comunque dato che quel programma non può dare gli errori che descrivi ti consiglierei di controllare bene i messaggi di errore in compilazione e trasferimento

Buongiorno, io non sono un programmatore quindi sto cercando di imparare da quello che trovo sulla rete incluso il forum.
Nel codice ho dimenticato a copiare "unsigned long currentMillis = now.unixtime() * 1000;" prima del primo if.

Per quanto riguarda errori di compilazione non ne da. Lo sketch viene caricato su Arduino, parte ma poi si blocca.
Non saprei!!

Invece di impegolarsi con i millisecondi io controllerei quando cambia il secondo:

if (now.second() != previousSecond) {
    previousSecond = now.second(); 

}
1 Like

Adesso si comincia a ragionare

E per quanto riguarda la condizione sbagliata?

Perfetto questo mi semplifica il codice!!!!

Se lo provi ti funziona? Cioè riesci a vedere l'ultimo serial print?

Non lo so

Non lo provo di certo

E' incompleto e certamente sbagliato

Il debug si fa su programmi completi e che dovrebbero funzionare

Su quelli che sono certamente sbagliati "prima" si tolgono gli errori conosciuti, "dopo" si vede cosa fanno

Riassumendo: metti a posto la condizione
Ricompila il programma
Vedi come va
E poi casomai postalo con una descrizione completa e dettagliata di cosa dovrebbe fare e di cosa fa

E mi raccomando: completo, compilabile e formattato

1 Like

Quel if non può funzionare senza ulteriori parentesi
tuo originale:
now.hour()>=0 && now.minute()==0 | now.minute() ==15 | now.minute() ==30 | now.minute() ==45 && now.second()==0

corretto:
now.hour()>=0 && (now.minute()==0 || now.minute() ==15 || now.minute() ==30 || now.minute() ==45) && now.second()==0

senza parentesi ogni test viene valutato da sx a dx, quindi ora>=0 e minuto=0, poi oppure minuto=15, etc. Inoltre or logico è || e non | (solo uno è or sui bit)

P.S. a che serve chiedere se hour() >= 0 ?? ti risulta possa essere negativo ??

Edit: corretto "or logico", grazie @Salvorhardin

Buona sera, ringrazio tutti per le correzioni e mi scuso per il ritardo nella risposta. Ho aggiunto alcune righe di codice e lo condivido in modo da poterlo sistemare. Il codice viene compilato, il seriale restituisce quello che deve ma appena tolgo lo Slash della riga 269 e i successivi serial print il monitor seriale si blocca. Grazie a dopo!!!

//RTC+SD
#include <RTClib.h>
#include <SPI.h>
#include <SD.h>
#define SD_CS_PIN 10  //pin CS del modulo SD
File dataFile;
RTC_DS1307 rtc;
char daysOfTheWeek[7][4] = {"Dom","Lun","Mer","Mer","Gio","Ven","Sab",};


// valore dell'igrometro che attiva il relè
const int valore_limite = 990;

// costanti per il calcolo del VPD. La formula è stata presa dal file excel del calcolo del VPD
float avpd = 0;
float a = 0;

// costanti per il calcolo della media delle letture dell'igrometro
float valori [10];
float media =0.0;

//costanti igrometro
float igro = 0;
float umdtrr = 0;

//costanti light sensor e attivazione attuatori
int StartTimeWork = 6;
int FinishTimeWork = 22;
int TimeBuffer = 1;
long PPFD_micro_watt_cmq = 0;
long PPFD_watt_mq = 0;
int soglia_PPFD_watt_mq = 400;
unsigned long DLI_micromoli_mq_giornaliero = 0;
long soglia_DLI_micromoli_mq_giornaliero = 20000; //scegliere un valore in moli e convertirlo in micromoli(es: 100 moli/mq/day * 1000000)
DateTime PPFD_firstOverThresholdTime;
bool PPFD_OverThreshold = false;
bool DLI_OverThreshold = false;

//costanti per stampare a intervalli regolari
unsigned long correntMillis;
unsigned long previousMillis = 0;
const long intervalRead = 1000;

//DGT11 sensor:
#include "DHT.h"
#define DHTPIN 6 //sensore collegato al pin 6
#define DHTTYPE DHT11 //DHT 11
DHT dht(DHTPIN, DHTTYPE);

//I2C LCD:
#include <Wire.h> // Libreria Wire
#include <LiquidCrystal_I2C.h> //Libreria LCD I2C

//LCD Address
LiquidCrystal_I2C lcd = LiquidCrystal_I2C (0x27, 20, 4);//da cambiare se si ha un modello diverso

//Libreria Light Sensor
#include <Wire.h>
#include "Adafruit_AS726x.h"
//create the object
Adafruit_AS726x ams;
//buffer to hold raw values
uint16_t sensorValues[AS726x_NUM_CHANNELS];
//buffer to hold calibrated values (not used by default in this example)
//float calibratedValues[AS726x_NUM_CHANNELS];

void setup() {
 
 Serial.begin(9600);

// Pin 4 al relè - IN4
 pinMode(4, OUTPUT);

// Pin 3 al relè - IN3
 pinMode(3, OUTPUT);

// Pin 2 al relè - IN2
 pinMode(2, OUTPUT);

//I2C LCD
 lcd.init ();
 lcd.backlight();
 lcd.clear();
 //Serial.print ("Serra Domotizzata");
 lcd.print("Serra Domotizzata");
 lcd.clear();

//Avvio Sensore DHT11
 dht.begin();

 //Avvio RTC+SD
 if (!rtc.begin()) {
    Serial.println("Error");
    return;
  }
 if (!rtc.isrunning()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  } 

// initialize digital pin LED_BUILTIN as an output light sensor
  pinMode(LED_BUILTIN, OUTPUT);

//begin and make sure we can talk to the light sensor
  if(!ams.begin()){
    Serial.println("could not connect to sensor! Please check your wiring.");
    while(1);
  }

//begin SD card
  if (!SD.begin(SD_CS_PIN)) {
    Serial.println("inizializzazione SD fallita");
    while (1)
      ;
  }
}


void loop() {

//RTC+SD
 DateTime now = rtc.now();

   correntMillis = now.unixtime() * 1000;                 //conversione del tempo in millisecondi
  if (correntMillis - previousMillis >= intervalRead) {  //Confronta il tempo corrente rispetto all'ultima lettura del tempo e se la differenza è maggiore o uguale allintervallo allora...
    previousMillis = correntMillis;                      //il tempo precedente dell'ultima lettura è uguale alla lettura del tempo corrente, quindi essendo uguali la sequanza del loop avverrà  a cadenza dell'intervallo prefissato.

    Serial.print(now.day(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.year(), DEC); 
    Serial.print(" (");
    Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
    Serial.print(") ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println(" ");

//Stampa su SD
    dataFile = SD.open("datalog.txt", FILE_WRITE); 
    if (dataFile) {
      dataFile.print(now.hour(), DEC);
      dataFile.print(" : ");
      dataFile.print(now.minute(), DEC);
      dataFile.print(" : ");
      dataFile.print(now.second(), DEC);
      dataFile.println(" ");
      dataFile.close();
    } else {
      Serial.println("Errore scrittura su SD");
    }


    if (now.hour() >= StartTimeWork && now.hour() < FinishTimeWork) {

      //read the device temperature
      uint8_t temp = ams.readTemperature();

      //ams.drvOn(); //uncomment this if you want to use the driver LED for readings
      ams.startMeasurement();  //begin a measurement

      //wait till data is available
      bool rdy = false;
      while (!rdy) {
        //delay(5);
        rdy = ams.dataReady();
      }
      //ams.drvOff(); //uncomment this if you want to use the driver LED for readings

      //read the values!
      ams.readRawValues(sensorValues);
      //ams.readCalibratedValues(calibratedValues);

      Serial.print("Temp: ");
      Serial.print(temp);
      Serial.print(" Violet: ");
      Serial.print(sensorValues[AS726x_VIOLET]);
      Serial.print(" Blue: ");
      Serial.print(sensorValues[AS726x_BLUE]);
      Serial.print(" Green: ");
      Serial.print(sensorValues[AS726x_GREEN]);
      Serial.print(" Yellow: ");
      Serial.print(sensorValues[AS726x_YELLOW]);
      Serial.print(" Orange: ");
      Serial.print(sensorValues[AS726x_ORANGE]);
      Serial.print(" Red: ");
      Serial.print(sensorValues[AS726x_RED]);
      Serial.print(" PPFD: ");
      PPFD_micro_watt_cmq = (sensorValues[AS726x_VIOLET]) + Serial.print(sensorValues[AS726x_BLUE]) + (sensorValues[AS726x_GREEN]) + (sensorValues[AS726x_YELLOW]) + (sensorValues[AS726x_ORANGE]) + (sensorValues[AS726x_RED]);
      Serial.print(PPFD_micro_watt_cmq);
      Serial.print(" microwatt/cq ");
      Serial.print(" PPFD: ");
      PPFD_watt_mq = (PPFD_micro_watt_cmq / 100);
      DLI_micromoli_mq_giornaliero += (PPFD_watt_mq * 2); //1 watt/mq = 2 micromoli/mq/s. La moltiplicazione x 2 serve a fare la conversione. Vedi slide Stanghellini. 
      Serial.print(PPFD_watt_mq);
      Serial.print(" watt/mq  ");
      Serial.print(" DLI: ");
      Serial.print(DLI_micromoli_mq_giornaliero);
      Serial.println(" micromole/m2/s");
      //Serial.println();


      if (DLI_micromoli_mq_giornaliero <= soglia_DLI_micromoli_mq_giornaliero) {
       if (PPFD_watt_mq < soglia_PPFD_watt_mq) {
         if (!PPFD_OverThreshold) {                  //prima volta che la soglia della luce è stata superata in positivo o in negativo in base alle impostazioni
          PPFD_firstOverThresholdTime = rtc.now();  //salva l'ora corrente
          PPFD_OverThreshold = true;                //la soglia è stata superata
        } else {
          DateTime now = rtc.now();
          TimeSpan elapsed = now - PPFD_firstOverThresholdTime;
          if (elapsed.totalseconds() >= TimeBuffer) {
            Serial.println("Accesa");
          }
        }
       }
             else {  //la luce è sopra la soglia, reset
        PPFD_OverThreshold = false;
        Serial.println("spenta");
       }
      } 
     }  
    }  
 

//Fotoresistore
  int Lumen = analogRead (A0); //Lettura della fotoresistenza dal pin A0
  

 if (Lumen > 750)
  digitalWrite (2, HIGH); //se il valore di Lumen è maggiore di 750 attiva relè
 else
  digitalWrite (2, LOW); //altrimenti spegni il relè

//Livello acqua
  int water = analogRead(A1);
  

 if (water >=300) {
  lcd.setCursor(0,3);
  lcd.print("Livello Acqua: OK");
  }
   else
    {
      lcd.setCursor(0,3);
      lcd.print("Livello Acqua: BASSA");
      //alarm();
      //flash();
  }

//lettura Umidità e Temperatura e calcolo AVPD
   float h = dht.readHumidity();
   float t = dht.readTemperature();
    
   a = 610.78 * exp( t/(t + 237.3) * 17.2594 )/1000.0;
   avpd = a * (1.0 - h/100.0);


  
//Lettura valori dei sensori a intervalli prestabiliti
  if(now.hour()>=0 && (now.minute()==00 || now.minute() ==56 || now.minute() ==30 || now.minute() ==45) && now.second()==0) {  
 
//Igrometro
    igro = analogRead (A2);
    umdtrr = 0; //Variabile umidità suolo
    umdtrr = map (igro, 100, 990, 100, 0); //converte il valore analogico in percentuale
    //Serial.println("     Valore puntuale umidità del suolo: ");
    //Serial.println(umdtrr);


  for (int a =0; a<10; a++){
    valori [a] = umdtrr;
    media = media + valori [a];
    //Serial.print("Valore delle 10 letture per fare la media dell'umidità del suolo: ");
    //Serial.println(valori [a] );
  }
    media = media /10;
      
    //Serial.print("Media di 10 letture umidità del suolo: ");
    //Serial.println(media);

//Stampa valore sensore crepuscolare
    //Serial.print ("Sensore crepuscolare: ");
    //Serial.println (Lumen, DEC); //stampa un valore decimale del fotoresistore

//Stampa valore sensore di livello acqua
    //Serial.print ("Sensore di livello: ");
    //Serial.println(water, DEC); //stampa il valore decimale del livello dell'acqua

//Stampa valore sensore T e U
    //Serial.print ("Temp: ");
    //Serial.print (t);
    //Serial.println (" C");
    //Serial.print ("Umid: ");
    //Serial.print (h);
    //Serial.println (" %");
 }

    
}

     





Che sarebba dalla riga //Serial.println(" Valore puntuale umidità del suolo: ");

Non ci vedo nulla di strano, mi sembra corretto come codice.
Hai provato a togliere i commenti a solo UNA di quelle Serial.print ?

P.S. quel giro di 10 col for non ha senso. Leggi solo 1 volta analogRead(A2) e lo scrivi in igro
essendo fuori dal for... umdtrr vale sempre lo stesso valore. Non serve un vettore visto che calcoli subito, non azzeri mai media.

//Igrometro
  media = 0 ;
  for (int a =0; a<10; a++)
  { igro = analogRead (A2);                                   
    media = media + map (igro, 100, 990, 100, 0);  //converte il valore analogico in percentuale
  }
  media = media / 10.0;

269Ciao.

"Che sarebba dalla riga `//Serial.println(" Valore puntuale umidità del suolo: ");" Semplicemente è il valore di umidità nel momento della lettura. Per quanto riguarda la media dell'umidità, ha avuto solo lo scopo di verificare se il sensore leggeva correttamente, comunque andrà tolta. La modificherò per come mi hai consigliato.

"Hai provato a togliere i commenti a solo UNA di quelle Serial.print ?"
ho fatto diverse prove:

1)Stampa con serial print esclusa la riga 269 e successive: Tutto funziona correttamente

11/7/2024 (Gio) 17:27:45
Temp: 29 Violet: 265 Blue: 292 Green: 377 Yellow: 335 Orange: 229 Red: 197 PPFD: 2921406 microwatt/cq PPFD: 14 watt/mq DLI: 28 micromole/m2/s
11/7/2024 (Gio) 17:27:46
Temp: 28 Violet: 265 Blue: 292 Green: 377 Yellow: 335 Orange: 230 Red: 197 PPFD: 2921407 microwatt/cq PPFD: 14 watt/mq DLI: 56 micromole/m2/s
Accesa
11/7/2024 (Gio) 17:27:47
Temp: 29 Violet: 265 Blue: 293 Green: 377 Yellow: 335 Orange: 230 Red: 197 PPFD: 2931407 microwatt/cq PPFD: 14 watt/mq DLI: 84 micromole/m2/s
Accesa
11/7/2024 (Gio) 17:27:48
Temp: 29 Violet: 265 Blue: 292 Green: 377 Yellow: 335 Orange: 230 Red: 197 PPFD: 2921407 microwatt/cq PPFD: 14 watt/mq DLI: 112 micromole/m2/s

  1. Stampa con aggiunta della riga 269: Questo il risultato

11/7/2024 (Gio) 17:38:36
Temp: 30 Violet: 257 Blue: 287 Green: 372 Yellow: 333 Orange: 229 Red: 200 PPFD: 2871394 microwatt/cq PPFD: 13 watt/mq DLI: 26 micromo11/7/2024 (Gio) 17:38:38
Temp: 30 Violet: 257 Blue: 288 Green: 372 Yellow: 333 Orange: 229 Red: 200 PPFD: 2881394 microwatt/cq PPFD: 13 watt/mq DLI: 26 micromole/�

  1. stampa senza la riga 269 ma con la riga 270: funziona correttamente
    11/7/2024 (Gio) 17:40:6
    Temp: 30 Violet: 256 Blue: 288 Green: 373 Yellow: 334 Orange: 229 Red: 201 PPFD: 2881396 microwatt/cq PPFD: 13 watt/mq DLI: 158 micromole/m2/s
    Accesa
    11/7/2024 (Gio) 17:40:7
    Temp: 30 Violet: 257 Blue: 288 Green: 373 Yellow: 334 Orange: 230 Red: 202 PPFD: 2881399 microwatt/cq PPFD: 13 watt/mq DLI: 184 micromole/m2/s

  2. stampa senza la riga 269 ma con la riga 270 e quando arrivo al minuto specifico dichiarato nella riga 263 questo è il risultato:
    11/7/2024 (Gio) 17:42:0
    Temp: 30 Violet: 257 Blue: 290 Green: 376 Yellow: 337 Orange: 232 Red: 205 PPFD: 2901410 microwatt/cq PPFD: 14 watt/mq DLI: 980 micromole/m2/s
    Accesa
    0.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.0011/7/2024 (Gio) 17:42:1

Che Arduino stai utilizzando? ... perché ricorda problemi di mancanza di memoria ... :roll_eyes:

Guglielmo

arduino 1

ho provato a mettere una parola al posto della lettura del sensore e a fatto 13 stampe invece che 1. Mi sembra un problema legato all'RTC ma comunque è strano perchè quando questa parte di codice era in un altro sketch funzionava bene.

17:54:05.916 -> 11/7/2024 (Gio) 18:0:59

17:54:06.232 -> Temp: 30 Violet: 254 Blue: 298 Green: 392 Yellow: 358 Orange: 250 Red: 230 PPFD: 2981487 microwatt/cq PPFD: 14 watt/mq DLI: 1764 micromole/m2/s

17:54:06.396 -> Accesa

17:54:06.396 -> ciao

17:54:06.396 -> ciao

17:54:06.428 -> ciao

17:54:06.473 -> ciao

17:54:06.515 -> ciao

17:54:06.515 -> ciao

17:54:06.584 -> ciao

17:54:06.584 -> ciao

17:54:06.617 -> ciao

17:54:06.650 -> ciao

17:54:06.682 -> ciao

17:54:06.715 -> ciao

17:54:06.748 -> ciao

17:54:06.828 -> ciao

17:54:06.874 -> ciao

17:54:06.905 -> ciao

17:54:06.905 -> 11/7/2024 (Gio) 18:1:0

17:54:07.227 -> Temp: 30 Violet: 253 Blue: 298 Green: 391 Yellow: 357 Orange: 250 Red: 230 PPFD: 2981484 microwatt/cq PPFD: 14 watt/mq DLI: 1792 micromole/m2/s

Ho fatto alcune prove.
Togliendo alcune etichette dai valori letti dai sensori la stampa non si blocca.

Se però tolgo tutte le etichette si blocca comunque

... per me, al 90% è un problema di memoria ... usi librerie che sono delle vere mangia memoria, se ci aggiungi tutte le stringhe delle Serial.print() ... ecco fatto che vai fuori. :roll_eyes:

Puoi provare, come ultima ratio, ad usare la macro F() per le stringhe che stampi spostandole così in flash invece che in SRAM ... vedi in fondo a QUESTA pagina.