Orto idroponico verticale con Arduino – quarta parte

La quarta parte del progetto Orto idroponico verticale con Arduino la dedicherai quasi completamente allo sketch.

orto idroponico verticale

Data la complessità dello sketch ho deciso di dividerlo in due file:

  • OrtoWeMake.ino
    function.ino

Il progetto completo puoi trovarlo condiviso su gitHub come InternetOfGreens :

InternetOfGreens-github

in cui ho inserito anche gli sketch utilizzati nelle fasi di test e taratura dei sensori.

Lo sketch dell’orto idroponico verticale

In questo primo articolo esaminerai solo lo sketch denominato OrtoWeMake.ino contenente tutte le definizioni ed i richiami alle funzioni che ho spostato nel file function.ino

Il progetto è stato realizzato con una Arduino MEGA 2560 sia per incrementare la disponibilità di pin sia per consentire l’uso di più memoria in cui far funzionare l’intero sketch:

/* Orto WeMake Arduino Day 2015 */

#include <SPI.h>
#include <Ethernet.h>
#include <ArduinoJson.h>
#include <EthernetUdp.h>
#include <Wire.h>
#include "RTClib.h"

/**********************************************************************************/

#define DEBUG 1

/**********************************************************************************/

#define textBuffSize 500
#define PhMeterPin   8             //pH meter Analog output to Arduino Analog Input 0
#define Offset       0.24          //deviation compensate
#define ArrayLenth   40            //times of collection
#define pinLamp1     22            // Relay right Light
#define pinLamp2     23            // Relay left Light
#define pinPump1     32            // Relay Pump 1
#define pinPump2     33            // Relay Pump 2
#define pinFert1     3             // elettrovalvola Fertilizzante
#define pinValF1     2             // controllo valvola Fertilizzante

/**********************************************************************************/

const char*  LIGHT1= "5509b3d74ca0f61a7c9ced62"; // Accensione Luci  1
const char*  LIGHT2= "5509b3d74ca0f61a7c9ced63"; // Accensione Luci  2
const char*  LIGHT3= "5509b3d74ca0f61a7c9ced64"; // Accensione Luci  3
const char*  LIGHT4= "5509b3d74ca0f61a7c9ced65"; // Accensione Luci  4
const char*  LIGHT5= "5509b3d74ca0f61a7c9ced66"; // Accensione Luci  5
const char*  LIGHT6= "5509b3d74ca0f61a7c9ced67"; // Accensione Luci  6
const char*  LIGHT7= "5509b3d74ca0f61a7c9ced68"; // Accensione Luci  7
const char*  LIGHT8= "5509b3d74ca0f61a7c9ced69"; // Accensione Luci  8
const char*  LIGHT9= "5509b3d74ca0f61a7c9ced6a"; // Accensione Luci  9
const char*  LIGHT0= "5509b3d74ca0f61a7c9ced6b"; // Accensione Luci 10
const char*  POMPA1= "5509b3d74ca0f61a7c9ced6c"; // Pompa per parete verticale
const char*  FERTI1= "5509b3d74ca0f61a7c9ced6d"; // Fertilizzante
const char*  ACLEV1= "5509b3d74ca0f61a7c9ced6e"; // Livello acqua bidone idroponica
const char*  NO2SN1= "5509b3d74ca0f61a7c9ced6f"; // Sensore NO2 (SmartCitizen)
const char*  NOISE1= "5509b3d74ca0f61a7c9ced72"; // Rumore ambiente (SmartCitizen)
const char*  TEMPC1= "5509b3d74ca0f61a7c9ced75"; // Temperatura ambiente (SmartCitizen)
const char*  PHMET1= "5509b3d74ca0f61a7c9ced76"; // Ph Idroponica
const char*  CO2SN1= "5509b3d74ca0f61a7c9ced71"; // CO2 ambiente (SmartCitizen)
const char*  LIAMB1= "5509b3d74ca0f61a7c9ced73"; // Luce ambiente (SmartCitizen)
const char*  HUMID1= "5509b3d74ca0f61a7c9ced74"; // Sensore umidità (SmartCitizen)
const char*  SENEC1= "5509b3d74ca0f61a7c9ced82"; // Sensore EC 1
const char*  SENEC2= "5509b3d74ca0f61a7c9ced83"; // Sensore EC 2
const char*  SENEC3= "5509b3d74ca0f61a7c9ced84"; // Sensore EC 3
const char*  SENEC4= "5509b3d74ca0f61a7c9ced85"; // Sensore EC 4
const char*  SENEC5= "5509b3d74ca0f61a7c9ced86"; // Sensore EC 5
const char*  SENEC6= "5509b3d74ca0f61a7c9ced87"; // Sensore EC 6
const char*  SENEC7= "5509b3d74ca0f61a7c9ced88"; // Sensore EC 7
const char*  SENEC8= "5509b3d74ca0f61a7c9ced89"; // Sensore EC 8
const char*  SENEC9= "5509b3d74ca0f61a7c9ced8a"; // Sensore EC 9
const char*  SENEC0= "5509b3d74ca0f61a7c9ced8b"; // Sensore EC 10
const char*  BATTE1= "5509b3d74ca0f61a7c9ced77"; // Voltaggio (SmartCitizen)  

