giovedì 22 novembre 2012

ORTOLINO: influenza della temperatura

Dopo alcune prove, che consistevano nello spostare ORTOLINO con tutto il vaso di terra dal balcone a 12 °C all'inteno della casa a 21°C, ho constatato che la resistenza del suolo non cambia. Poi ho messo acqua nel vaso fino a veder comparire un filo d'acqua nel piattello sotto. Questo credo sia un segnale che la terra nel vaso è satura d'acqua, la resistenza è scesa fino a 10 kohm. Dalla taratura fatta in precedenza a questa resistenza corrisponde un contenuto di acqua pari al 15% circa.  Bisogna tener presente che la percentuale si riferisce al peso totale di terra+acqua.
Bene adesso credo che sia arrivato il momento di provare ORTOLINO sul campo, registrare i dati e magari osservare a vista quando il terreno avrebbe bisogno di essere irrigato, in modo da individuare i valori di resistenza limite, che servono a far scattare l'irrigazione automatica.

Ancora su ORTOLINO

In questi giorni sto provando ORTOLINO per lunghi periodi. L'obiettivo è quello di sperimentare la durata delle batterie (4 AAA) e l'attendibilità delle misure di resistenza del terreno con il sensore di umidità. Da una prima prova con una trasmissione dati ogni secondo e batterie IKEA, la durata è stata di 5 gg e 14 ore.  Ho quindi cambiato il programma, facendo trasmettere il Jeenode ogni 30 secondi. Adesso è in funzione dal 19/11. Intanto mi è sorto il dubbio che le misure di soil moisture siano influenzate dalla temperatura del terreno. Infatti questo è riscontrabile dalla letteratura, ma vorrei verificare sperimentalmente la differenza tra misure sulla stessa terra a due temperature diverse: quella del balcone, intorno a 10 °C, e quella dentro casa a circa 21°C.
Per chi fosse interessato a vedere il programma caricato su ORTOLINO, è qui sotto. Noterete alcuni commenti in inglese che derivano dal programma originale del Jeelabs, da cui sono partito.


/*   Trasmette le variabili misurate da Ortolino
struttura del pacchetto di 10 byte trasmesso
1 - 2  RH  resistenza del soil moisture in centinaia di ohm
3 - 4  T  temperatura del suolo in decimi di grado
5 - 6  L  luminosità in unità digit
7 - 8    libero
9 - 10   Vcc  in mV

*/
#include <JeeLib.h>
#include <avr/sleep.h>
ISR(WDT_vect) { Sleepy::watchdogEvent(); }
Port an1 (1);
Port an2 (2);
Port an3 (3);
Port an4 (4);
MilliTimer readoutTimer, aliveTimer;
//word runningAvg1;
word runningAvg2;
word runningAvg3;
word runningAvg4;
byte radioIsOn;
word pluto[5];
int  nodeID;
int ECHO = 0;  // Print debug
float R1 = 55.3;  // Kohm
float VCC = 3.3;
float Vconv = VCC/1023;
float V1=0;
float V2=0;
float RH1=0;
float RH2=0;
float RH=0;
float diff = 0;
float temper= 0;

//////////function for reading power supply/////////////////
long readVcc() { // SecretVoltmeter from TinkerIt
long result;
  // Read 1.1V reference against AVcc
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = 1126400L / result; // Back-calculate AVcc in mV
  return result;
 }
///////////////////////////////////////////////////////
void setup () {
    // initialize the serial port and the RF12 driver
    Serial.begin(57600);
    Serial.print("\n[pof66]");
    nodeID = rf12_config();
    if(ECHO == 1){
      delay(1000);
    Serial.println(nodeID);
    }
    // set up easy transmissions at 30 sec rate
    rf12_easyInit(30);  
//  setta come INPUT le 4 porte analogiche
    an1.mode2(INPUT);
    an2.mode2(INPUT);
    an3.mode2(INPUT);
    an4.mode2(INPUT);
//  setta come output la porta digitale 1 e 2
    an1.mode(OUTPUT);
    an2.mode(OUTPUT);
//  pull up resistors on analog ports

    an1.digiWrite2(0); //no pullup soil moisture
    an2.digiWrite2(0); // no pullup termometer TMP36GZ
    an3.digiWrite2(1);  // pullup photoresistor
    an4.digiWrite2(1);
    
// prime the running average
 //   runningAvg1 = an1.anaRead();
    runningAvg2 = 0;
    runningAvg3 = 0;
    runningAvg4 = 0;
// start with the radio on
    radioIsOn = 1;
}

