PitOrto

PitOrto il sistema di irrigazione dell'orto sul balcone del Pit

 

Sistema di irrigazione da balcone da utilizzare durante brevi periodi di assenza.

Il sistema di irrigazione preleva con la piccola pompa l'acqua dal serbatoio e la invia alle piante.

Sono presenti un sensore di umidità del terreno e un sensore di umidità autocostruito. L'irrigazione avviene una volta al giorno per una durata calcolata in funzione dell'umidità del terreno (3 minuti con terreno secco - 18 secondi con terreno quasi bagnato) e previa verifica sia della necessità (sensore di umidità del terreno - sotto 500 il terreno è considerato bagnato - sopra 1000 secco) sia della presenza di acqua nel serbatoio (per evitare di bruciare la pompa - sopra 700 il serbatoio è vuoto).

In questo modo in caso di assenza si evita di allagare tutto il palazzo se quache cosa non funzionasse.

Nel software è inserita una funzione di reset che dopo un certo numero di cicli (superiori a 1 ora) resetta il sistema. In questo modo si evita che nel funzionamento continuo il sistema si impalli.

Nel codice sono presenti delle variabili per la compilazione condizionale in modo da semplificare le operazioni di debug.

Nella documentazione da scaricare sono presenti due versioni una con due sensori commerciali per la misura dell'umidità, una con l'utilizzo di un sensore commerciale e uno autocostruito. La versione con i due commerciali è da preferire in quanto quello autocostruito consuma troppa corrente e il NANO di blocca in quanto la tensione si abbassa al punto che non riesce a pilotare il RELE'. Bisognerebbe trovare un sistmema di misurare l'umdità del terreno che consumi poca corrente :) .

ozio_gallery_jgallery

Il PitOrto in azione nella fase di testing.

Cosa serve:

  • Arduino Nano
  • Real Time Clock - RTC1307
  • Rele per accensione pompa
  • Pompa da acquario portata circa 300 l/h prevalenza 50 cm
  • Sensore di umidità del terreno
  • Sensore di presenza acqua nel servatoio (cavi + resistenza)
  • Tubo capillare per irrigazione
  • Gocciolatori
  • Raccordi a T
  • Supporti tubo

Codice sorgente:


/* 
ZappocoS      - PitOrto18_05_06       29/05/2018 --  sostituzione sensore FaiDaTe con sensore commerciale
ZappocoS      - PitOrto18_05_05       20/05/2018 --  interpolazione lineare per durata del pompaggio
ZappocoS      - PitOrto18_05_04       19/05/2018 --  switch button per testing
ZappocoS      - PitOrto18_04_03       22/04/2018 --  timing e controlli orario - altezza H2O - umidità
ZappocoS      - PitOrto18_04_02       22/04/2018 --  aggiunta RTC
ZappocoS      - PitOrto18_04_01       21/04/2018 --  inizio programma - controllo sensori
  PitOrto --> Stazione di Irrigazione orto sul Balcone del PIT
  www.zappoco.altervista.org
*/
#define PitOrtoVersion "PitOrto V18_05_05- by Zappoco"
//----------------------------------------------------------------------------------------
//  Settaggio flag per stampa su seriale di dati per debug e led come sistema di controllo
//----------------------------------------------------------------------------------------
#define OnSerial     //stampa sulla seriale
//#define OnDebug      //accorcia i tempi
//#define OnButton     //utilizza il sensore di presenza acqua come SWITCH per accensione pompa
//#define OnLed        //utilizza il led 
//#define OnPiuDebug   // stampa maggiori dettagli sulla seriale
// ---------------------------------------------------
// presenza del DS1307RTC per lettura timing
// ---------------------------------------------------
#define DS1307RTC
//----------------------------------------------------------------------------------------
// Esegue il Reset ogni 10 cicli
//----------------------------------------------------------------------------------------
#define OnReset              //Attiva il reset
#ifdef OnDebug     
  #define intTime  10000     // setta a 10 secondi (10000 millisecondi) l'intervallo tra le letture (timedelay)
  #define intReset 10        // setta a 3 le volte per il ritardo reset
  #define pumpOrario 19      // Ora in cui viene accesa la pompa
  #define pumpDurata 30000   // durata del pompaggio