/**********************************************************************************/

unsigned int localPort = 8888;
byte timeZone = 1;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
char server_in[]  = "api.smartcitizen.me";    // name address for Google (using DNS)
char server_out[] = "iot.enter.it";    // name address for Google (using DNS)
char timeServer[] = "time.nist.gov";     // NTP Server

const int NTP_PACKET_SIZE= 48;
byte packetBuffer[ NTP_PACKET_SIZE];

int index;
char results[textBuffSize];
boolean startData = false;
char* strBuffer;

//const char* timestamp;
double temp, hum, co, no2, light;
int noise, batt;
  
IPAddress ip(192, 168, 2, 249);
EthernetClient client;
EthernetUDP Udp;

byte currHour, currMin, currSec;
static float pHValue = 0;

/**********************************************************************************/

boolean statusLight = false;
boolean statusPompa = false;
const float ECValRif = 0.9;
byte lastTimeSet = 0;
char lcdBuffer1[16] = "";
char lcdBuffer2[16] = "";

/**********************************************************************************/

byte nsens = 2;
byte pinEC1[] = {51,50};
byte pinEC2[] = {15,14};
byte pinEC3[] = {53,52};
// parametri di taratura in uS/cm
float A[] = {870.43,822.71};
float B[] = {-1.194,-1.190};
float R1 = 470.;  //  resistenza fissa tra P1 e P3 in ohm
float RS[] = {0,0}; //  inizializzo resistenza tra i due elettrodi 
float CS[] = {0,0}; //  inizializzo conducibilità specifica

byte isens = 0;
byte n = 50;

/**********************************************************************************/

RTC_DS1307 RTC;

/**********************************************************************************/

void setup() {
  Serial.begin(9600);
  
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    Ethernet.begin(mac, ip);
  }
  
  Udp.begin(localPort);
  Wire.begin();
  RTC.begin();
  
  Serial.print("My IP address: ");
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print("."); 
  }
  Serial.println("");
  
  if (! RTC.isrunning()) { Serial.println("RTC NOT running! RESET REQUIRED"); }
  else                   { RTC.adjust(DateTime(__DATE__, __TIME__)); }
  
  DateTime now = RTC.now();
  getTime(); 
  RTC.adjust(DateTime(now.year(), now.month(), now.day(), currHour, currMin, currSec)); 
  lastTimeSet = currHour;
  
  pinMode(pinLamp1,OUTPUT);
  pinMode(pinLamp2,OUTPUT);
  pinMode(pinPump1,OUTPUT);
  pinMode(pinPump2,OUTPUT);
  pinMode(pinFert1,OUTPUT);
  
  pinMode(pinValF1,INPUT);
  
  for(byte isens = 0; isens < nsens ; isens++){
    pinMode(pinEC1[isens],OUTPUT);
    pinMode(pinEC2[isens],INPUT);
    pinMode(pinEC3[isens],OUTPUT);
  }
  analogWrite(pinFert1,0);
}

/**********************************************************************************/