////////////////////////////////////////////////
static void lowPower (byte mode) {
    // disable the ADC
    byte prrSave = PRR, adcsraSave = ADCSRA;
    ADCSRA &= ~ bit(ADEN);
    PRR &= ~ bit(PRADC);
    // go into power down mode
    set_sleep_mode(mode);
    sleep_mode();
    // re-enable the ADC
    PRR = prrSave;
    ADCSRA = adcsraSave;
}
////////////////////////////////////////////////////
static void loseSomeTime (word ms) {
    // only slow down for longer periods of time, as this is a bit inaccurate
    if (ms > 100) {
        word ticks = ms / 32 - 1;
        if (ticks > 127)    // careful about not overflowing as a signed byte
            ticks = 127;
        rf12_sleep(ticks);  // use the radio watchdog to bring us back to life
        lowPower(SLEEP_MODE_PWR_DOWN); // now we'll completely power down
        rf12_sleep(0);      // stop the radio watchdog again
        // adjust the milli ticks, since we've just missed lots of them
        extern volatile unsigned long timer0_millis;
        timer0_millis += 32U * ticks;
    }
}
//////////////////////////////////////////////////////////
void loop () {
    // switch to idle mode while waiting for the next event
    lowPower(SLEEP_MODE_IDLE);
    // keep the easy tranmission mechanism going
    if (radioIsOn && rf12_easyPoll() == 0) {
        rf12_sleep(0); // turn the radio off
        radioIsOn = 0;
    }
    // if we will wait for quite some time, go into total power down mode
    if (!radioIsOn)
        loseSomeTime(readoutTimer.remaining());
    // only take  sensors reading once a second
    // fa una lettura dei sensori ogni 30 secondi
    if (readoutTimer.poll(30000)) {
      
 // sensor power supply for measuring V1, i.e. P1-D on and P2-D off
      
        an1.digiWrite(1);
        an2.digiWrite(0);
        Sleepy::loseSomeTime(1000);
//        delay(1000);
        V1 =  Vconv*an1.anaRead();
        
 // sensor power supply for measuring V2, i.e. P1-D off and P2-D on
    
        an1.digiWrite(0);
        an2.digiWrite(1);
        Sleepy::loseSomeTime(1000);
//        delay(1000);
        V2 =  Vconv*an1.anaRead();

 //  compute RH

    diff = abs(3.3 - V2);
    if(diff < 0.001){
      RH2 = 5000.0;
    }
    else{
     RH2 = R1*V2/(3.3 - V2);
    }
    if(V1 < 0.001){
      RH1 = 5000.0;
    }
    else{
     RH1 = R1*(3.3 - V1)/V1;
    }
     RH = 5*(RH1+RH2);  // 0.1 kohm
//
     runningAvg2 = an2.anaRead();
     runningAvg3 = an3.anaRead();
     runningAvg4 = an4.anaRead();  
//       
     pluto[0] =  word(RH);
     temper = 10*(25 + (100*Vconv*runningAvg2-75));
     pluto[1] =  word(temper);  // gradi in decimi interi
     pluto[2] =  1023 - runningAvg3;  // unità digit per la luminosità
     pluto[3] =  runningAvg4;  
     pluto[4] =  word(readVcc()); // read power supply in mV 
// send measurement data, but only when it changes
      char sending = rf12_easySend(&pluto, sizeof pluto);
//   Backup  //////////////////////////////////
   if(ECHO == 1){
       Serial.print(" Node ID: ");
       Serial.print(nodeID);
       Serial.print(" n.byte payload: ");
       Serial.println(sizeof pluto);
       Serial.print(" P1: ");
       Serial.print(pluto[0]);
       Serial.print(" P2: ");
       Serial.print(pluto[1]);
       Serial.print(" P3: ");
       Serial.print(pluto[2]);
       Serial.print(" P4: ");
       Serial.print(pluto[3]);
       Serial.print(" Vcc: ");
       Serial.println(pluto[4]);
   }
///////////////////////////////////////////////
   
        // force a "sign of life" packet out every 60 seconds
        if (aliveTimer.poll(60000))
            sending = rf12_easySend(0, 0); // always returns 1
        if (sending) {
            // make sure the radio is on again
            if (!radioIsOn)
                rf12_sleep(-1); // turn the radio back on
            radioIsOn = 1;
        }
    }
}

