Timer On/Off ma quando si spegne e riaccende Arduino non riaccende Luce

Salve a tutti, mi chiamo Michele e sto progettando un sistema di controllo per la mia mini serra di peperoncino e basilico, ho riscontrato un piccolo problemino, per quando riguarda l’accensione della luce qualora andasse via la corrente, vi spiego meglio.

Se imposto l’orario di accensione alle 20.00 e lo spegnimento alle 23.00 e la corrente va via alle 20.30 e ritorna alle 20.35 Arduino non mi accende la luce, come posso risolvere questo piccolo problemino?

Il codice scritto è il seguente:
Nel codice purtroppo i relè mi lavorano al contrario, HIGH = SPENTO, LOW = ACCESO.

#include <SimpleDHT.h>
#include <DS3231.h>
#include "RTCLib.h"


int relay1 = 2;
int relay2 = 3;
int relay3 = 4;
SimpleDHT22 dht22(5);

DS3231  rtc(SDA, SCL);
Time t;

void setup() 
{
    Serial.begin(9600);
    rtc.begin();
    pinMode(relay1, OUTPUT);// PIN 2 OUTPUT
    pinMode(relay2, OUTPUT);// PIN 3 OUTPUT
    pinMode(relay3, OUTPUT);// PIN 4 OUTPUT
    
    digitalWrite(relay1, HIGH); // IMPOSTO IL RELE' IN OFF DI DEFAULT
    digitalWrite(relay2, HIGH); // IMPOSTO IL RELE' IN OFF DI DEFAULT
    digitalWrite(relay3, HIGH); // IMPOSTO IL RELE' IN OFF DI DEFAULT
}

void loop() {
  flash();
  temperaturaumidita();
  timer();
}

  void flash() //Sistema in esecuzione
  {
  digitalWrite(6, HIGH);   // Imposta il LED su ON
  delay(50);               // Aspetta per 1 secondo
  digitalWrite(6, LOW);    // Impostiamo il LED su OFF
  delay(50);   // Aspetta per 1 secondo
  }
  
  void timer()
  {

  const int OnOra = 20; //IMPOSTO L'ORARIO PER L'ACCENSIONE DELLA LUCE
  const int OnMin = 00;
  const int OffOra = 23; //IMPOSTO L'ORARIO PER LO SPEGNIMENTO DELLLA LUCE
  const int OffMin = 00;

  t = rtc.getTime(); //LEGGO L'ORA DAL TIMER
  
  Serial.print(t.hour);
  Serial.print(" ORA, ");
  Serial.print(t.min);
  Serial.print(" MINUTI");
  Serial.println(" ");
  delay (1500);
  
    if(t.hour == OnOra && t.min == OnMin){
    digitalWrite(relay3,LOW);
    Serial.println("LUCE ON");
    }
    
    else if(t.hour == OffOra && t.min == OffMin){
      digitalWrite(relay3,HIGH);
      Serial.println("LUCE OFF");
    }

  }

   void temperaturaumidita()
   {
  float temperature = 0;
  float humidity = 0; 
  dht22.read2(&temperature, &humidity, NULL);
  Serial.print((float)temperature); Serial.print(" °C, ");
  Serial.print((float)humidity); Serial.println(" %");
  delay(1500);
 
  if (temperature >= 20) 
  {
    digitalWrite(relay1, LOW); 
        }
    else
    {
      digitalWrite(relay1, HIGH);
      }
      if(humidity >= 90)
          {
             digitalWrite(relay2, LOW); 
           }
           else
           {
            digitalWrite(relay2, HIGH); 
           }
    }

Buonasera e benvenuto, :) essendo il tuo primo post, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD ([u]spiegando bene quali conoscenze hai di elettronica e di programmazione[/u] ... possibilmente [u]evitando[/u] di scrivere solo una riga di saluto) e di leggere con molta attenzione tutto il su citato REGOLAMENTO ... Grazie. :)

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposito thread, nessuno ti potrà rispondere, quindi ti consiglio di farla al più presto. ;)

