Mi scuso per la scarsa tecnicità del mio post. Sto cercando di far venire al mondo la mia centralina di irrigazione. Dotazione: Arduino Mega, RTC, LCD, Tastierino 3X4; Modulo relè 2 canali; Sensore umidità terreno. Circuiti corretti, fatto il programmo con possibilità di attivare il relè (che collegherò ad elettrovalvola) in modalità manuale o automatica (con impostazione ora inizia e fine) e con tutto ciò correlato al grado di umidità del terreno. Primo test: TUTTO OK . Tutto funziona benissimo. Per necessità personali voglio aggiungere possibilità di attivarlo anche a distanza. Acquisto un Ethernet shield e da buon neofita (scarsone) parto da zero e scopro app Blynk. Riparto con la trascrizione del codice (utilizzando schetch di base) e tutto funziona bene con solo Blynk. (riesco a leggere valore umidità sullo smartphone e attivare e disattivare relè pigiando un bottone). Ed allora non devo far altro che mettere tutto insieme...
Ed ecco che il tutto non funziona più. In pratica i secondi sul display scorrono per 5 secondi poi si bloccano, arduino si disconnette da internet e tutti gli altri comandi si bloccano. Non capisco perchè le 2 cose non si possano integrare. Grazie
per cominciare ad aiutarti a capire qualche cosa.... dobbiamo poter vedere il programma che hai scritto, solo in seguito si potrà discutere
Non riesco a postare tutto il programma insieme perchè supera i 9000 caratteri. Lo devo dividere in pù parti:
//Includiamo le librerie
#include <Key.h> // per la tastiera
#include <Keypad.h> //per la tastiera
#include <Wire.h> // per lo schermo lcd
#include "RTClib.h" // per orologio
#include <LiquidCrystal.h> // per lo schermo lcd
//per la connessione ethernet
#define BLYNK_PRINT Serial //per la connessione a Internet
#include <SPI.h>
#include <Ethernet.h>
#include <BlynkSimpleEthernet.h>
char auth[] = "XXXXXXXXXXXXXXXXXXXXX"; //come comunicato su mail da blink
#define W5100_CS 10 //serve per blink
# define Val_umidita V0 //impostiamo pin virtuale V0 per leggere su android valore umidità
//fine parte connessione ethernet
RTC_DS1307 rtc; /*gestione orologio*/
const int rs = 22, en = 24, d4 = 26, d5 = 28, d6 = 30, d7 = 32; /* pin per lo schermo lcd */
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); /* gestione lcd*/
const byte ROWS = 4; //quattro righe Keypad
const byte COLS = 3; //tre colonneKeypad
char keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
byte rowPins[ROWS] = {41,43,45,47}; //i Pin a cui sono connesse le righe del KeyPad
byte colPins[COLS] = {49,51,53}; // i Pin a cui sono connesse le colonne del KeyPad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
const int SogliaUmidita = 350; //valore soglia oltre il quale deve partire irrigazione
int tasto=0;
int livello=0; //definizione di costanti che serviranno per i vari passaggi nei sottomenu
int menu=0; //definizione di costanti che serviranno per i vari passaggi nei sottomenu
int rele=23; //definizione dei pin che dirigono rele
int X=0; //definizione di costanti che serviranno per settare orari di inizio e fine irrigazione automatica
int Y=0; //definizione di costanti che serviranno per settare orari di inizio e fine irrigazione automatica
int Z=0; //definizione di costanti che serviranno per settare orari di inizio e fine irrigazione automatica
int W=0; //definizione di costanti che serviranno per settare orari di inizio e fine irrigazione automatica
int A=0; //definizione di costanti che serviranno per settare orari di inizio e fine irrigazione automatica
int B=0; //definizione di costanti che serviranno per settare orari di inizio e fine irrigazione automatica
int C=0; //definizione di costanti che serviranno per settare orari di inizio e fine irrigazione automatica
int D=0; //definizione di costanti che serviranno per settare orari di inizio e fine irrigazione automatica
void setup()
{
lcd.begin(16, 4);
Wire.begin();
rtc.begin();
pinMode(rele, OUTPUT);
digitalWrite(rele, HIGH);
if (! rtc.isrunning()) //inizializzazione RTC
{
lcd.println("RTC is NOT running!");
// compilare questa linea la prima volta per settare RTC con anno, mese, giorno, ora, minuti, secondi
rtc.adjust(DateTime(2018, 9, 5, 9, 51, 05));
}
//PER LA CONNESSIONE ETHERNET
Blynk.begin(auth);
// You can also specify server:
//Blynk.begin(auth, "blynk-cloud.com", 80);
//Blynk.begin(auth, IPAddress(192,168,1,100), 8080);
// For more options, see Boards_Ethernet/Arduino_Ethernet_Manual example
// Puoi inviare qualsiasi valore in qualsiasi momento.
// Si prega di non inviare più di 10 valori al secondo.
//Provo ad usare pin virtuale per leggere valore umidità
BLYNK_READ (Val_umidita);
// FINE CONNESSIONE ETHERNET
}
Da qui inizia il void loop. Considerate che devo verificare meglio le formule per gli orari, ma sembra funzionino bene. Mi scuso se ho commesso errori grossolani o fatto le cose con passaggi "stupidi", ma è tutto frutto della mia inesperienza e tanti copia ed incolla poi modificati
void loop()
{
int ValoreUmidita = analogRead(A8); // per leggere valore umidità dal pin analogico 8 collegato ad un sensore di umidità terreno
int umidita = map(analogRead(A8),0,1023,100,0);// trasformo il valore letto in valore percentuale compreso tra 0-100 mediante funzione map
char key = keypad.getKey(); // attivo Keypad
String giorni,mesi; // definisco giorni mesi per stampare su LCD
String ore,minuti,secondi; // definisco ore minuti secondi per stampare su LCD
DateTime now = rtc.now(); //leggo da RTC la data
int ora=now.hour();
int minuto=now.minute();
if ( menu == 0 && livello == 0) // se nulla è premuto abbiamo lo schermo iniziale (menu 0 livello 0) // Irrighino Gatto
{ // 05/09/2018
lcd.clear(); // 09:51:05 U: 40%
lcd.setCursor(0, 2); // #Aut. 7Man.
lcd.print(" ");
if (now.hour()<10)
{
ore = "0"+String(now.hour()); //se ora è prima delle 10 inserisco lo 0
lcd.print(ore);}
else{
lcd.print(now.hour(), DEC);}
lcd.print(':');
if ((now.minute())<10) /*+2 per correggere errore di RTC*/
{
minuti = "0"+String(now.minute()); //se minuti è prima di 10 inserisco lo 0
lcd.print(minuti);}
else{
lcd.print(now.minute(), DEC);}
lcd.print(':');
if (now.second()<10) //se secondi è prima di 10 inserisco lo 0
{
secondi = "0"+String(now.second());
lcd.print(secondi);}
else{
lcd.print(now.second(), DEC);}
lcd.print (" U:");
lcd.print (umidita);
lcd.print ("%");
lcd.setCursor(3, 1);
if (now.day()<10) // se giorno è prima di 10 inserisco 0
{
giorni = "0"+String(now.day());
lcd.print(giorni);}
else{
lcd.print(now.day(), DEC);}
lcd.print('/');
if (now.month()<10)
{
mesi = "0"+String(now.month());//se mesi è prima di 10 inserisco lo 0
lcd.print(mesi);}
else{
lcd.print(now.month(), DEC);}
lcd.print('/');
lcd.print(now.year(), DEC);
lcd.print(' ');
lcd.setCursor(0, 0);
lcd.print("Irrighino Gatto");
lcd.setCursor(2, 3);
lcd.print("#aut. 7man.");
}
if ( key == '#' && menu == 0 && livello == 0) // se pigio # entro nel menu automatico (menu=1 livello=1) primo sottomenu che prevede impostazione orario inizio e fine o esci
{lcd.clear ();
livello=1;
menu=1;
lcd.setCursor(1, 1);
lcd.print ("7=imposta ora");
lcd.setCursor(4, 2);
lcd.print ("9=esci");
}
if (key == '7' && menu == 1 && livello == 1) // se nel menu automatico pigio 7 entro nel sottomenu per impostare orari di inizio e fine irrigazione (menu=1 livelo=2)
{ //impostare ora partenza elettrovalvola e chiusura elettrovalvola
menu=1; livello=2;
lcd.clear ();
lcd.setCursor (1,0);
lcd.print ("*=OK #=esci");
lcd.setCursor (4,1);
lcd.print ("__:__");
}
if (key == '#' && menu == 1 && livello == 2) // se pigio il tasto # torno al menu iniziale uscire da sottomenu automatico imposta ora
{menu=0; livello=0; }
if (menu==1 && livello==2)
{ lcd.setCursor (3,1);
lcd.print (" ");
lcd.blink();}
if (menu==1 && livello==2 && key=='#')
{livello=0;
menu=0; }
//iniziamo ad inserire orario di avvio: ad ogni digitazione aumenta il livello di 1
if (menu==1 && livello==2 && (key=='0' || key=='1' || key=='2')) //prima i decimali ora
{X=(key-48); //conversione del valore letto dalla pressione del tasto in numero (se pigio 1 sulla tastiera arduino legge 49)
lcd.setCursor (3,1);
lcd.print (" ");
lcd.cursor();
lcd.blink();
lcd.print (key);
livello=3;
} //decimali ora
if (keypad.getState()==RELEASED && menu==1 && livello==3) {livello=4;}
//decimali ora
if (menu==1 && (livello==3||livello==4) && key=='#')
{livello=0; menu=0; }
[code]
A questo punto aumento di livello per ogni numero inserito. In questo modo riesco a settare inizio e fine nei formati: XY:WZ e AB:CD.
Infine:
//partenza relè in funzione degli orari impostati e del tasso di umidità:
if (((X * 10)+ Y) == ((A * 10) + B)) { //se inizio e fine sono nella stessa ora (ad es. 21.15-21.45) il relè viene attivato se ZW<= ora attuale <=CD ed il valore umidità è maggiore della soglia (più basso)
if (((X * 10)+ Y)==ora && ((Z * 10) + W)<=minuto && ((A * 10) + B)>=ora &&((C * 10)+D)>=minuto && (ValoreUmidita >= SogliaUmidita))
{digitalWrite(rele, LOW);
livello=22;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Irrighino Gatto");
lcd.setCursor(0, 1);
lcd.print(" Irrigazione ON");
lcd.setCursor(0, 2);
lcd.print("I:");
lcd.print (X);
lcd.print (Y);
lcd.print (":");
lcd.print (Z);
lcd.print (W);
lcd.print (" ");
lcd.print ("F:");
lcd.print (A);
lcd.print (B);
lcd.print (":");
lcd.print (C);
lcd.print (D);
lcd.noCursor();
lcd.setCursor(0, 3);
lcd.print (" #=annulla"); }
else {digitalWrite(rele, HIGH);
}}
if (((X * 10)+ Y) < ((A * 10) + B)) { //se ora inizio precede ora fine (ad es. 21.15-22.45)il relè viene attivato se XY=ora attuale e ZW<=minuto attuale o XY<ora attuale<AB o AB=ora attuale e CD>=minuto attuale ed il valore umidità è maggiore della soglia (più basso)
if ( ((((X * 10)+ Y)==ora && ((Z * 10) + W)<=minuto)||(((X * 10)+ Y)<ora && ((A * 10) + B)>ora)|| (((A * 10) + B)==ora &&((C * 10)+D)>=minuto)) && (ValoreUmidita >= SogliaUmidita))
{digitalWrite(rele, LOW);
livello=22;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Irrighino Gatto");
lcd.setCursor(0, 1);
lcd.print(" Irrigazione ON");
lcd.setCursor(0, 2);
lcd.print("I:");
lcd.print (X);
lcd.print (Y);
lcd.print (":");
lcd.print (Z);
lcd.print (W);
lcd.print (" ");
lcd.print ("F:");
lcd.print (A);
lcd.print (B);
lcd.print (":");
lcd.print (C);
lcd.print (D);
lcd.noCursor();
lcd.setCursor(0, 3);
lcd.print (" #=annulla");}
else {digitalWrite(rele, HIGH);
}}
if (((X * 10)+ Y) > ((A * 10) + B)) { //se ora fine precede ora inizio (ad es. 23.15-00.45) XXXXXXXXXXXXXXXXXXXXXXXXXXX ed il valore umidità è maggiore della soglia (più basso)
if (((X * 10)+ Y)==ora && ((Z * 10) + W)<=minuto && ((A * 10) + B)<ora &&((C * 10)+D)<=minuto ||((X * 10)+ Y)>ora && ((Z * 10) + W)>=minuto && ((A * 10) + B)==ora &&((C * 10)+D)>=minuto && (ValoreUmidita >= SogliaUmidita))
{digitalWrite(rele, LOW);
livello=22;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Irrighino Gatto");
lcd.setCursor(0, 1);
lcd.print(" Irrigazione ON");
lcd.setCursor(0, 2);
lcd.print("I:");
lcd.print (X);
lcd.print (Y);
lcd.print (":");
lcd.print (Z);
lcd.print (W);
lcd.print (" ");
lcd.print ("F:");
lcd.print (A);
lcd.print (B);
lcd.print (":");
lcd.print (C);
lcd.print (D);
lcd.noCursor();
lcd.setCursor(0, 3);
lcd.print (" #=annulla"); }
else {digitalWrite(rele, HIGH);
}}
if (livello==22 && (ValoreUmidita < SogliaUmidita)) //la partenza della irrigazione automatica è vincolata alla lettura di umidità. Il relè non viene attivato se umidità è elevata ed arduino ci darà il seguente messaggio
{ lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Irrighino Gatto");
lcd.setCursor(0, 1);
lcd.print(" Irrigazione OFF");
lcd.setCursor(0, 2);
lcd.print("I:");
lcd.print (X);
lcd.print (Y);
lcd.print (":");
lcd.print (Z);
lcd.print (W);
lcd.print (" ");
lcd.print ("F:");
lcd.print (A);
lcd.print (B);
lcd.print (":");
lcd.print (C);
lcd.print (D);
lcd.noCursor();
lcd.setCursor(0, 3);
lcd.print (" #=annulla"); }
//sottomenu Manuale: menu 2 livello 2
if (key == '7' && menu ==0 && livello ==0) // se nel menu iniziale pigio 7 entro nel sottomenu manuale
{ lcd.clear ();
livello = 2; menu = 2;
lcd.print ("#=Avvia 1=Ferma *=Esci"); } // inserire codice per attivare pin con #, disativare con 1, uscire con *
if (key == '#' && menu ==2 && livello ==2) //se nel sottomenu manuale pigio # potrei attivare rele
{menu = 3; }
if (menu ==3 && livello ==2)
{
if (ValoreUmidita < SogliaUmidita) //Se il terreno è Umido arduino me lo comunica e mi chiede se voglio irrigare comunque altrimenti parte irrigazione
{lcd.clear();
menu=4;
lcd.setCursor (2,0);
lcd.print ("Terreno Umido");
lcd.setCursor (5,1);
lcd.print (umidita);
lcd.print ("%");
lcd.setCursor (3,2);
lcd.print ("avviare?");
lcd.setCursor (0,3);
lcd.print ("1=Ferma 3=Avvia"); }
else {
digitalWrite(rele, LOW);
lcd.clear();
lcd.setCursor (3,0);
lcd.print ("Irrigazione");
lcd.setCursor (3,1);
lcd.print ("avviata");
lcd.setCursor (3,2);
lcd.print ("1=Ferma"); } }
if (key == '3' && menu ==4 && livello ==2)
{menu=5;}
if (menu ==5 && livello ==2)
{digitalWrite(rele, LOW);
lcd.clear();
lcd.setCursor (3,0);
lcd.print ("Irrigazione");
lcd.setCursor (3,1);
lcd.print ("avviata");
lcd.setCursor (3,2);
lcd.print ("1=Ferma"); }
if (key == '1' && (menu ==3 || menu ==4 || menu ==5) && livello ==2) //se nel sottomenu manuale pigio 1 disattivo rele
{ menu = 2; livello = 2;
digitalWrite(rele, HIGH);
lcd.clear();
lcd.setCursor (3,1);
lcd.print ("Irrigazione");
lcd.setCursor (3,2);
lcd.print ("ferma");
lcd.setCursor (2,3);
lcd.print ("#=avvia *=esci"); }
if (key == '*' && menu ==2 && livello ==2) //se nel sottomenu manuale pigio * torno al menu iniziale
{ menu = 0 ; livello = 0 ; }
//creazione del menu di irrighino
//PER LA CONNESSIONE ETHERNET
//attivazione con smartphone
Blynk. virtualWrite (Val_umidita, umidita );
Blynk.run();
//FINE PROGRAMMA CONNESSIONE ETHERNET
delay (500);
}
Se scindo i 2 programmi (quello per ethernet e quello locale) entrambi funzionano alla grande. Se invece li fondo Arduino si blocca dopo 5 secondi (sullo schermo lcd vedo scorrere i secondi fino al blocco).
Hai un conflitto di Pin con la scheda Ethernet e il Keypad
byte colPins[COLS] = {49,51,53}; // i Pin a cui sono connesse le colonne del KeyPad
SPI: 50 (MISO), 51 (MOSI), 52 (SCK), 53 (SS)
Grazie mille, provo a spostare la tastiera, però la scheda ethernet è collegata ai pin digitali fino a 13 ed agli analogici fino a A5. farò sapere se funziona =D.
brunello22:
Hai un conflitto di Pin con la scheda Ethernet e il Keypadbyte colPins[COLS] = {49,51,53}; // i Pin a cui sono connesse le colonne del KeyPad
SPI: 50 (MISO), 51 (MOSI), 52 (SCK), 53 (SS)
Grazie mille!!!!! Spostando la tastiera ai pin 41,40,43,42,44,45,47 funziona cosi cosi. Nel senso che adesso non si blocca più (problema risolto). Però adesso quando avvio relè da smartphone si attiva per il tempo che pigio il tasto e poi si disattiva (credo sia adesso da studiare una soluzione per evitare che il pin venga spenta dal programma, mi metto sotto!!!!). Chiedo però, se possibile, spiegazioni circa quel conflitto. La scheda ethernet infatti non era collegata ai pin da 50 in poi, perchè faceva conflitto?
Giacomo77:
Grazie mille, provo a spostare la tastiera, però la scheda ethernet è collegata ai pin digitali fino a 13 ed agli analogici fino a A5. farò sapere se funziona =D.
La scheda Ethernet usa i pin ICSP ( che è quel connettore a 6 poli presente nel retro della scheda )
Ma siccome nella Mega sono collegati anche ai pin 50 (MISO), 51 (MOSI), 52 (SCK), ), non puoi usarli.
Poi la scheda EThernet usa i pin 10 CS e 4 CS per la SD, il resto è tutto libero
Giacomo77:
Grazie mille, provo a spostare la tastiera, però la scheda ethernet è collegata ai pin digitali fino a 13 ed agli analogici fino a A5. farò sapere se funziona =D.
La SPI sul Arduino UNO é sui pin 11,12, e 13 mentre sul MEGA é sui pin 50,51 e 52. Qua i pin 11,12 e 13 sono disponibili. L'Arduino LEONARDO non ha i Pin SPI sui contatti esterni perché sono piedini diversi.
Per unificare tutto c'é il connettore a 6 pin centrale dove é collegato la ICSP che serve per programmare il controller quando questo non ha uno bootloader e che corrisponde all'interfaccia SPI. Il pin CS della SPI puó essere qualsiasi pin e dipende dallo shield. spesso vengono usato i pin 10 e 4 che sono quelli su tutti i diversi Arduini.
Ciao Uwe
Grazie mille brunello e uwe. Devo approfondire conoscenze sulla scheda che uso. Problema risolto.