mercoledì 14 novembre 2012

Nuovo sensore termometrico con telelettura e zero consumo di energia

Ho risolto il problema della misura di temperatura esterna con consumo energetico nullo!!

Si può leggere a distanza, non richiede batterie e ha un range da -40 a +50 °C.  Provare per credere!

giovedì 8 novembre 2012

Taratura di Ortolino

La taratura di ortolino è stata fatta prendendo un campione di terriccio, essicato al forno, pesato e messo in un vaso dove è stato poi "piantato" ortolino. Alla terra si sono aggiunte quantità di acqua note e misurata la resistenza. Dopo varie misure si è ottenuta la seguente curva di taratura:

 La quantità di acqua in ascisse è espressa come percentuale della massa totale (acqua+terra).
Bisogna tener presente che questa curva può variare in funzione del tipo di terra nella quale si trova Ortolino. Pertanto vale la pena ripetere la procedura di taratura per terreni diversi.

Il sensore di temperatura, costituito da un integrato TMP36GZ non ha bisogno di taratura in quanto il livello di uscita è di 750 mV a 25°C e cambia di 10 mV / °C .

Il sensore di luce ha invece bisogno di taratura, ma può essere usato qualitativamente prendendo alcuni suoi valori in corrispondenza di varie condizioni di illuminazione (sole pieno, tramonto, notte...)

mercoledì 7 novembre 2012

Ortolino ?

Visto che ogni realizzazione con Arduino è chiamata con un nome che finisce in "ino", così ho chiamato la versione praticamente definitiva del soil moisture meter, descritto nei precedenti post, con il nome ORTOLINO. Se qualcuno ha in mente qualcosa di meglio, si faccia avanti!!

La palletta da ping pong che si vede contiene una fotoresistenza, che diminuisce il suo valore all'aumentare della luce ambiente. L'intento è stato quello di completare la stazione per la misura del contenuto d'acqua nel terreno con un sensore di luce e con uno di temperatura: il filo che esce dal tubo.
Il jeenode contenuto all'interno del tubo, trasmette i valori della resistenza del terreno, della temperatura del terreno o dove si vuole posizionare la sonda, e un valore in mV inversamente proporzionale alla luce che batte sulla pallina.
Dopo varie prove con il soil moisture sensor (SMS) descrito nei miei precedenti post, quello che avevo chiamato carota bianca, ho deciso di sostituirlo con due più semplici bulloni in acciaio inox, come si vede nella foto successiva.  Infatti la carota rispondeva troppo lentamente alle variazioni di bagnatura. Il problema delle tensioni galvaniche ai capi degli elettrodi permane anche con i due bulloni, ma ho visto che il sistema di alimentazione che si inverte, riduce al minimo questo effetto.
Lo schema elettrico dei tre sensori è descritto nelle figure successive.
La prima mostra i circuiti equivalenti del SMS nelle due situazioni in cui si viene a trovare invertendo la sua alimentazione. Le due formule riguardano il calcolo della resistenza del sensore nelle due configurazioni. i due valori così trovati vengono poi mediati tra loro in modo da ridurre l'influenza delle tensioni galvaniche e dell'eventuale polarizzazione degli elettrodi. Il significato dei simboli è riportato sotto la figura.




Vs : è la d.d.p. galvanica prodotta dal Soil Moisture Sensor (SMS)
Vcc: è il valore “High” della d.d.p. sul piedino digitale P1D o P2D
P1A: è l’input analogico della porta P1
P1D: è l’input digitale della porta P1
P2D: è l’input digitale della porta P2
Rs : è la resistenza del SMS
R1: 56 Kohm
V1 : è la tensione misurata su P1A
V2: è la tensione misurata su P2A




Continua nel prossimo post.