#else
  #define intTime 300000     // setta a 5 minuti (300000 millisecondi) l'intervallo tra le letture (timedelay)
  #define intReset 24        // setta a 24 le volte per il ritardo reset  --> 2 ore
  #define pumpOrario 19      // Ora in cui viene accesa la pompa
  #define pumpDurata 180000  // durata del pompaggio 3 minuti (180000 millisecondi) circa 1 litro
#endif
#if defined(ARDUINO_ARCH_SAMD)  // for M0 Pro, output on USB Serial console, remove line below if using programming port to program the Zero!
   #define Serial SerialUSB
#endif
// ---------------------------------------------------
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
// ---------------------------------------------------
#ifdef DS1307RTC
    //----------------------------------------------------------------------------------------
    // librerie DS1307RTC
    //----------------------------------------------------------------------------------------
    #include "Wire.h"
    #include "RTClib.h"
    RTC_DS1307 rtc;
    char daysOfTheWeek[7][12] = {"Domenica", "Lunedi'", "Martedi'", "Mercoledi'", "Giovedi'", "Venerdi'", "Sabato"};
#endif
// ---------------------------------------------------
// Funzione di reset
// Dichiarazione di funzione che punta all'indirizzo zero
// ---------------------------------------------------
#ifdef ESP8266  
#else
  #ifdef OnReset
    void(* Riavvia)(void) = 0;
  #endif
