Automazione lightbox per pepper

Buonasera, contemporaneamente alla serra automatizzata sto realizzando l’automazione di un lightbox, che è una “scatola” in polistirolo con delle luci temporizzate giornalmente per la coltivazione indoor di peperoncini, con l’ausilio di una ventola per diminuzione di temperatura e ricambio d’aria.

Ho a disposizione un arduino UNO, scheda a due relè, RTC DS3231 e logicamente un alimentatore per la scheda che setterò a 9V, alimentando anche la stessa ventola (classica ventola da pc) in modo da farla girare più lentamente…

Lo sketch sottostante per ora accende le luci dalle 8 alle 22 e avvia la ventola per tutta la durata dell’accensione delle luci.
Se volessi alimentare la ventola una volta all’ora per 15minuti come potrei fare?

Per un progettino del genere serve l’RTC?
Non mi serve la precisione del minuto, mi basta nell’ordine dei 5 o 10 minuti. Leggevo di una libreria swRTC, secondo voi può fare al caso mio?

Ho dato un’occhiata pure ai millis ma sembrano un pochino ostici :smiley:

Cosa mi consigliate?
Grazie mille :wink:

#include <DS3232RTC.h> //http://github.com/JChristensen/DS3232RTC
#include <Time.h>      //http://www.arduino.cc/playground/Code/Time  
#include <Wire.h>      //http://arduino.cc/en/Reference/Wire

// DEFINIZIONE OGGETTI
#define pinLuce 7
#define pinVentola 8
int ora = hour();
int orainizio = 8;
int orafine = 22;

void setup(void)
{
  Serial.begin(9600);
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if (timeStatus() != timeSet)
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");
}


void loop(void)
{
  digitalClockDisplay();
  delay(1000);
  if ( ora >= orainizio && ora <= orafine  )
  {
    digitalWrite( pinLuce, LOW ); //attivo luce
  }
  else
  {
    digitalWrite( pinLuce, HIGH ); //spengo luce
  }
  if (pinLuce == LOW)
    if ()
  {
    digitalWrite( pinVentola, LOW ); //attivo ventola
  }
  else
  {
    digitalWrite( pinVentola, HIGH ); //spengo ventola
  }

}

void digitalClockDisplay(void)
{
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(' ');
  Serial.print(day());
  Serial.print(' ');
  Serial.print(month());
  Serial.print(' ');
  Serial.print(year());
  Serial.println();
}

