/* c'è una piccola consol dove ci sono led e pulsanti
il pulsante RESET esiste, ma non viene menzionato anche perché è solo un collegamento fisico
esisteno altri 9 pulsanti
1 per tarare gli irrigatori
1 per fare una irrigazione saltuaria
1 per selezionare quale irrigazione si vuole avere
con altri 2 per incrementare o decrementare i numeri
1 per definire i tempi di irrigazione
con altri 2 per incrementare o decrementare i numeri
*/
#include <EEPROM.h>
#include <Arduino.h>
#include <TM1637Display.h>
//variabili che servono per il display
#define CLK 3
#define DIO 2
TM1637Display display(CLK, DIO);
int ritardoSuDisplay = 1000;// per dare il tempo di leggere il messaggio
// questo gestisce gli orari
#define Min_Mill 60000
#define Ore_Min 5
#define quar 40
#define ritardoIrrSalt 6000
//poichè i relè iniziano il collegamento al pin 41 si considererà nr - 40 = varrà come numero del pin
int Irrigatori[] = {
41, //goggia a goccia lato cucina
42, //irrigatore OS 140 lato sud
43, // irrigatore vicino garage
44, //goggia a goccia lato ovest garage
45, // irrigatore lato ovest
46, //irrigatore OS 140 lato nord ingresso
47 //goggia a goccia lato nord ingresso
};
//minimo da cui leggere e scrivere per le varie irrigazioni
#define StartOraIrr 700
#define MaxOraIrr 1023
byte OraLocMem = 1;
#define StartByte 0
#define MaxByte 254
// variabili che servono per il debouncing dei pulsanti
unsigned long tempodb = 0;
#define deb_delay 200
//servono per la pausa
//considerando l'ora di accensione alle 12 mezzogiorno
// fino alle 12 di notte sono: 12 ore che in mille secondi sono:
// 12 x 60 x 60 x 1000 = 43200000 millisecondi
// poi sarà ogni 24 ore quindi 86.400.000 millisecondi
unsigned long intervallo = 43200000;
unsigned long oraInizio = 0;
unsigned long oraFine = 0;
#define giorno 86400000
// quanti irrigatori, quante voci sono? questo se si aggiungono altri irrigatori
#define LunArr sizeof(Irrigatori) / sizeof(Irrigatori[0])
/**** PULSANTI ***/
//Pulsante e variabile per irrigazione saltuaria
#define Pin_Saltuaria 4
//Pulsante per tarare gli irrigatori
#define Pin_Taratura 5
//Pulsante per VARIARE I TEMPI DI IRRIGAZIONE
#define Pin_Tempi_Taratura 6
#define INC_Tempi_Taratura 8
#define DEC_Tempi_Taratura 9
//Pulsante per cambio orario gli irrigatori
#define Pin_Var_Orario 7
#define INC_Pin_Var_Orario 10
#define DEC_Pin_Var_Orario 11
//led di segnalzaione
#define led_Taratura 22
#define led_Orario 23
#define led_Irrigo 24
//costanti di messaggio
const char ciao = 'CIAO'; //OK
const uint8_t SEG_CIAO[] = {
SEG_A | SEG_D | SEG_D | SEG_E | SEG_F, // C
SEG_B | SEG_C, // I
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // A
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F
}; // O
const char salt = 'salt'; //OK
const uint8_t SEG_SALT[] = {
SEG_A | SEG_C | SEG_D | SEG_F | SEG_G, // S
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // A
SEG_D | SEG_F | SEG_E, // L
SEG_E | SEG_F | SEG_G | SEG_D
};//t
const char tara = 'tara'; //OK
const uint8_t SEG_TARA[] = {
SEG_E | SEG_F | SEG_G | SEG_D, //t
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // A
SEG_E | SEG_G, // r
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G // A
};
//const char fine = 'fin'; //OK
const char end = 'end'; //OK
const uint8_t SEG_END[] = {B01111001, B01010100, B01011110, B00000000};
const char done = 'done'; //OK
const uint8_t SEG_DONE[] = {
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // d
SEG_C | SEG_D | SEG_E | SEG_G, // O
SEG_C | SEG_E | SEG_G, // n
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G
}; // E
const char orario = 'orar'; //OK
const uint8_t SEG_ORAR[] = {B00111111, B01010000, B01110111, B01010000};
//const char ir = 'ir'; //OK
const uint8_t SEG_IR[] = {B00010000, B01010000};
//const char t = 't'; //OK
const uint8_t SEG_T[] = {B01111000};
const char irri = 'irri'; //OK
const uint8_t SEG_IRRI[] = {B00010000, B01010000, B01010000, B00010000};
const char pros = 'pros'; //OK
const uint8_t SEG_PROS[] = {B01110011, B01010000, B01011100, B01101101};
const char totx = 'totx';
const uint8_t SEG_TOTX[] = {B01111000, B01011100, B01111000, B01011111};
const char clear = 'cz'; //OK
const char play = 'play';
const uint8_t PLAY[] = {B01110011, B00111000, B01011111, B01101110};
const uint8_t celsius[] = {B01100011};
void setup()
{
//***********************************************/
//questo dipende dall'Arduino utilizzato
#define UltimoPinInput 13 // logici + analogici
#define PrimoPinInput 2 //i primi 2 sono inutilizzzabili
Serial.begin(9600);// questo deve essere messo per forza qui
for (byte x = PrimoPinInput; x < UltimoPinInput; x++) {
//pinMode(x, OUTPUT);
pinMode(x, INPUT);
}
// io non conoscevo i relè a 'comando alto' anche se consigliato da Standardoil per cui ho comprato i relè sbagliati
#define ReleSpento HIGH
#define ReleAcceso LOW
#define UltimoPinOutput 53 // logici
#define PrimoPinOutput 30
for (byte x = PrimoPinOutput; x < UltimoPinOutput; x++) {
pinMode(x, OUTPUT);
digitalWrite(x, ReleSpento);
}
display.setBrightness(0x0f);
visStringa(ciao);
visStringa(pros);
visStringa(irri);
VisualizzaOrario( OraIrrigazione());
delay(ritardoSuDisplay);
visStringa(clear);
}
void loop()
{
/* questa pausa serve sia per l'avviamento alle 12
sia per l'irrigazione giornaliera a mezzanotte
*/
pausa(intervallo);
//digitalWrite(led_Irrigo, HIGH);
// immagazzino l'ora di inizio perché non so quanto dura l'irrigazione
unsigned long oraInizioIrr = millis();
byte oraIrrigaz = 0;
OraLocMem = 0;//perché viene riportato subito a 1
byte MinutiDaMezzanotte = 0;
for (int Ora = (StartOraIrr ); Ora < MaxOraIrr; Ora++) {
OraLocMem++;
oraIrrigaz = OraIrrigazione();
if (oraIrrigaz > 0 )
{
pausa((oraIrrigaz - MinutiDaMezzanotte) * Ore_Min * Min_Mill );
digitalWrite(led_Irrigo, HIGH);
IrrigazioneSaltuaria();
digitalWrite(led_Irrigo, LOW);
display.clear();
MinutiDaMezzanotte += oraIrrigaz;
}
}
unsigned long oraFineIrr = millis();
intervallo = giorno - (oraFineIrr - oraInizioIrr );
//visPosizione( 13);
digitalWrite(led_Irrigo, LOW);
display.clear();
} //loop
/******effettua la pausa desiderata
**********************************
**************************************
**************************************
*/
void pausa(long unsigned attesa ) {
/*********************************************
qua si blocca ed attende
**********************************************/
oraInizio = millis();
do // questo è il blocco principale
{
/*********************************************
IRRIGAZIONE SALTUARIA
**********************************************/
if (digitalRead(Pin_Saltuaria))
{
// Serial.println("IrrigazioneSaltuaria dal blocco proncipale");
//deciderer dove accendere i led
bool procedo = true;
if (debouncing()) {
visStringa(irri);
visStringa(salt);
visPosizione(OraLocMem);
/******************
questo viene messo per avere la possibilità di annullare
l'irrigazione saltuaria ed effettuarne un'altra
*************************/
for (int k = 0; k < ritardoIrrSalt; k++)
{
if (digitalRead(Pin_Taratura)) {
if (debouncing()) {
VisualizzaTutto();
}
}
if (digitalRead(Pin_Saltuaria)) {
if (debouncing()) {
procedo = false;
visStringa(end);
break;
}
}
}
// se non è stata annullata
if (procedo) {
IrrigazioneSaltuaria();
}
visStringa(done);
visStringa(clear);
}
}
/*********************************************
TARATURA GETTO DEGLI IRRIGATORI
**********************************************/
if (digitalRead(Pin_Taratura))
{
//Serial.println("ProvaIrrigatori dal blocco proncipale");
if (debouncing()) {
visStringa(tara);
//visPosizione(40 );
ProvaGettoIrrigatori();
//visPosizione(401 );
visStringa(end);
visStringa(clear);
}
}
/*********************************************
MODIFICA GLI ORARI NOTTURNI DI IRRIGAZIONE
**********************************************/
if (digitalRead(Pin_Var_Orario))
{
if (debouncing()) {
// Serial.println("modifica orari irrigazione");
visStringa(orario);
// visPosizione( 60);
OrariIrrigazione();
// visPosizione(601 );
visStringa(done);
visStringa(clear);
}
}
oraFine = millis();
} while ((oraFine - oraInizio) < attesa );
} // pausa
/*irrigazione saltuaria*/
void IrrigazioneSaltuaria() {
for (byte y = 0; y < LunArr; y++) {
byte minuti = MinutiIrrigazione( Irrigatori[y]);
visNumero(minuti);
VisNrIrrigatore (Irrigatori[y]);
VisMinIrrigatore (minuti);
//visPosizione(33);
if (minuti > 0 ) {
//visPosizione(34);
digitalWrite(led_Irrigo, HIGH);
digitalWrite(Irrigatori[y], ReleAcceso);
Attendi(minuti);
digitalWrite(Irrigatori[y], ReleSpento);
// visPosizione(35);
digitalWrite(led_Irrigo, LOW);
}
}//for
}//IrrigazioneSaltuaria
/* blocca acceso gli irrigatori per
orientare il getto*/
void ProvaGettoIrrigatori() {
digitalWrite(led_Irrigo, HIGH);
for (byte y = 0; y < LunArr; y++) {
//visPosizione(41 );
VisNrIrrigatore (Irrigatori[y]);
digitalWrite(Irrigatori[y], ReleAcceso);
bool prossimo = true;
do {
if (digitalRead(Pin_Taratura))
{
if (debouncing()) {
prossimo = false;
}
}
} while (prossimo);
digitalWrite(Irrigatori[y], ReleSpento);
}//(byte y = 0; y < LunArr; y++)
//visPosizione( 42);
//visStringa(end);
//clear c'è dopo
digitalWrite(led_Irrigo, LOW);
}//ProvaGettoIrrigatori
/********************************
questo serve per modificare gli orari di
irrigazione notturni
*************************************/
void OrariIrrigazione() {
digitalWrite(led_Orario, HIGH);
bool PossoTarare = true;
//visPosizione(61);
visStringa(orario);
visPosizione(OraLocMem);
VisualizzaOrario(OraIrrigazione());
do {
if (digitalRead(Pin_Tempi_Taratura)) {
if (debouncing()) {
// visPosizione(62);
ModOrarioIrrNotturno();
// visPosizione(63);
visPosizione(OraLocMem);
VisualizzaOrario(OraIrrigazione());
}
}
/************************************
da qui si gestisce i vari orari di irrigazione notturni
*************************************/
if (digitalRead(Pin_Var_Orario)) {
if (debouncing()) {
PossoTarare = false;//per chiudere
break;//*******************************************
//Serial.println(" chiudo PossoTarare");
//visPosizione(64 );
}
}
if (digitalRead(INC_Pin_Var_Orario)) {
if (debouncing()) {
/*Serve solo ad incrementare o a diminuire il valore di OraLocMem*/
if (OraLocMem < (MaxOraIrr - StartOraIrr)) {
OraLocMem++;
//Serial.println("");
visPosizione(OraLocMem);
//visPosizione( 65);
VisualizzaOrario(OraIrrigazione());
}
}
}
if (digitalRead(DEC_Pin_Var_Orario)) {
if (debouncing()) {
/*Serve solo ad incrementare o a diminuire il valore di OraLocMem*/
if (OraLocMem > 1) {
OraLocMem--;
/*Serial.println("");
Serial.println(OraLocMem);*/
visPosizione(OraLocMem);
//visPosizione(66 );
VisualizzaOrario(OraIrrigazione());
}
}
}
/*********************************************
VISUALIZZA IL TEMPO DI TUTTI GLI IRRIGATORI SENZA MODIFICARLI
**********************************************/
if (digitalRead(Pin_Taratura))
{
if (debouncing()) {
VisualizzaTutto();
visStringa(orario);
visPosizione(OraLocMem);
VisualizzaOrario(OraIrrigazione());
}
}
} while (PossoTarare);
digitalWrite(led_Orario, LOW);
}//OrariIrrigazione ModificaOrari
/*********************************************
VISUALIZZA IL TEMPO DI TUTTI GLI IRRIGATORI SENZA MODIFICARLI
**********************************************/
void VisualizzaTutto() {
int totaleOra = 0;
for (byte y = 0; y < LunArr; y++) {
byte minuti = MinutiIrrigazione(Irrigatori[y]);
totaleOra = totaleOra + minuti;
VisNrIrrigatore (Irrigatori[y]);
VisMinIrrigatore (minuti);
}//for (byte y = 0; y < LunArr; y++)
visStringa(totx);
visNumero(totaleOra);
delay(ritardoSuDisplay);
display.clear();
}//VisualizzaTutto
/************************************************
MODIFICA L'ORARIO NOTTURNO DI IRRIGAZIONE
**************************************************/
void ModOrarioIrrNotturno() {
digitalWrite(led_Taratura, HIGH);
byte orario = OraIrrigazione();
bool condizione = true;//esce dal loop
visStringa(play);
VisualizzaOrario(orario);
do {
//esce dal loop
if (digitalRead(Pin_Tempi_Taratura )) {
if (debouncing()) {
condizione = false;
EEPROM.update((OraLocMem + StartOraIrr), orario);
visStringa(done);
break;
}
}
if (digitalRead(INC_Tempi_Taratura)) {
if (debouncing()) {
orario++;
VisualizzaOrario(orario);
}
}
if (digitalRead(DEC_Tempi_Taratura )) {
if (debouncing()) {
orario--;
VisualizzaOrario(orario);
}
}
if (digitalRead(Pin_Taratura))
{
if (debouncing()) {
TaraDurataIrrigatori();
}
}
} while (condizione);//do
digitalWrite(led_Taratura, LOW);
visStringa(clear);
}//ModOrarioIrrNotturno
/************************************************
AGGIORNA DURATA DI IRRIGAZIONE
**************************************************/
void TaraDurataIrrigatori() {
digitalWrite(led_Irrigo, HIGH);
for (byte y = 0; y < LunArr; y++) {
int LocMemMinuti = ((OraLocMem * LunArr) + Irrigatori[y]);
bool condizione = true;//esce dal loop ed avanza y
byte MinutiXIrrigatore = MinutiIrrigazione(Irrigatori[y]);
VisNrIrrigatore (Irrigatori[y]);
VisMinIrrigatore (MinutiXIrrigatore);
do {
if (digitalRead(Pin_Taratura)) {
//questo permette di avanzare di un irrigatore
if (debouncing()) {
condizione = false;
break;
}
}
if (digitalRead(Pin_Tempi_Taratura)) {
if (debouncing()) {
EEPROM.update((LocMemMinuti), MinutiXIrrigatore);
VisNrIrrigatore (Irrigatori[y]);
VisMinIrrigatore (MinutiXIrrigatore);
visStringa(done);
VisNrIrrigatore (Irrigatori[y]);
}
}
if (digitalRead(INC_Tempi_Taratura) ) {
if (debouncing()) {
MinutiXIrrigatore++;
VisMinIrrigatore (MinutiXIrrigatore);
}
}
if (digitalRead(DEC_Tempi_Taratura) ) {
if (debouncing()) {
MinutiXIrrigatore--;
VisMinIrrigatore (MinutiXIrrigatore);
}
}
} while (condizione);
}//(byte y = 0; y < LunArr; y++)
digitalWrite(led_Irrigo, LOW);
}//TaraIrrigatori
/*Routin che aspetta il tempo
che dovrebbero essere minuti
In questa routin si potrebbe misurare il tempo che la differenza*/
void Attendi (unsigned long tempoAtt) {
tempoAtt = tempoAtt * Min_Mill;//1 Minuti = 60000 Millisecondi
unsigned long previousMillis = millis();
unsigned long currentMillis = 0;
do {
currentMillis = millis();
} while ((currentMillis - previousMillis) < tempoAtt);
//visPosizione(42);
}
/* questa routine serve per evitare che il pulsante invii doppio click
**************************
*/
bool debouncing() {
unsigned long precedenteMillis = millis();
if (( precedenteMillis - tempodb) > deb_delay) {
tempodb = precedenteMillis;
return true;
} else {
return false;
}
}//debouncing
//legge l'orario
byte OraIrrigazione() {
byte orairr = EEPROM.read(OraLocMem + StartOraIrr);
if ((orairr > StartByte) && (orairr < MaxByte)) {
return orairr;
} else {
return 0;
}
}
byte MinutiIrrigazione(byte irrigatore) {
byte min = EEPROM.read((OraLocMem * LunArr) + irrigatore) ;
if ((min > StartByte) && (min < MaxByte)) {
return min;
} else {
return 0;
}
}
/*************************************
***********VISUALIZZA SUL DISPLAY************
* *******************************************
* ********************************/
void VisNrIrrigatore (byte NrIrrigatore)
{
display.setSegments(celsius, 1, 1);
display.setSegments(SEG_IR, 2, 2);
display.showNumberDec(NrIrrigatore - quar, false, 1, 0);
delay(ritardoSuDisplay);
}
void VisMinIrrigatore (byte MinIrrigatore)
{
display.setSegments(SEG_T, 1, 0);
display.showNumberDec(MinIrrigatore, false, 3, 1);
delay(ritardoSuDisplay);
}
void VisualizzaOrario(int Ora) {
int Orario = 0;
Ora = Ora * 5;
int PP = Ora / 60;
int PS = (Ora % 60);
Orario = (PP * 100) + PS;
display.showNumberDecEx(Orario, 0b11100000, true, 4, 0);
}
void visPosizione (int numero) {
display.clear();
display.setSegments(celsius, 1, 3);
byte Posizione = 2;
byte q = 1;
if (numero > 9) {
Posizione = 1;
q = 2;
}
if (numero > 99) {
Posizione = 0;
q = 3;
}
display.showNumberDec(numero, false, q, Posizione);
delay(ritardoSuDisplay);
}
void visNumero(int numero) {
display.showNumberDec(numero, false, 4, 0);
delay(ritardoSuDisplay);
}
void visStringa(char stringa) {
// prende l'ultima lettera del valore della stringa
switch (stringa) {
case tara:
display.setSegments(SEG_TARA);
break;
case done:
display.setSegments(SEG_DONE);
break;
case end:
display.setSegments(SEG_END);
break;
case ciao:
display.setSegments(SEG_CIAO);
break;
case orario:
display.setSegments(SEG_ORAR);
break;
case irri :
display.setSegments(SEG_IRRI);
break;
case pros:
display.setSegments(SEG_PROS);
break;
case salt:
display.setSegments(SEG_SALT);
break;
case totx:
display.setSegments(SEG_TOTX);
break;
case play:
display.setSegments(PLAY);
break;
default:
display.clear();
break;
}
delay(ritardoSuDisplay);
}
type or paste code here