Salve Guglielmo,

ho eseguito la presentazione come da te indicato, ora provvedo alla lettura del regolamento.

Grazie.

Il problema è nel modo in cui l'hai impostato, ossia tu accendi quando ora e minuti sono esattamente quelli dell'ora di inizio, e spegni quando sono quelli della fine. Per cui non solo fai più volte "LUCE ON" per un intero minuto (lo stesso per "LUCE OFF") ma se passa il minuto non accendi più.

Devi quindi cambiare la condizione di accensione in:

SE l'ora corrente è maggiore o uguale a quella di accensione E minore di quella di spegnimento E la luce è spenta ALLORA accendi.

Per sapere se è accesa o spenta ti basta leggere con digitalRead(relay3).

Provaci e facci vedere il risultato. ;)

docdoc: ... Per sapere se è accesa o spenta ti basta leggere con digitalRead(relay3) ...

... beh, i*n questo caso*, non è che cambia molto se non se lo chiede e continua a fare la digitalWrite() ;)

Però può essere un ottimo esercizio per imparare a gestire situazioni più complesse ... :D

Guglielmo

gpb01: ... beh, i*n questo caso*, non è che cambia molto se non se lo chiede e continua a fare la digitalWrite() ;)

Si, ma oltre ad essere inutile, scrive pure su seriale tutte le volte... ;)

E comunque con l'algoritmo che gli ho suggerito non capita sicuramente più.

docdoc: Il problema è nel modo in cui l'hai impostato, ossia tu accendi quando ora e minuti sono ...

Grazie per la risposta docdoc, chiedo gentilmente se puoi farmi un esempio su come scrivere il ciclo di controllo.

>micky994: Quando si quota un post, NON è necessario riportarlo (inutilmente) tutto; bastano poche righe per far capire di cosa si parla ed a cosa ci si riferisce, inoltre, se si risponde al post immediatamente precedente, normalmente NON è necessario alcun "quote" dato che è sottinteso. :)

Gli utenti da device "mobile" (piccoli schermi) ringrazieranno per la cortesia ;)

Guglielmo

P.S.: Ho troncato io il "quote" del tuo post qui sopra ;)

micky994: Grazie per la risposta docdoc, chiedo gentilmente se puoi farmi un esempio su come scrivere il ciclo di controllo.

Te l'avevo già descritto, ossia la condizione deve essere:

SE l'ora corrente è maggiore o uguale a quella di accensione E minore di quella di spegnimento E la luce è spenta ALLORA accendi.

Prova a tradurre questo in codice C, ti basta capire come codificare le condizioni. fai una prova, e se non riesci posta quello che avrai nel frattempo scritto così ti aiutiamo vlentieri.

Aiutino: per poter fare confronti più agevoli, converti ore e minuti in un intero che corrisponde ai minuti, ti basta sommarli all'ora moltiplicata per 60. Quindi se ad esempio volessi rappresentare come ore di inizio e di fine le 20:30 e le 23:00 farei:

int ora1 = 20 * 60 + 30; int ora2 = 23 * 60 + 0;

Quando leggi dall'RTC farai lo stesso:

int adesso = t.hour * 60 + t.min;

A quel punto avrai dei valori interi da usare per fare confronti in modo più comodo... Occhio solo ad eventuali intervalli che dovessero superare le 23:59... ;)

Dai, prova e facci sapere.

Salve docdoc, grazie per la delucidazione, ho messo su questo nel timer lo sto testando è sembra funzionare, puoi darmi qualche altro consiglio? oppure il codice che ho messo presenta errori? è da venerdì che mi sto scimmiando per capire. :confused:

onTimer = onora * 60 + onminuti;
offTimer = offora * 60 + offminuti;

OraAttuale = now.hour() * 60 + now.minute();