void loop() {
  DateTime now = RTC.now();
  Serial.println("\n---------------");
  
  sprintf(lcdBuffer2,"Ora: %02d:%02d:%02d DayOfWeek: %d",(currHour+LegalTime(RTC.now())),currMin,currSec,now.dayOfWeek()); 
  Serial.println(lcdBuffer2);
  
  /**********************************************************************************/
  if ( lastTimeSet != currHour && currMin == 15) { 
      getTime(); 
      RTC.adjust(DateTime(now.year(),now.month(),now.day(),currHour,currMin,currSec)); 
      lastTimeSet = currHour;
   } else {
     currHour = now.hour();
     currMin  = now.minute();
     currSec  = now.second();
   }
   
   /**********************************************************************************/
   if ( 0 == currMin || currMin == 30 ) { // Get Data from Smart Citizen project
     while ( !getApiSmartCitizen() ) { ; }
     if ( results[0] == '{' ) {

      // Mapping Value
      co = map(((int)((co/100) + 0.5)*100),1,1000,300,1500);
      no2 = map(((int)(no2/100 + 0.5)*100),0,500,0,1);
      noise = map((((int)(noise/10)+0.5)*10),0,100,10,100);
      batt = map(batt,0,100,0,5);

      sprintf(lcdBuffer1,  "%02d° %03d% %04dCo", temp, hum, co); 
      sprintf(lcdBuffer2,  "%03dn %03dl %1dv %01dNo", noise, light, batt, no2); 
      Serial.println(lcdBuffer1);
      Serial.println(lcdBuffer2);
      
      strBuffer=""; dtostrf(temp,2,0,strBuffer);  while (!postData(TEMPC1,strBuffer)) {;}
      strBuffer=""; dtostrf(hum,2,0,strBuffer);   while (!postData(HUMID1,strBuffer)) {;}
      strBuffer=""; dtostrf(co,4,0,strBuffer);    while (!postData(CO2SN1,strBuffer)) {;}
      strBuffer=""; dtostrf(no2,1,0,strBuffer);   while (!postData(NO2SN1,strBuffer)) {;}
      strBuffer=""; dtostrf(noise,3,0,strBuffer); while (!postData(NOISE1,strBuffer)) {;}
      strBuffer=""; dtostrf(light,2,0,strBuffer); while (!postData(LIAMB1,strBuffer)) {;}
      strBuffer=""; dtostrf(batt,2,0,strBuffer);  while (!postData(BATTE1,strBuffer)) {;}
     }

     /**********************************************************************************/
     
     getPh();
     if (pHValue > 0 ) { 
        strBuffer=""; dtostrf(pHValue,2,2,strBuffer);
        while ( !postData(PHMET1, strBuffer) ) { ; }
      }
     
     /**********************************************************************************/
  
     digitalWrite(pinEC1[1],HIGH);
     if ( analogRead(pinEC2[1]) > 512 ) { while ( !postData(ACLEV1, "1") ) { ; } }
     else                               { while ( !postData(ACLEV1, "0") ) { ; } } 
     
     /**********************************************************************************/
  
   } // end if 0 and 30 min
   
  /**********************************************************************************/

  if (((20<=currHour && currHour<=23) || (5<=currHour && currHour<=7)) && currMin==20) {
     float CS1 = readEC(0);
     if (CS1 < 0)   { CS1 = 0; }
     if (CS1 > 1.3) { CS1 = 1.3; } 
     strBuffer=""; dtostrf(CS1,1,1,strBuffer);  
       
     while ( !postData(SENEC1, strBuffer) ) { ; }
     while ( !postData(SENEC2, strBuffer) ) { ; }
     while ( !postData(SENEC3, strBuffer) ) { ; }
     while ( !postData(SENEC4, strBuffer) ) { ; }
     while ( !postData(SENEC5, strBuffer) ) { ; }
     while ( !postData(SENEC6, strBuffer) ) { ; }
     while ( !postData(SENEC7, strBuffer) ) { ; }
     while ( !postData(SENEC8, strBuffer) ) { ; }
     while ( !postData(SENEC9, strBuffer) ) { ; }
     while ( !postData(SENEC0, strBuffer) ) { ; }
   }

   /**********************************************************************************/
     
   // FERTILIZZANTE
   if ( currHour == 22 && currMin == 30 ) {
     apriGocciolatore();
     while ( !postData(FERTI1, "1") ) { ; }
     delay( 1300 ); // con 1300 millisecondi fa 10ml
     chiudiGocciolatore();
     while ( !postData(FERTI1, "0") ) { ; }
   }

   /**********************************************************************************/

   if ( 7 <= currHour && currHour <= 20 && statusLight == false ) {
     digitalWrite(pinLamp1,HIGH);
     digitalWrite(pinLamp2,HIGH);
     
     while ( !postData(LIGHT1, "1") ) { ; }
     while ( !postData(LIGHT2, "1") ) { ; }
     while ( !postData(LIGHT3, "1") ) { ; }
     while ( !postData(LIGHT4, "1") ) { ; }
     while ( !postData(LIGHT5, "1") ) { ; }
     while ( !postData(LIGHT6, "1") ) { ; }
     while ( !postData(LIGHT7, "1") ) { ; }
     while ( !postData(LIGHT8, "1") ) { ; }
     while ( !postData(LIGHT9, "1") ) { ; }
     while ( !postData(LIGHT0, "1") ) { ; }
     
     statusLight = true;
   }
   
   if (((21<=currHour && currHour<=23) || (0<=currHour && currHour<=6)) 
         && statusLight==true) {
     digitalWrite(pinLamp1,LOW);
     digitalWrite(pinLamp2,LOW);
     
     while ( !postData(LIGHT1, "0") ) { ; }
     while ( !postData(LIGHT2, "0") ) { ; }
     while ( !postData(LIGHT3, "0") ) { ; }
     while ( !postData(LIGHT4, "0") ) { ; }
     while ( !postData(LIGHT5, "0") ) { ; }
     while ( !postData(LIGHT6, "0") ) { ; }
     while ( !postData(LIGHT7, "0") ) { ; }
     while ( !postData(LIGHT8, "0") ) { ; }
     while ( !postData(LIGHT9, "0") ) { ; }
     while ( !postData(LIGHT0, "0") ) { ; }
     
     statusLight = false;
   }
   
   /**********************************************************************************/
   
   if (( 8 <= currHour && currHour <= 21 ) && (0 <= currMin && currMin <= 15)) {
      digitalWrite(pinPump1,HIGH);
      if ( !statusPompa ) {
        while ( !postData(POMPA1, "1") ) { ; }
        statusPompa = true;
      }
   }
   if ( 16 <= currMin && currMin <= 59) {
      digitalWrite(pinPump1,LOW);
      if ( statusPompa ) {
        while ( !postData(POMPA1, "0") ) { ; }
        statusPompa = false;
      }
   }
   
   /**********************************************************************************/
   delay( 60000 );
} // end loop

