/*
*
* Questo software è di proprieta di Ciro Marciano
*
* E' permesso l'utilizzo, compresa la modifica, di questo software,
* esclusivamente per uso personale.
*
* L’utente non è autorizzato a pubblicare, trasmettere, condividere,
* cedere in uso a qualsiasi titolo, distribuire, dare accesso o sfruttare
* commercialmente in qualsiasi modo, anche solo parzialmente, il presente software.
*
* Questo programma è distribuito senza alcuna garanzia.
*/
// Questo programma usa due librerie
#include <DS1307RTC.h> // per la comunicazione con il modulo DS1307
#include <Wire.h>
#include <TimerOne.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Definizione dei piedini
int LED_ROSSO = 2; // Il LED rosso è collegato al piedino D2
int LED_BLU = 3; // Il LED giallo è collegato al piedino D3
int LED_VERDE = 4; // Il LED verde è collegato al piedino D4
int PULSANTE = 5; // Il pulsante è collegato al piedino D5
int BUZZER = 6; // pin del buzzer
// Definizione del programma iniziale
int PROGRAMMA=2;
// Definizione degli orari
// L'alba inizia alle 8:00
long ORA_INIZIO_ALBA=8;
long MIN_INIZIO_ALBA=0;
// E finisce alle 9:00
long ORA_FINE_ALBA=9;
long MIN_FINE_ALBA=0;
// Il tramonto inizia alle 17:00
long ORA_INIZIO_TRAM=17;
long MIN_INIZIO_TRAM=0;
// e finisce alle 18:00
long ORA_FINE_TRAM=18;
long MIN_FINE_TRAM=0;
// Convertiamo le ore e i minuti in numero di secondi dalla mezzanotte.
long TEMPO_INIZIO_ALBA=60L*MIN_INIZIO_ALBA+3600L*ORA_INIZIO_ALBA;
long TEMPO_FINE_ALBA=60L*MIN_FINE_ALBA+3600L*ORA_FINE_ALBA;
long TEMPO_INIZIO_TRAM=60L*MIN_INIZIO_TRAM+3600L*ORA_INIZIO_TRAM;
long TEMPO_FINE_TRAM=60L*MIN_FINE_TRAM+3600L*ORA_FINE_TRAM;
// Variabili per l'orologio.
DS1307RTC Clock;
bool secolo=false;
bool h12=false;
bool PM=false;
// La funzione setup viene eseguita una volta sola,
// appena Arduino viene acceso. Serve per inizializzare il sistema.
void setup() {
lcd.init();
lcd.backlight();
tone(BUZZER, 2400, 30);
delay(140);
tone(BUZZER, 2400, 30);
delay(140);
tone(BUZZER, 2400, 30);
delay(140);
lcd.setCursor(0, 0);
lcd.print(" CENTRALINA ");
lcd.setCursor(0, 1);
lcd.print(" ACQUARIO ");
delay(2500);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" VERSIONE ");
lcd.setCursor(0, 1);
lcd.print(" FIRMWARE 1.0.1 ");
delay(1000);
// inizializiamo i piedini collegati ai LED di controllo
pinMode(LED_ROSSO, OUTPUT);
pinMode(LED_BLU, OUTPUT);
pinMode(LED_VERDE, OUTPUT);
pinMode(BUZZER, OUTPUT);
// inizializiamo il piedino del pulsante
pinMode(PULSANTE,INPUT);
digitalWrite(PULSANTE, HIGH);
// Inizializziamo il collegamento con l'orologio
Wire.begin();
// Apriamo un collegamento con la porta seriale, per poter regolare l'ora
Serial.begin(9600);
}
// La funzione loop viene eseguita subito dopo la funzione setup e
// ripetuta all'infinito.
void loop() {
// Andiamo a vedere se il pulsante è stato premuto
if (leggiPulsante(PULSANTE)){
// Cambiamo di programma, se è stato premuto il pulsante
PROGRAMMA=(PROGRAMMA+1)%3;
}
// Regoliamo il livello dei LED, a secondo del programma
regolaLivelloLed();
// Controlliamo se è stato scritto qualcosa nella porta seriale
if (Serial.available()) {
LeggiDataOraDS1307();
}
// Aspettiamo 500ms prima di ricominciare
delay(500);
}
// Funzione che legge data e ora dalla porta seriale
// La data e l'ora devono essere dati con il formato GGMMAAHHmmSS, ovvero
// GG: il giorno del mese (15 per il 15)
// MM: il mese (01 per Gennaio)
// AA: l'anno (ad esempio 19 per 2019)
// HH: ora del giorno (18 per le 6 del pomeriggio)
// mm: minuti
// SS: secondi
// Esempio: per regolare l'orologio alle 18:23:12 del 5 gennaio 2019, bisogna scrivere 050119182312.
void LeggiDataOraDS1307(){
tmElements_t tm;
RTC.read(tm);
//Serial.print(tmElements_t);
/*void leggiDataOraPortaSeriale(){
boolean finito = false;
byte dati[12];
byte j=0;
boolean corretto=true;
while (!finito) {
if (Serial.available()) {
char carattere = Serial.read();
if (!isDigit(carattere)) {
finito = true;
corretto=false;
Serial.println("Formato data e ora non corretto. Il formato corretto e': GGMMAAHHmmSS.");
} else {
dati[j]=(byte)carattere-48;
}
if (j==11) finito=true;
j += 1;
}
}
if (corretto){
RTC.set(false);
// Regola il giorno
RTC.set(dati[0]*10+dati[1]);
// Regola il mese
RTC.set(dati[2]*10+dati[3]);
// Regola l'anno
RTC.set(dati[4]*10+dati[5]);
// Regola l'ora
RTC.set(dati[6]*10+dati[7]);
RTC.set(dati[8]*10+dati[9]);
RTC.set(dati[10]*10+dati[11]);
Serial.println("Data e ora impostata");
}
Serial.println("Data e ora presente:");
Serial.print(RTC.get(), DEC);
Serial.print("/");
Serial.print(RTC.get(secolo), DEC);
Serial.print("/20");
Serial.print(RTC.get(), DEC);
Serial.print(" ");
Serial.print(RTC.get(h12, PM), DEC);
Serial.print(":");
Serial.print(RTC.get(), DEC);
Serial.print(":");
Serial.println(RTC.get(), DEC); */
}
// Funzione che regola il livello dei LED
void regolaLivelloLed(){
int livello_caldi; // Variabile con il livello dei LED bianco caldo
int livello_freddi; // Variabile con il livello dei LED bianco freddo
if (PROGRAMMA==0) { // Se programma è uguale a 0:
digitalWrite(LED_ROSSO, HIGH); // Accendi il LED rosso
digitalWrite(LED_BLU, LOW); // Spegni il LED giallo
digitalWrite(LED_VERDE, LOW); // Spegni il LED verde
// Settiamo il livello dei LED a 0
livello_caldi=0;
livello_freddi=0;
} else if (PROGRAMMA==1){ // Se programma è uguale a 1:
digitalWrite(LED_ROSSO, LOW); // Spegni il LED rosso
digitalWrite(LED_BLU, HIGH); // Accendi il LED giallo
digitalWrite(LED_VERDE, LOW); // Spegni il LED verde
} else {
digitalWrite(LED_ROSSO, LOW); // Spegni il LED rosso
digitalWrite(LED_BLU, LOW); // Spegni il LED giallo
digitalWrite(LED_VERDE, HIGH); // Accendi il LED verde
// Settiamo il livello dei LED secondo il fotoperiodo
float livello=calcolaLivello();
}
// Applichiamo ai LED il livello calcolato
}
// Questa funzione serve a leggere se il pulsante viene premuto.
// Per leggere correttamente il pulsante, vogliamo che la lettura sia stabile
// per almeno 10 millisecondi.
boolean leggiPulsante(int pin) {
boolean stato;
// Leggiamo lo stato iniziale del pulsante
boolean statoIniziale = digitalRead(pin);
for(int i=0; i < 10; i++) {
// Aspettiamo 1 millisecondo
delay(1);
stato = digitalRead(pin); // Leggiamo di nuovo lo stato del pulsante
if (stato != statoIniziale) {
// Se lo stato del pulsante è cambiato, ricominciamo
i = 0;
statoIniziale = stato;
}
}
// restituisce true se il pulsante è stato premuto
return !stato;
}
// Funzione per calcolare il livello di luminosità (rispetto al massimo) in funzione del tempo
float calcolaLivello(){
// Leggiamo che ora è, e convertiamo tutto in secondi dalla mezzanotte
long ore=RTC.get()*60L;
long minuti=RTC.get()*60L;
long secondi=RTC.get();
long tempo=secondi+minuti+ore;
float livello=0.0;
if (tempo >= TEMPO_FINE_ALBA && tempo <= TEMPO_INIZIO_TRAM){
//Se siamo tra la fine dell'alba e l'inizio del tramonto, livello di luminosità è massima
livello=1.0; //
} else if (tempo > TEMPO_INIZIO_ALBA && tempo < TEMPO_FINE_ALBA){
// Se siamo durante l'alba, livello di luminosità aumenta linearmente con il tempo
livello=(tempo-TEMPO_INIZIO_ALBA)*1.0/(TEMPO_FINE_ALBA-TEMPO_INIZIO_ALBA);
} else if (tempo > TEMPO_INIZIO_TRAM && tempo < TEMPO_FINE_TRAM){
// Se siamo durante il tramonto, livello di luminosità diminuisce linearmente con il tempo
livello=(TEMPO_FINE_TRAM-tempo)*1.0/(TEMPO_FINE_TRAM-TEMPO_INIZIO_TRAM);
}
return livello;
}