#endif
//----------------------------------------------------------------------------------------
// Variabili temporali
//----------------------------------------------------------------------------------------
unsigned long TimeDelay = intTime;       // setta a 3 minuti (180000 millisecondi) il tempo di delay tra le letture
unsigned long TimeStart = 0;             // tempo di partenza 
unsigned long TimeUltima = 0;            // tempo ultima lettura
unsigned long TimeAdesso = 0;            // tempo della lettura
long TimeDelta  = 0;                     // differenza
unsigned long tempo;
unsigned long Counter = 0;               // contatore delle letture
int sensorCPin = A0;                     //sensore commerciale misura umidità del terreno
unsigned long sensorCValue;
unsigned long sensorCMin;
unsigned long sensorCMax;
unsigned long sensorCSomma;
unsigned long UMIFlagPresent = 500;       //limite del terreno umido (minore di 500 bagnato con 850 è secco)
int sensorFPin = A1;                      //sensore fai da te misura presenza h2o nel serbatoio
unsigned long sensorFValue;
unsigned long sensorFMin;
unsigned long sensorFMax;
unsigned long sensorFSomma;
unsigned long H2OFlagPresent = 700;       //limite presenza di acqua (minore di 700 presente)
int pumpPin = 4;                         //pin collegamento pompa
int pumpHour = pumpOrario;               //ora in cui viene accesa la pompa
unsigned long pumpDelay;                 //durata del pompaggio
unsigned long pumpDelayMax = pumpDurata; //durata del pompaggio
boolean pumpFlag = false;                //Flag pompaggio
void setup() {
  TimeStart  = millis();
  TimeAdesso = TimeStart;
  TimeUltima = TimeStart;
  // attesa iniziale
  delay(intTime / 3 * 2);
  #ifdef OnSerial
    Serial.begin( 9600 );
  #endif
  #ifdef OnSerial     
    // Serial.println(Arduino);
    Serial.println("");
    Serial.println("");
    Serial.println(PitOrtoVersion);
    Serial.println("---------------------------"); 
    #ifdef OnButton     
      Serial.println("Funzionamento con Button");
    #endif
    #ifdef OnPiuDebug
      Serial.print  (" OnLed        is ");
      #ifdef OnLed
        Serial.println("on");
      #else
        Serial.println("off");
      #endif
      Serial.print  (" OnDebug      is ");
      #ifdef OnDebug
        Serial.println("on");
      #else
        Serial.println("off");
      #endif
      Serial.print  (" OnButton     is ");
      #ifdef OnButton
        Serial.println("on");
      #else
        Serial.println("off");
      #endif
      Serial.println("---------------------------");
    #endif
  #endif 
  // ---------------------------------------------------
  // Inizializzazione PIN
  // ---------------------------------------------------
  pinMode(sensorCPin, INPUT);
  pinMode(sensorFPin, INPUT);
  pinMode (pumpPin, OUTPUT);
  digitalWrite (pumpPin, LOW);
  // pinMode (7, OUTPUT);
  // ---------------------------------------------------
  // Inizializzazione RTC
  // ---------------------------------------------------
  #ifdef DS1307RTC
    if (! rtc.begin()) {
      Serial.println("Couldn't find RTC");
      while (1);
    }
    if (! rtc.isrunning()) {
      Serial.println("RTC is NOT running!");
      // following line sets the RTC to the date & time this sketch was compiled
      rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
      // This line sets the RTC with an explicit date & time, for example to set
      // January 21, 2014 at 3am you would call:
      // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
    }
  #endif
}
void loop() {
  // ---------------------------------------------------
  // fase di test usa il pin del sensore di livello acqua per accendere la pompa per 7 secondi
  // ---------------------------------------------------
  #ifdef OnButton     
	// sensorFValue = 1023 - analogRead(sensorFPin); -- per sensore fai da te 
    sensorFValue = analogRead(sensorFPin);
    #ifdef OnPiuDebug 
      Serial.print(" Button    ---> valore letto ");
      Serial.println( sensorFValue );
    #endif
    if(sensorFValue < 50)
    {
      Serial.println(" Pump      ---> on for 7 second");
      digitalWrite (pumpPin, HIGH);
      delay (60000);
      pumpFlag = true;
    }
    else
    {
      digitalWrite (pumpPin, LOW);
      pumpFlag = false;
    }
    return;
  #endif
  TimeAdesso = millis();
  TimeDelta = TimeAdesso - TimeUltima - TimeDelay;
  if (TimeDelta >= 0) {  
    TimeUltima = millis();
    Counter = Counter +1;
    // ---------------------------------------------------
    // lettura RTC
    // ---------------------------------------------------
    #ifdef DS1307RTC
      DateTime now = rtc.now();
      #ifdef OnSerial
        if(now.day() < 10)
          Serial.print('0');
        Serial.print(now.day(), DEC);
        Serial.print('/');
        if(now.month() < 10)
          Serial.print('0');
        Serial.print(now.month(), DEC);
        Serial.print('/');
        Serial.print(now.year(), DEC);
        Serial.print(" (");
        Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
        Serial.print(") ");
        if(now.hour() < 10)
          Serial.print('0');
        Serial.print(now.hour(), DEC);
        Serial.print(':');
        if(now.minute() < 10)
          Serial.print('0');
        Serial.print(now.minute(), DEC);
        Serial.print(':');
        if(now.second() < 10)
          Serial.print('0');
        Serial.print(now.second(), DEC);
        Serial.println();
      #endif
    #endif
    //orario accensione pompa e flag pompaggio eseguito
    #ifdef OnSerial
      Serial.print("  pumpHour : ");
      Serial.print(pumpHour);
      Serial.print("  pumpFlag : ");
      Serial.print(pumpFlag);
    #endif
    if  (now.hour() == pumpHour)
    {
      #ifdef OnSerial
        Serial.println("  OK  è l'ora giusta");
      #endif
      if  (pumpFlag == false)
      {
        #ifdef OnSerial
          Serial.println("  controllo livelli e umidita' per pompaggio ");
        #endif
        sensorCMin = 2000;
        sensorCMax = 0;
        sensorCSomma = 0;
        sensorFMin = 2000;
        sensorFMax = 0;
        sensorFSomma = 0;
        // lettura sensore commerciale
        for (int i = 1; i <= 10;i++)
        {
          sensorCValue = analogRead(sensorCPin);
          if (sensorCValue < sensorCMin)
          {
            sensorCMin = sensorCValue ;
          }
          if (sensorCValue > sensorCMax)
          {
            sensorCMax = sensorCValue ;
          }
          sensorCSomma = sensorCSomma + sensorCValue;
          #ifdef OnSerial
            Serial.print(".");
          #endif
          #ifdef OnPiuDebug 
            Serial.print(i);
            Serial.print("  sensorCValue ");
            Serial.print( sensorCValue );
            Serial.print("  sensorCMin ");
            Serial.print( sensorCMin );
            Serial.print("  sensorCMax ");
            Serial.print( sensorCMax );
            Serial.print("   sensorCSomma ");
            Serial.println( sensorCSomma );
          #endif
          delay(200);
        }
        sensorCValue = (sensorCSomma - sensorCMin - sensorCMax) / 8;
        // lettura sensore Fai da te
        for (int i = 1; i <= 10;i++)
        {
		  // sensorFValue = 1023 - analogRead(sensorFPin);
          sensorFValue = analogRead(sensorFPin);
          if (sensorFValue < sensorFMin)
          {
            sensorFMin = sensorFValue ;
          }
          if (sensorFValue > sensorFMax)
          {
            sensorFMax = sensorFValue ;
          }
          sensorFSomma = sensorFSomma + sensorFValue;
          #ifdef OnSerial
            Serial.print(".");
          #endif
          #ifdef OnPiuDebug 
            Serial.print(i);
            Serial.print("  sensorFValue ");
            Serial.print( sensorFValue );
            Serial.print("  sensorFMin ");
            Serial.print( sensorFMin );
            Serial.print("  sensorFMax ");
            Serial.print( sensorFMax );
            Serial.print("   sensorFSomma ");
            Serial.println( sensorFSomma );
          #endif
          delay(200);
        }
        sensorFValue = (sensorFSomma - sensorFMin - sensorFMax) / 8;
        #ifdef OnSerial
          Serial.println("");
          Serial.print("  Pin A0: ");
          Serial.print( sensorCPin );
          Serial.print(" Terreno ---> valore letto ");
          Serial.println( sensorCValue );
          Serial.print("  Pin A1: ");
          Serial.print( sensorFPin );
          Serial.print(" Serbatoio ---> valore letto ");
          Serial.println( sensorFValue );
        #endif
        if (sensorFValue < H2OFlagPresent)
        {
            #ifdef OnSerial
              Serial.print("  Livello H2O OK ");
            #endif
            if (sensorCValue > UMIFlagPresent )
            {
              #ifdef OnSerial
                Serial.print("Terreno Secco: pump ON ");
              #endif
              digitalWrite (pumpPin, HIGH);
              pumpFlag = true;
      			  // ---------------------------------------------------
      			  //
      			  // calcolo del tempo di pompaggio
      			  //
      			  // u = umidità
      			  // t = tempo
      			  //
      			  // per u1 = 500 ( 500 = UMIFlagPresent)--> t1 = 0.1 * pumpDelayMax
      			  //
      			  // per u2 = 1000 ( 1000 = 2 * UMIFlagPresent) --> t2 = pumpDelayMax
      			  //
      			  // per u  = sensorCValue -->  valore letto viene fatta l'iterpolazione lineare (vale anche oltre 900)
      			  //
      			  // t = t1 + (t2 - t1) / (u2 - u1) * (u - u1)
      			  //
      			  // t = 0.1 * pumpDelayMax + (pumpDelayMax - 0.1 * pumpDelayMax ) / (2 * UMIFlagPresent - UMIFlagPresent ) * (sensorCValue - UMIFlagPresent)
      			  //
      			  //   | 0.1 * pumpDelayMax + (0.9 * pumpDelayMax) / (UMIFlagPresent) * (sensorCValue - UMIFlagPresent)
      			  //
      			  // ---------------------------------------------------
  			      pumpDelay = 0.1 * pumpDelayMax + (0.9 * pumpDelayMax) / (UMIFlagPresent) * (sensorCValue - UMIFlagPresent);
              #ifdef OnSerial
                Serial.print(" pumpDelayMax = ");
                Serial.println( pumpDelayMax );
                Serial.print(" pumpDelay    = ");
                Serial.println( pumpDelay );
              #endif
              delay(pumpDelay);
              digitalWrite (pumpPin, LOW);
              #ifdef OnSerial
                Serial.println("--> Pompaggio completato correttamente");
              #endif
            }
            else
            {
              #ifdef OnSerial
                Serial.println("Terreno umido pompaggio non necessario: pump OFF");
              #endif
              // pumpFlag = true;
            }
        }
        else
        {
            #ifdef OnSerial
              Serial.println("  Livello H2O basso: pump OFF");
            #endif
        }
        digitalWrite (pumpPin, LOW);
      }
      else
      {
        #ifdef OnSerial
          Serial.println("  pompaggio gia' eseguito");
        #endif
      }
    }
    else
    {
      #ifdef OnSerial
        Serial.println("  Non è l'ora giusta");
      #endif
      // pumpFlag = false;
    }
    #ifdef OnReset
      if  (Counter == intReset){
        #ifdef ESP8266  
          ESP.reset();
        #else
          Riavvia();
        #endif
      }
    #endif
  }
}

Scarica tutto quello che serve:

ZappocoS - 19 maggio 2018