linee 003-008: includi tutte le librerie che ti serviranno per controllare l’RTC, la Ethernet Shield e gli oggetti JSON;

linea 012: imposta la #define DEBUG che ti serve per abilitare/disabilitare la visualizzazione del debug su monitor seriale;

linea 016: definisci textBuffSize in cui memorizzare la stringa di risposta in formato JSON in risposta dal progetto SmartCitizen, non preoccuparti se ora ti sembra incomprensibile al termine della descrizione di tutti gli sketch coinvolti vedrai che sarà chiara la sua funzione;

linea 017: definisci il pin analogico a cui è connesso il PhMetro, siccome usiamo la MEGA posso definire il pin A8 come “8”;

linea 018: definisci l’Offset da applicare al valore letto dal PhMetro, puoi leggere come impostarlo in questo articolo

linea 019: definisci il numero di campionamenti eseguiti dal PhMetro;

linee 020-025: definisci i pin a cui sono connessi i relay che si preoccupano di accendere le lampade, in gruppi di due, la pompa 1 e una pompa di riserva, il sistema per il controllo del fertilizzante formato da un motore ed un microswitch per la rilevazione dello stato chiuso / aperto;

linee 029-059: siccome l’orto è InternetOfGreens e come avrai letto esiste un app on-line realizzata per il monitoraggio dell’orto abbiamo definito una serie di codici abbinati alle piante inserite nell’orto, ai sensori ed agli attuatori. Alcuni codici sono validi per i medesimi sensori ed attuatori in quanto è prevista la possibilità di espendere il numero di sensori e dividere le linee di controllo per realizzare orti di dimensioni superiori;