void printDigits(int digits)
{
  // utility function for digital clock display:
  // prints preceding colon and leading 0
  Serial.print(':');
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

Mi sembra che tu abbia bisogno di una certa precisione e che la cosa debba funzionare per giorni, quindi ... ... dimentica l'uso di millis(), Arduino NON è sufficientemente preciso sui tempi lunghi. Per cui ... ti occorre necessariamente un BUON RTC (con un semplice DS1307 hai comunque un errore di ± svariati secondi al giorno) tipo il DS3231.

Guglielmo

L’RTC da te citato è già montato e funzionante :smiley:

Saresti così gentile da darmi uno spunto per implementare il codice qui sotto in modo che la ventola si accenda ogni ora per 15 minuti verificato che le luci siano accese? Nel codice fatto da me dovrebbe “credo” rimanere in moto fino a quando le luci non si spengono.

riposto il codice corretto, c’era un refuso nel precedente.

#include <DS3232RTC.h> //http://github.com/JChristensen/DS3232RTC
#include <Time.h>      //http://www.arduino.cc/playground/Code/Time 
#include <Wire.h>      //http://arduino.cc/en/Reference/Wire

// DEFINIZIONE OGGETTI
#define pinLuce 7
#define pinVentola 8
int ora = hour();
int orainizio = 8;
int orafine = 22;

void setup(void)
{
  Serial.begin(9600);
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if (timeStatus() != timeSet)
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");
}


void loop(void)
{
  digitalClockDisplay();
  delay(1000);
  if ( ora >= orainizio && ora <= orafine  )
  {
    digitalWrite( pinLuce, LOW ); //attivo luce
  }
  else
  {
    digitalWrite( pinLuce, HIGH ); //spengo luce
  }
  if (pinLuce == LOW)
  {
    digitalWrite( pinVentola, LOW ); //attivo ventola
  }
  else
  {
    digitalWrite( pinVentola, HIGH ); //spengo ventola
  }

}

void digitalClockDisplay(void)
{
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(' ');
  Serial.print(day());
  Serial.print(' ');
  Serial.print(month());
  Serial.print(' ');
  Serial.print(year());
  Serial.println();
}

void printDigits(int digits)
{
  // utility function for digital clock display:
  // prints preceding colon and leading 0
  Serial.print(':');
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

nessuno? :(

Direi che la soluzione potrebbe essere quella di implementare prima di tutto bene la SOLA accensione delle luci negli orari che vuoi tu ... ... una volta che questo funziona bene, quando accendi la luce metti una flag a true per indicare che le luci sono accese, e quando le spegni metti la stessa flag a false per indicare che sono spente ... in questo modo, in qualsiasi momento, sai se le luci sono accese o spente semplicemente guardando il valore della flag.

Il terzo ed ultimo passo è aggiungere nel loop() ancora un cosa ... SE cambia l'ora (ora_precedente != ora_attuale) ti chiedi se le luci sono accese o meno (hai la flag che te lo indica), se sono accese accendi la ventola, memorizzi i millis() e, dopo 900000 millisecondi la spegni (o se si spengono le luci).

SE non sei pratico nell'uso della millis(), ti consiglio di studiare prima QUI, poi QUI ed infine leggi anche QUI e QUI.

Guglielmo

Grazie mille Guglielmo, sei di grande aiuto!

Ho applicato il consiglio dei flag (spero bene :smiley: ) ma al posto dei millis ho usato comunque l’RTC in questo modo:

#include <DS3232RTC.h> //http://github.com/JChristensen/DS3232RTC
#include <Time.h>      //http://www.arduino.cc/playground/Code/Time  
#include <Wire.h>      //http://arduino.cc/en/Reference/Wire

// DEFINIZIONE OGGETTI
#define pinLuce 7
#define pinVentola 8
int ora = hour();
int orainizio = 0;
int orafine = 22;
int durataminuti = 15;
int flag = 0;

void setup(void)
{
  Serial.begin(9600);
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if (timeStatus() != timeSet)
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");
}


void loop(void)
{
  digitalClockDisplay();
  delay(1000);
  // Accensione e spegnimento luci con orario stabilito
  if ( hour() >= orainizio and hour() <= orafine )
  {
    digitalWrite( pinLuce, LOW ); //attivo luce
    flag = 1;
    Serial.print("Luci accese");
  }
  else
  {
    digitalWrite( pinLuce, HIGH ); //spengo luce
    flag = 0;
    Serial.print("Luci spente");
  }
  // Ventola in moto 15 minuti ogni ora solo se le luci sono accese
  if (flag == 1 and minute() <= durataminuti)
  {
    digitalWrite( pinVentola, LOW ); //accendo ventola
    Serial.print("Ventola in moto");
  }
  else
  {
    digitalWrite( pinVentola, HIGH ); //Spengo ventola
    Serial.print("Ventola ferma");
  }
}

void digitalClockDisplay(void)
{
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(' ');
  Serial.print(day());
  Serial.print(' ');
  Serial.print(month());
  Serial.print(' ');
  Serial.print(year());
  Serial.println();
}

void printDigits(int digits)
{
  // utility function for digital clock display:
  // prints preceding colon and leading 0
  Serial.print(':');
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

In pratica la ventola sta accesa solo se verificata il flag==1, e solo se i minuti sono inferiori o uguali a 15… Che ne pensi?

L’ho provato e mi sembra funzioni, spero non mi scappi qualcosa :slight_smile:

Si, è un altro modo, e dato che funziona ... va bene :)

Guglielmo

P.S.: Impara comunque ad usare la millis() ... non sempre esiste una soluzione più facile ... ;)

Grazie Guglielmo, al più presto me li studio... ;)