if (onTimer < offTimer) {
    if ((OraAttuale >= onTimer) && (OraAttuale < offTimer)) {
      digitalWrite(relay3,LOW);// ACCESO     
    } else {
      digitalWrite(relay3,HIGH);// SPENTO
    }
} else {
    if ((OraAttuale >= onTimer) || (OraAttuale < offTimer)) {
      digitalWrite(relay3,LOW);// ACCESO
    } else {
      digitalWrite(relay3,HIGH);// SPENTO
    }

gpb01 > Va bene, ti ringrazio.

micky994:
Salve docdoc, grazie per la delucidazione, ho messo su questo nel timer lo sto testando è sembra funzionare, puoi darmi qualche altro consiglio? oppure il codice che ho messo presenta errori?

Bravo, vedo che hai giustamente messo quella if() per distinguere se onTimer sia minore o maggiore di offTimer, e funziona. Però teoricamente quando si realizzano temporizzazioni di questo tipo conviene sempre agire solo quando occorre, ossia accendere la luce se dovesse risultare spenta e viceversa, sia per non ripetere centinaia di volte al secondo la stessa istruzione sia perché a volte l’azione da effettuare potrebbe non essere solamente quella di alzare un pin ma anche altre cose, che vanno eseguite solo una volta e solo al cambio di stato.

Il che significa che ti ancherebbe una condizione, quella che verifica se la luce sia accesa o spenta:

SE l’ora corrente è maggiore o uguale a quella di accensione
E minore di quella di spegnimento
E la luce è spenta
ALLORA accendi.
SE l’ora corrente è minore di quella di accensione
O maggiore o uguale a quella di spegnimento
E la luce è accesa
ALLORA spegni.

Se l’accensione dovesse risultare maggiore dello spegnimento (es. dalle 23 alle 6) devi solamente invertire la logica ossia le condizioni “E” ed “O” che ho evidenziato.

Poi dato che i relè usano spesso la logica inversa, usa dei simboli per chiarire meglio la cosa ed evitare possibili confusioni, rendendo il codice ben più leggibile… :wink: I simboli e le costanti si mettono per convenzione in maiuscolo, per distinguerli dalle variabili, quindi ti consiglio di fare così anche per i numeri dei pin.

Vedi questa versione ad esempio, io farei così:

...
// Pin del relè (ex "relay3)
// Nota: metti possibilmente un prefisso per i pin, ad esempio "P_", ed usa sempre nomi più 
// significativi, come questo esempio:
#define P_LUCI 3

#define SPENTO HIGH
#define ACCESO LOW
bool inOrario; // Indica se l'ora corrente è quella di accensione
...
onTimer = onora * 60 + onminuti;
offTimer = offora * 60 + offminuti;
OraAttuale = now.hour() * 60 + now.minute();
// Determino se siamo nell'orario di accensione
if (onTimer < offTimer)
  inOrario = (OraAttuale >= onTimer && OraAttuale < offTimer);
else  
  inOrario = (OraAttuale >= onTimer || OraAttuale < offTimer);
// Verifico lo stato del relè
if ( inOrario && digitalRead(P_LUCI) == SPENTO) {
    digitalWrite(P_LUCI, ACCESO);
  if ( (OraAttuale >= onTimer || OraAttuale < offTimer) && digitalRead(P_LUCI) == ACCESO ) {
    digitalWrite(P_LUCI, SPENTO);
...

Come vedi, il codice è persino più compatto e molto più leggibile e comprensibile anche da parte di chi, come noi, leggiamo un tuo codice.

(PS: la “if (onTimer < offTimer)” si potrebbe anche scrivere diversamente, ma sarebbe meno leggibile…)

Ok DocDoc,
grazie ancora più tardi codifico ciò che mi hai detto e lo condivido sul forum per sapere se va bene,
giusto per curiosità ed ampliare la mia conoscenza mi dici come scrivere diversamente quello in cui ti ho citato.

(PS: la “if (onTimer < offTimer)” si potrebbe anche scrivere diversamente, ma sarebbe meno leggibile…)

Grazie.

micky994:
giusto per curiosità ed ampliare la mia conoscenza mi dici come scrivere diversamente quello in cui ti ho citato.

Al posto dell’intera if():

if (onTimer < offTimer)
  inOrario = (OraAttuale >= onTimer && OraAttuale < offTimer);
else 
  inOrario = (OraAttuale >= onTimer || OraAttuale < offTimer);

si può usare la cosiddetta “inline if” ossia l’operatore “?”, questa è l’istruzione equivalente:

in Orario = (onTimer < offTimer)?(OraAttuale >= onTimer && OraAttuale < offTimer):(OraAttuale >= onTimer || OraAttuale < offTimer);

Ma, come dicevo, è molto meno leggibile, come vedi.

E comunque di fatto inutile dato che il compilatore genera praticamente lo stesso codice, per cui puoi anche ignorare questa cosa.

O ancora, terzo modo, si può scrivere il tutto come singola espressione logica:

inOrario = (onTimer<offTimer && OraAttuale>=onTimer && OraAttuale<offTimer) || (onTimer>=offTimer && (OraAttuale>=onTimer || OraAttuale<offTimer));

In questo post c’era ancora un’altra soluzione per via aritmetica, ma l’if scritto per esteso rimane tra tutte il più leggibile e comprensibile :wink:

La verifica potrebbe anche essere fatta solo ogni 30 secondi o ogni 10: sarebbe già molto meno rispetto a farla centinaia (orientativamente: dipende dalla velocità con cui gira il loop) di volte al secondo e comunque idonea allo scopo.

Se lo spegnimento è impostato a un’orario minore di quello di accensione, ad esempio accensione alle 22 e spegnimento alle 7 (il giorno dopo), si potrebbe mettere una verifica:
if (offTimer<onTimer) {offTimer+=24*60;}
e poi una comparazione unica.

Datman:
La verifica potrebbe anche essere fatta solo ogni 30 secondi o ogni 10: sarebbe già molto meno rispetto a farla centinaia (orientativamente: dipende dalla velocità con cui gira il loop) di volte al secondo e comunque idonea allo scopo.

Si, ovviamente, ma in ogni caso con il codice che ho messo di fatto fa solo il controllo (d’altronde almeno l’ora deve leggerla ;)) ma non "agisce2 se non quando è necessario cambiare lo stato per cui non è che faccia nulla di particolare o pesante. :wink:

Certo, poi dipende anche da dove mette quel controllo e cosa altro faccia o debba fare e con quali eventuali tempistiche, comunque sia basta controllare se è cambiato l’orario. E’ sufficiente (credo) quando cambiano i minuti, quindi il controllo lo farà una volta ogni 60 secondi circa), ad esempio:

...
// Pin del relè (ex "relay3)
#define P_LUCI 3

#define SPENTO HIGH
#define ACCESO LOW
bool inOrario; // Indica se l'ora corrente è quella di accensione
int OraAttuale;
int OraPrec = -1;
...
void loop()
{
...  
  OraAttuale = now.hour() * 60 + now.minute();
  if ( OraAttuale != OraPrec ) {
    OraPrec = OraAttuale;
    onTimer = onora * 60 + onminuti;
    offTimer = offora * 60 + offminuti;
    // Determino se siamo nell'orario di accensione
    if (onTimer < offTimer)
      inOrario = (OraAttuale >= onTimer && OraAttuale < offTimer);
    else 
      inOrario = (OraAttuale >= onTimer || OraAttuale < offTimer);
    // Verifico lo stato del relè
    if ( inOrario && digitalRead(P_LUCI) == SPENTO) {
        digitalWrite(P_LUCI, ACCESO);
      if ( (OraAttuale >= onTimer || OraAttuale < offTimer) && digitalRead(P_LUCI) == ACCESO ) {
        digitalWrite(P_LUCI, SPENTO);
  }
...

Buongiorno Doc,

sto tentando di scrivere il codice così come da te indicato ma non mi funziona e non sto capendo dove sbaglio, gentilmente puoi darmi un occhi tu?

Grazie.

  void timer()
  {
   int onora = 10;      //IMPOSTO L'ORARIO PER L'ACCENSIONE DELLA LUCE
   int onminuti = 35;   //IMPOSTO L'ORARIO PER L'ACCENSIONE DELLA LUCE
   int offora = 20;     //IMPOSTO L'ORARIO PER LO SPEGNIMENTO DELLA LUCE
   int offminuti = 14;  //IMPOSTO L'ORARIO PER LO SPEGNIMENTO DELLA LUCE
   int onTimer;
   int offTimer;
   int OraAttuale;
   bool inOrario;        // indica ora corrente è quella di accensione
   int OraPrec = -1;


 DateTime now = rtc.now();
  
  if(now.hour() <10)
  {
    Serial.print("0");
  }
  Serial.print(now.hour());
  Serial.print(":");
if(now.minute() <10)
  {
    Serial.print("0");
  }
  Serial.print(now.minute());
  Serial.print(":");
if(now.second() <10)
  {
    Serial.print("0");
  }
  Serial.print(now.second());
  Serial.println(" ");

#define R_LUCI 4

#define ACCESO LOW
#define SPENTO HIGH


OraAttuale = now.hour() * 60 + now.minute();

if (OraAttuale != OraPrec)
{
    onTimer = onora * 60 + onminuti;
    offTimer = offora * 60 + offminuti;
}

if(onTimer < offTimer)
{
  inOrario = (OraAttuale >= onTimer && OraAttuale < offTimer);
}
else
{
  inOrario = (OraAttuale >= onTimer || OraAttuale < offTimer);
}
    if ( inOrario && digitalRead(R_LUCI) == SPENTO) {
        digitalWrite(R_LUCI, ACCESO);
         Serial.println("LUCE ON1");
}
    
     if((OraAttuale >= onTimer || OraAttuale < offTimer) && digitalRead(R_LUCI) == ACCESO) 
     {
        digitalWrite(R_LUCI, SPENTO);
     }
    }
if((OraAttuale >= onTimer || OraAttuale < offTimer)

mi sa che deve essere:
if((OraAttuale < onTimer || OraAttuale >= offTimer)

micky994:
sto tentando di scrivere il codice così come da te indicato ma non mi funziona e non sto capendo dove sbaglio, gentilmente puoi darmi un occhi tu?

Hm, volentieri, ma quello che hai postato non è un codice compilabile perché è incompleto (è solo una funzione “timer()” ma come/quando la usi/chiami?), poco coerente (ci sono degli “#include” in mezzo al codice, quelle costanti essendo di configurazione mettile in testa a tutto il codice!), e male indentato (usa il Ctrl-T dentro all’IDE, quantomeno prima di postarlo, te lo riformatta decentemente lui automaticamente).

Poi vedo che hai “manipolato” il codice che ti ho postato io: perché? Ad esempio io avevo scritto:

  if ( OraAttuale != OraPrec ) {
    OraPrec = OraAttuale;
    onTimer = onora * 60 + onminuti;
    offTimer = offora * 60 + offminuti;
    // Determino se siamo nell'orario di accensione
    if (onTimer < offTimer)
      inOrario = (OraAttuale >= onTimer && OraAttuale < offTimer);
    else
      inOrario = (OraAttuale >= onTimer || OraAttuale < offTimer);

tu invece hai aggiunto varie parentesi graffe, alcune di fatto inutili ma che ci possono anche stare, ma anche dove non dovevano esserci, ad esempio:

  if (OraAttuale != OraPrec)
  {
    onTimer = onora * 60 + onminuti;
    offTimer = offora * 60 + offminuti;
  } // <--- PERCHE'???

Capisci che la prima “if()” serviva per eseguire TUTTO il codice restante e non solo quelle due righe…

Ovviamente il codice che ti avevo scritto “al volo” era solo uno spunto e per di più solo parziale (non sapendo dove tu avresti messo quelle righe, visto che non hai postato l’intero tuo codice), però se in compilazione ti dà qualche errore o se non fa quello che ti aspetti che faccia, allora o cerchi di capire dove sia il problema oppure posta tutto il codice che non ti compila (indicando l’errore del compilatore) o che non funziona (in questo caso cosa fa / non fa?).

Poi ci sono variabili, come OraPrec, che dovrebbero essere globali, ossia vanno definite fuori da qualsiasi funzione perché devono mantenere il loro valore per tutta la durata del programma. I valori di configurazione poi (come i pin o i valori degli orari ad esempio) meglio metterli tutti in testa al codice per averli sott’occhio.

Infine le costanti per convenzione meglio metterle in maiuscolo (e magari come simboli “#define”).

Insomma, ecco un altro codice, dove ho fatto alcuni aggiustamenti e te l’ho indentato decentemente, e che ti ricordo essere parziale (se hai ancora bisogno di aiuto da ora per favore posta TUTTO il tuo codice) quindi devi inserire tu le parti mancanti:

// Parametri di configurazione
#define R_LUCI 4
// ORARIO ACCENSIONE DELLA LUCE
#define ON_ORA 10
#define ON_MIN 10
// ORARIO SPEGNIMENTO DELLA LUCE
#define OFF_ORA 20
#define OFF_MIN 14

// Altre costanti utili
#define ACCESO LOW
#define SPENTO HIGH

// Variabili globali
int onTimer;
int offTimer;
int OraAttuale;
int OraPrec = -1;

bool inOrario;   // indica che l'ora corrente è quella di accensione

void setup()
{
  ...
  onTimer = ON_ORA * 60 + ON_MIN;
  offTimer = OFF_ORA * 60 + OFF_MIN;
  ...
}

void loop()
{
  timer();
  ...
}

void timer()
{
  DateTime now = rtc.now();
  OraAttuale = now.hour() * 60 + now.minute();
  if ( OraAttuale != OraPrec ) {
    OraPrec = OraAttuale;
    // Determino se siamo nell'orario di accensione
    if (onTimer < offTimer)
      inOrario = (OraAttuale >= onTimer && OraAttuale < offTimer);
    else
      inOrario = (OraAttuale >= onTimer || OraAttuale < offTimer);
    // Verifico lo stato del relè
    // Se siamo in orario ed è spento, lo accendo
    if ( inOrario && digitalRead(P_LUCI) == SPENTO) {
      digitalWrite(P_LUCI, ACCESO);
      Serial.println("LUCE ON");
    }
    // Se non siamo in orario ed è acceso, lo spengo
    if ( !inOrario && digitalRead(P_LUCI) == ACCESO ) {
      digitalWrite(P_LUCI, SPENTO);
      Serial.println("LUCE OFF");
    }
  }
}

Grazie infinitamente Doc, ho apportato le modifiche del caso al codice seguendo i tuoi consigli e si presenta così:

#include <DS3232RTC.h>
#include <SimpleDHT.h>
#include <DS3231.h>
#include <Wire.h>
#include <Time.h>
#include <RTClib.h>

SimpleDHT22 dht22(5);
RTC_DS3231 rtc;
Time t;

#define R_TEMP 2
#define R_UMID 3
#define R_LUCE 4
#define R_VENTILATORE 8
#define P_BUZZER 7

#define ACCESO LOW
#define SPENTO HIGH

#define ON_ORA 10   // ORA ACCENSIONE
#define ON_MIN 15   // MINUTI ACCENSIONE
#define OFF_ORA 10  // ORA SPEGNIMENTO
#define OFF_MIN 30  // MINUTI SPEGNIMENTO

// Variabili globali
int onTimer;
int offTimer;
int OraAttuale;
int OraPrec = -1;

bool inOrario;   // indica che l'ora corrente è quella di accensione

unsigned long t1, dt1, t2, dt2;

void setup() 
{
    Tono();
    Serial.begin(115200);
    rtc.begin();
    pinMode(R_TEMP, OUTPUT);// PIN 2 OUTPUT
    pinMode(R_UMID, OUTPUT);// PIN 3 OUTPUT
    pinMode(R_LUCE, OUTPUT);// PIN 4 OUTPUT
    pinMode(R_VENTILATORE, OUTPUT);// PIN 8 OUTPUT
    pinMode(P_BUZZER, OUTPUT);// PIN 7 OUTPUT
    
    digitalWrite(R_TEMP, SPENTO); // IMPOSTO IL RELE' IN OFF DI DEFAULT
    digitalWrite(R_UMID, SPENTO); // IMPOSTO IL RELE' IN OFF DI DEFAULT
    digitalWrite(R_LUCE, SPENTO); // IMPOSTO IL RELE' IN OFF DI DEFAULT
    digitalWrite(R_VENTILATORE, SPENTO); // IMPOSTO IL RELE' IN OFF DI DEFAULT

    onTimer = ON_ORA * 60 + ON_MIN;
    offTimer = OFF_ORA * 60 + OFF_MIN;
}

void loop() {
    dt1 = millis() -t1; 
     if (dt1>= 1000){
      t1 = millis();
      Timer();
      Temperaturaumidita();
      }
    dt2 = millis() - t2;
      if (dt2 >= 500) {
       t2 = millis();
        Flash();
       }
}
  void Flash() //Sistema in esecuzione
  {
  digitalWrite(6, HIGH);
  delay(50);              
  digitalWrite(6, LOW);   
  delay(50);   
  }
  
  void Timer()
  {
 DateTime now = rtc.now();
 OraAttuale = now.hour() * 60 + now.minute();
  
  if(now.hour() <10){     
    Serial.print("0");
  }
  Serial.print(now.hour());
  Serial.print(":");
  if(now.minute() <10){
    Serial.print("0");
  }
  Serial.print(now.minute());
  Serial.print(":");
  if(now.second() <10){
    Serial.print("0");
  }
  Serial.print(now.second());
  Serial.println(" ");

  if ( OraAttuale != OraPrec ) {
    OraPrec = OraAttuale;
    // Determino se siamo nell'orario di accensione
    if (onTimer < offTimer)
      inOrario = (OraAttuale >= onTimer && OraAttuale < offTimer);
    else
      inOrario = (OraAttuale >= onTimer || OraAttuale < offTimer);
    // Verifico lo stato del relè
    // Se siamo in orario ed è spento, lo accendo
    if ( inOrario && digitalRead(R_LUCE) == SPENTO) {
      digitalWrite(R_LUCE, ACCESO);
      Serial.println("LUCE ON");
    }
    // Se non siamo in orario ed è acceso, lo spengo
    if ( !inOrario && digitalRead(R_LUCE) == ACCESO ) {
      digitalWrite(R_LUCE, SPENTO);
      Serial.println("LUCE OFF");
    }
  }
}
  
  void Temperaturaumidita()
   {
  float temperature = 0;
  float humidity = 0;
  dht22.read2(&temperature, &humidity, NULL);
  Serial.print((float)temperature); Serial.print(" °C, ");
  Serial.print((float)humidity); Serial.println(" %");
  
  if (temperature >= 20) {
    digitalWrite(R_TEMP, ACCESO); 
        }
    else{
      digitalWrite(R_TEMP, SPENTO);
      }
      if(humidity >= 90){
             digitalWrite(R_UMID, ACCESO); 
           }else{
            digitalWrite(R_UMID, SPENTO); 
           }
    }
    void Tono()
    {
      tone(P_BUZZER,1000,200);     //suona 
      delay(2000);                 //aspetta 2 secondi
      noTone(P_BUZZER);            //non suona
      delay(1000);
    }

il tutto sembra funzionare al meglio, ora devo però far accendere una ventola per far circolare l’aria all’interno della serra, e deve funzionare che 1 ora ogni 2 deve accendersi quindi un ora accesa e due spente, dovrei agire via RTC oppure creare un timer con una pausa di due ore su off e una su on a ciclo continuo?