linee 063-064: definisci la porta ed il timeZone per la richiesta dell’ora con il protocollo ntp;

linee 066-069: imposta il Mac Address della scheda e gli Url per richiamare i servizi internet relativi a ntp, smartcitizen e internetofgreens.

linee 071-072: definisci la costante di buffer e l’array in cui memorizzare i dati ricevuti via ntp;

linee 074-077: definisci altre variabili utili alla comunicazione e ricezione dei dati ntp;

linee 079-081: imposta delle variabili in cui memorizzerai i dati relativi ai sensori di temperatura ed umidità rilevati dal progetto smart citizen;

linee 083-085: definisci una variabile contenente un Ip valido nella tua rete che utilizzerai in alternativa al DHCp qualora non dovesse funzionare l’assegnazione dell’Ip da parte del DHCP presente nella tua rete. Prepara due istanze una per l’oggetto client della Ethernet shield ed uno UDP per le richieste al server Ntp;

linea 087: definisci le variabili in cui memorizzerai i valori di ora, minuti e secondi dopo averle recuperate;

linea 088: crea la variabile phValue che conterrà il valore di Ph misurato;

linee 092-093: imposta due variabili di tipo boolean il cui scopo è segnalare se la pompa e le luci siano già state accese, questo stato serve ad evitare che lo stato luci o pompa venga rilevato e inviato ogni minuto se il precedente stato è identico a quello corrente;

linea 094: imposta un valore di riferimento per l’EC ( conducibilità elettrica ) rilavata. Il valore di EC varia da 0,1 a 1,3 circa per cui 0,9 è un valore intermedio;

linea 095: imposta una variabile “segnaposto” ossia una variabile che utilizzerai per segnare un valore temporale di riferimento da confrontare con l’ora corrente per determinare il passaggio del tempo ad ogni ciclo di loop();

linee 096-097: definisci due array buffer che userai per comporre due stringhe di 16 caratteri ciascuno prima di inviarli al monitor seriale, ho scelto la lunghezza 16 in modo da predisporre il codice ad un futuro uso con un display LCD;

linee 101-114: sono i parametri necessari ai sensori EC, in questo progetto ne useremo 2 posti entrambi nel bidone con la doppia funzione di rilevare sia il livello di EC sia il livello dell’acqua presente nel bidone. Per conoscere il significato di questi valori ti invito a consultare la spiegazione dettagliata in questo articolo.

linea 117: crea una istanza della classe RTC;

linea 122: attiva il monitor seriale;

linee 124-127: inizializza l’istanza Ethernet passandogli il solo mac ed attendendo l’assegnazione dell’IP dal DHCP, se questa operazione fallisce scrivi sul monitor seriale “Failed to configure Ethernet using DHCP” ed inizializzi l’istanza passandole sia il mac sia l’IP da utilizzare;

linee 129-131: inizializzi le istanze Udp, Wire ed RTC;

linee 133-138: scrivi sul monitor seriale l’IP ricevuto dal DHCP;

linee 140-141: controlla che ci sia comunicazione con l’RTC ed in caso di successo imposta la data e l’ora corrente del Pc sull’RTC arduino;

linea 143-146: subito dopo aver impostato l’ora del server crea un oggetto now di tipo DateTime per interrogare la RTC shield, ed esegui la chiamata alla funzione getTime(), che analizzeremo nel prossimo articolo, ed il cui scopo è collegarsi all’ntp server di riferimento e recuperare l’ora corrente in modo che la linea successiva possa reimpostarla sull’RTC shield. Infine imposta la variabile lastTimeSet con l’ora corrente in modo che all’avvio del loop() non venga richiesta una nuova sintonizzazione con l’ntp server;

linee 148-160: imposta i pin Mode INPUT per i pin da cui dovremo leggere e OUTPUT per i pin su cui dovrai inviare segnali di controllo;

linea 161: in chiusura al setup() imposta a 0 il pin di controllo del motore che gestisce il fertilizzante;

linea 167: componi nuovamente un istanza now dell’oggetto RTC per recuperare ad ogni ciclo di loop() l’ora corrente;

linee 170-172:  componi una prima stringa con il formato “Ora: hh:mm:ss DayOfWeek: gg” in cui l’ora è formata dall’ora rilevata sull’RTC shield sommato al valore restituito dalla funzione LegalTime(RTC.now()), che analizzeremo in un prossimo articolo, e ti permette di visualizzare l’ora comprensiva dell’ora legale;

linee 175-183: controlla che sia trascorsa un ora dall’ultima richiesta di sincronizzazione Ntp e che sia il 15° minuto dell’ora corrente in questo modo non esegui continue richieste di sincronizzazione ntp e non rischi di essere “bannato” con il tuo progetto. In caso di controllo falso, ossia per tutti i minuti diversi dal 15° dell’ora in cui hai eseguito la sincronizzazione l’ora corrente è presa dall’RTC.

linea 186: inizia un blocco che termina alla linea 226, il cui fattore scatenante è la corrispondenza del minuto corrente con 0 e 30, quindi ogni 30 min;

linea 187: richiami la funzione getApiSmartCitizen() il cui scopo è recuperare i valori dei sensori rilevati dal progetto per l’ambiente in cui ti trovi, ma ne parleremo in un prossimo articolo. Il fatto che la funzione sia richiamata con un ciclo while ti assicura che lo sketch resti fermo su questa chiamata fino al totale recupero delle informazioni che hai richiesto;

