Blocco programma utilizzando Blynk

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 :slight_smile: . 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... :confused: 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 :slight_smile:

per cominciare ad aiutarti a capire qualche cosa.... dobbiamo poter vedere il programma che hai scritto, solo in seguito si potrà discutere :wink:

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 :slight_smile:

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 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!!!!! 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. :slight_smile: