giovedì 22 novembre 2012

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;
        }
    }
}

Nessun commento:

Posta un commento