linea 188: siccome la funzione richiamata alla linea precedente risponde con un codice JSON che inizia per “{” controlli che il risultato abbia come primo carattere proprio “{“;

linee 191-194: dei valori recuperati dal progetto smart citizen alcuni come no2, co, ecc .. presentano dei valori non presenti nel range accettato dal sito web su cui dobbiamo pubblicarli per cui ho dovuto eseguire alcune operazioni di mappatura per riportarli negli intervalli accettati;

linee 196-199: componi due linee da visualizzare nel monitor seriale;

linee 201-207: per ciascun sensore di cui hai recuperato il valore esegui una sequenza di operazioni, prendo ad esempio la prima linea in cui azzeri il contenuto della variabile strBuffer con il comando dtostrf assegni il valore della temperatura ( temp ) al buffer appena pulito con la precisione di 2 cifre e nessun decimale. Infine richiami la funzione postData passandole il codice corrispondente al dato che invierai ed il valore rilevato;

linee 212-216: richiami la funzione getPh() che si preoccupa di leggere i valori di Ph dell’acqua rilevati dal Ph Meter e di inviarli in caso di valori > 0 al server che ospita l’applicazione/sito per collezionarli. Per l’invio di dai usi sempre la stessa funzione postData() cambiando solo il valore dell’ID relativo al sensore di cui stai inviando il dato;

linee 220-222: rilevi la presenza di acqua che copra il sensore EC1 ossia quello che nel bidone dell’orto idroponico verticale abbiamo posto in alto come segnalator di livello acqua;

linee 230-246: negli intervalli 20-23 e 5-7 al minuto 20 rilevi la conducibilità elettrica dell’acqua di irrigazione e la comunichi al server per tracciarne il valore, noti che questo valore è duplicato per 10 sensori EC, in quanto il progetto prevede la possibilità che tu abbia un sensore Ec in ogni vaso e fino a 10 vasi;

linee 251-257: una volta al giorno alle 22:30 il sistema di immissione fertilizzante deve aggiungere 10ml di fertilizzante all’acqua e per farlo apre per 1300 millisecondi il rubinetto chiamando la funzione apriGocciolatore() e richiudendola dopo il tempo esatto di 1,3sec con la funzione chiudiGocciolatore();

linee 261-267: dalle 7.00 alle 20.00 le luci dell’orto devono essere accese per garantire il corretto apporto di ore di luce alle piante per cui il controllo alla linea 261 verifica che l’ora corrente sia compresa in questo intervallo ed esegue l’accensione delle luci e l’invio dell’informazione al server;

linee 279-296: nelle restanti ore è necessario che le luci restino spente per simulare il normale ciclo di luce per le piante. Unica accortezza che ho utilizzato alla linea 279 è di spezzare il controllo a cavallo delle 0.00 in modo da non incorrere in errori di valutazione dell’orario;

linee 300-306: ogni giorno tra le 8.00 e le 21.00 la pompa parte per circa 15 min per fornire acqua alle piante della serra e recuperare l’acqua in eccesso nel bidone. Ogni azionamento della pompa viene notificato al server;

linee 307-313: come per la luce anche per la pompa è necessario un controllo che ne fermi l’erogazione nei minuti dal 16° al 59° di ogni ora limitando il ciclo di irrigazione a 15min all’ora.

Per questa prima parte del codice è abbastanza in quanto immagino già tu abbia le idee abbastanza confuse dal numero di controlli ed interazioni che il codice fa con l’orto idroponico verticale per far crescere le piante indoor.

Al prossimo articolo sull’orto !!!

  • Questo sito ed i suoi contenuti è fornito "così com'è" e Mauro Alfieri non rilascia alcuna dichiarazione o garanzia di alcun tipo, esplicita o implicita, riguardo alla completezza, accuratezza, affidabilità, idoneità o disponibilità del sito o delle informazioni, prodotti, servizi o grafiche correlate contenute sul sito per qualsiasi scopo.
  • Ti chiedo di leggere e rispettare il regolamento del sito prima di utilizzarlo
  • Ti chiedo di leggere i Termini e Condizioni d'uso del sito prima di utilizzarlo
  • In qualità di Affiliato Amazon io ricevo un guadagno dagli acquisti idonei qualora siano presenti link al suddetto sito.

Permalink link a questo articolo: https://www.mauroalfieri.it/elettronica/orto-idroponico-verticale-con-arduino-quarta-parte.html

5 commenti

Vai al modulo dei commenti

    • nino il 29 Ottobre 2015 alle 10:50
    • Rispondi

    Ciao sto iniziando ora a mettere insieme tutto il progetto ,vorrei però i utilizzare una shield Wi-Fi e una shield con relè a 12v in umido da posizionare un orto con un pannello solare a 12v.puoi consigliarono le shield giuste e come cambierà il progetto?grazie

    • nino il 16 Gennaio 2016 alle 09:51
    • Rispondi

    Ciao Mauro ho visto che il codice inserito qui è diverso rispetto a quello inserito in https://github.com/WeMakecc/InternetOfGreens/tree/master/OrtoWeMake .
    Tu scrivi alla linea
    if ( lastTimeSet != currHour && currMin == 15) {
    getTime();
    RTC.adjust(DateTime(now.year(),now.month(),now.day(),currHour,currMin,currSec));
    lastTimeSet = currHour;
    } else {
    currHour = now.hour();
    currMin = now.minute();
    currSec = now.second();
    }
    Nel codice su github

    if ((currHour == 9 || currHour == 13 || currHour == 19) && currMin == 8) {
    delay( 30000 );
    /*8s*/
    wdt_enable(WDTO_8S);
    delay( 10000 );
    }
    Potrebbe essere questo il problema relativo al mancato aggiornamento?

    1. Ciao Nino,
      le righe di codice che hai preso servono a fare que cosa completamente differenti.
      La seconda parte, in particolare, è relativa al watchdog che avevo incluso solo come test e poi eliminato.

    • nino il 18 Gennaio 2016 alle 15:31
    • Rispondi

    Si .ma il watchdog nella parte di codice su github c’è ancora.
    Poi la procedura di verifica dell ora con RTC sul sito la scrivi diversamente che su github.Ho inserito la verifica alle ore 00:00 sono due giorni che tiene l ora…SPERIAMO!!

    1. Hai ragione Nino, dovrei aggiornare anche il gitHub è che quella versione non la seguo da molto.
      Come ti ho scritto adesso sto lavorando alla OrtoYun.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.