Go Down

Topic: Barometro DIY; consigli e aiuti per la sonda esterna (Read 2 times) previous topic - next topic

djscudo

May 11, 2013, 09:56 pm Last Edit: May 12, 2013, 09:23 am by djscudo Reason: 1
Buonasera,

come già anticipato nella presentazione, il mio primo progetto con Arduino ha visto nascere un barometro; le componenti utilizzate sono state le seguenti:
Arduino uno rev3
Arduino Ethernet Shield
TMP36 <-- termometro analogico
DHT22 <-- termometro digitale + igrometro
MPL3115A2 <-- barometro + altimetro
Display LCD contenuto nello starter kit

la realizzazione in breadboard è stata la seguente:


.. e in funzione:



il codice per gestire tutto, con sincronizzazione sul sito Cosm

Ora, torniamo al topic, la mia voglia è quella di realizzare una sonda esterna, comunicante tramite RF a 433mhz con la stazione presente in casa (Arduino + Ethernet) e magari con alimentazione a pile.

Visto il previsto uso in pile ho letto nel forum che si può abbassare la velocità di clock a 1 Mhz per limitare i consumi; ho provato a replicare tutto con una standalone (ATmega328) programmata tramite Arduino con il connettore ISP; riscritto il bootloader per funzionare a 1 Mhz.
Ho dei problemi, sembra che il sensore di pressione non sia funzionante, e l'igrometro registra valori fuori dal regolare.

Non escludo di aver effettuato errori logici e fisici; vi espongo il mio schema che momentaneamente ho disegnato:


Stavo valutando anche di spostare l'MPL3115A2 nella stazione in casa.
Secondo voi esperti, i sensori DHT22, MPL3115A2 e i futuri RF (come li ho sotto mano aggiungo dettagli) possono essere comandati dall'ATmega328 a 1Mhz?

lesto

ciao,
ottimo lavoro!
Quote
riscritto il bootloader per funzionare a 1 Mhz

uhmmm, cosa moolto error prone, perchè no hai usato quelli già fatti? hai settato in modo corretto i FUSE? vedi la gioda di menniti in megatopic
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

djscudo

Ciao lesto, grazie  :)

ho scoperto il problema alcuni giorni fa, credo sia dovuto proprio a qualche Fuse errato. Ho cambiato il clock a 8 Mhz configurando così:

Code: [Select]
atmega328bb.name=ATmega328 (8 MHz internal clock)

atmega328bb.upload.protocol=stk500
atmega328bb.upload.maximum_size=32768
atmega328bb.upload.speed=57600
atmega328bb.upload.using=arduino:arduinoisp
atmega328bb.bootloader.low_fuses=0xE2
atmega328bb.bootloader.high_fuses=0xDA
atmega328bb.bootloader.extended_fuses=0x05
atmega328bb.bootloader.path=arduino:atmega
atmega328bb.bootloader.file=ATmegaBOOT_168_atmega328_pro_8MHz.hex
atmega328bb.bootloader.unlock_bits=0x3F
atmega328bb.bootloader.lock_bits=0x0F
atmega328bb.build.mcu=atmega328p
atmega328bb.build.f_cpu=8000000L
atmega328bb.build.core=arduino:arduino
atmega328bb.build.variant=standard


è differente rispetto alla megaguida di Menniti, ho provato con quella riportata sulla guida ma ho avuto problemi.

Ho rivisto "l'architettura" della sonda esterna, adesso è semplicemente un ATmega standalone, un sensore DHT22 e un trasmettitore RF a 433Mhz; tutto alimentato da una batteria per cellulari.

Attualmente la sonda esterna comunica via RF con la postazione arduino uno + ethernet presente in casa equipaggiata con un altro sensore DHT22. Ho implementato l'invio dei dati rilevati sul servizio Xively (ex Cosm).

Lo scambio prevede la seguente sintassi "/T00.00/U00.00#"

il codice sulla sonda:
Code: [Select]
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/power.h>

#include <VirtualWire.h>
#include <DHT22.h>

const int DHT22_PIN = 7;
const int DHT22_power = 6;

//const int LedRF_trans = 11;
const int RF_power = 9;
const int RF_transmit_pin = 10;

byte masterLoop=7;
byte correct = 1;
byte checker = 0;

volatile int counter = 0;

DHT22 myDHT22(DHT22_PIN);

void setup() {
 Serial.begin(9600);
 Serial.println("supertest");

      // Initialise the IO and ISR
 vw_set_tx_pin(RF_transmit_pin);
 //vw_set_rx_pin(receive_pin);
 //vw_set_ptt_pin(transmit_en_pin);
 vw_set_ptt_inverted(true); // Required for DR3100
 vw_setup(1200); // Bits per sec
 
 MCUSR = 0;
 wdt_disable();

 pinMode(DHT22_power,OUTPUT);
 digitalWrite(DHT22_power,LOW);
 
 set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // setta registri per il modo sleep
 sleep_enable();                        // abilita la sleep all'uso
 
 
}

// watchdog interrupt
ISR (WDT_vect) {
  wdt_disable();  // disable watchdog
}  // end of WDT_vect


void loop() {
 if (counter==masterLoop) {
   digitalWrite(DHT22_power,HIGH);
 
   delay(2000);
  // Read values from the sensor
   DHT22 loclDHT22 = getDHT22value();
 
   
    Serial.println("spegno il pin");
     digitalWrite(DHT22_power,LOW);
     
   if(correct==1){
     float temp_c = loclDHT22.getTemperatureC();
     float humidity = loclDHT22.getHumidity();
 
     Serial.print(temp_c); Serial.print("C "); Serial.println(humidity);    
   
     digitalWrite(RF_power, HIGH);
     delay(1500);
     
     char dataToSend[24];
     
     char _buffer[10];
     dtostrf(temp_c, 2, 2, _buffer);

     ////////////////////////////////////////////////////////////////////////////////////////    
     char dataToSend2[24];
     char _buffer2[10];
     dtostrf(humidity, 2, 2, _buffer2);
     sprintf(dataToSend2,  "/T%s/U%s#", (char*)_buffer, (char*)_buffer2);
     
     Serial.println(dataToSend2);
     vw_send((uint8_t *)dataToSend2, strlen(dataToSend2));
     vw_wait_tx(); // Wait until the whole message is gone
   
   
     digitalWrite(RF_power, LOW);
   }

   counter=1;
 } else {
   counter=counter+1;
 }
 Serial.print ("Numero cicli: "); Serial.println (counter);
 delay (500);

 // disable ADC
 ADCSRA = 0;  

 // clear various "reset" flags
 MCUSR = 0;    
 // allow changes, disable reset
 WDTCSR = _BV (WDCE) | _BV (WDE);
 // set interrupt mode and an interval
 WDTCSR = _BV (WDIE) | _BV (WDP3) | _BV (WDP0);    // set WDIE, and 8 seconds delay
 wdt_reset();  // pat the dog
 
 set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
 sleep_enable();

 // turn off brown-out enable in software
 MCUCR = _BV (BODS) | _BV (BODSE);
 MCUCR = _BV (BODS);
 sleep_cpu ();  
 
 // cancel sleep as a precaution
 sleep_disable();
 
} // end of loop


DHT22 getDHT22value(){
 correct = 1;
 
 if(checker<10){
   checker++;
   DHT22_ERROR_t errorCode;
   delay(2200);
   Serial.print("Requesting DHT22: ");
   errorCode = myDHT22.readData();
   switch(errorCode) {
     case DHT_ERROR_NONE:
       Serial.print(myDHT22.getTemperatureC()); Serial.print("C "); Serial.print(myDHT22.getHumidity()); Serial.println("%");
       checker= 0;
       return myDHT22;
       break;
     case DHT_ERROR_CHECKSUM:
       Serial.print("check sum error "); Serial.print(myDHT22.getTemperatureC()); Serial.print("C "); Serial.print(myDHT22.getHumidity()); Serial.println("%");
      // return myDHT22;
      getDHT22value();
       break;
     case DHT_BUS_HUNG:
       Serial.println("BUS Hung ");
       break;
     case DHT_ERROR_NOT_PRESENT:
       Serial.println("Not Present ");
       break;
     case DHT_ERROR_ACK_TOO_LONG:
       Serial.println("ACK time out ");
       break;
     case DHT_ERROR_SYNC_TIMEOUT:
       Serial.println("Sync Timeout ");
       break;
     case DHT_ERROR_DATA_TIMEOUT:
       Serial.println("Data Timeout ");
       getDHT22value();
       break;
     case DHT_ERROR_TOOQUICK:
       Serial.println("Polled to quick ");
       break;
   }
 } else {
   checker = 0;
   Serial.println("impossibile rilevare valori");
   correct = 0;
 }
}


djscudo

e il codice sulla postazione in casa:
Code: [Select]
#include <SPI.h>
#include <Ethernet.h>
#include <HttpClient.h>
#include <Xively.h>
#include <DHT22.h>
#include <VirtualWire.h>


//Definizione PIN
DHT22 myDHT22(7);


IPAddress dns_local (192, 168, 1, 1);
IPAddress ip_dis ( 192, 168, 1, 3 );
// MAC address for your Ethernet shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

float extTemp = 0;
float extUmid = 0;


unsigned long lastCheck = 0;
const unsigned long tempoMaster = 60000;
// Initialize the Xively library
char xivelyKey[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";


char bufferValue[140]; // enough space to store the string we're going to send
XivelyDatastream datastreams[] = {
 XivelyDatastream("temp_int", strlen("temp_int"), DATASTREAM_FLOAT),
 XivelyDatastream("temp_ext", strlen("temp_ext"), DATASTREAM_FLOAT),
 XivelyDatastream("umid_int", strlen("umid_int"), DATASTREAM_FLOAT),
 XivelyDatastream("umid_ext", strlen("umid_ext"), DATASTREAM_FLOAT),
};
// Finally, wrap the datastreams into a feed
XivelyFeed feed(129843, datastreams, 4 /* number of datastreams */);

EthernetClient client;
XivelyClient xivelyclient(client);


void setup() {

 //inizialize Serial comunication
 Serial.begin(9600);
 delay(2000);

 Serial.println("Inizializzazione board...");
 Serial.print("Tempo di loop (ms): "); Serial.println(tempoMaster);

 Serial.print("IP dispositivo: "); Serial.println(ip_dis);

 Serial.println("Done.");
 Ethernet.begin(mac, ip_dis, dns_local);
 delay(1000);
 
 vw_set_tx_pin(8);
 vw_set_rx_pin(9);
 vw_set_ptt_pin(3);
 vw_set_ptt_inverted(true); // Required for DR3100
 vw_setup(1200); // Bits per sec
 vw_rx_start();
 Serial.println("started RF receiver");  
   

}




void loop(){
 
 uint8_t buf[VW_MAX_MESSAGE_LEN];
 uint8_t buflen = VW_MAX_MESSAGE_LEN;
 
 if (vw_get_message(buf, &buflen)) // Non-blocking
   {
int i;

 //      digitalWrite(led_pin, HIGH); // Flash a light to show received good message
// Message with a good checksum received, print it.
       Serial.println("################");
Serial.print("Got: ");
char str[5];
       char umid[5];
   //    char type = buf[1];
       
       str[0] = buf[2];
       str[1] = buf[3];
       str[2] = buf[4];
       str[3] = buf[5];
       str[4] = buf[6];
   
       umid[0] = buf[9];
       umid[1] = buf[10];
       umid[2] = buf[11];
       umid[3] = buf[12];
       umid[4] = buf[13];


 //      digitalWrite(led_pin, LOW);

       Serial.print("Temperatura: "); Serial.println(str);
         extTemp= atof(str);
         
       Serial.print("Umidita: "); Serial.println(umid);    
         extUmid= atof(umid);
   }  
   
   
  if (millis() - lastCheck > tempoMaster) {
 
     delay(2000);
     DHT22 loclDHT22 = getDHT22value();

     float fTemp = loclDHT22.getTemperatureC();
     float fUmid = loclDHT22.getHumidity();

     Serial.print("temperatura interna: "); Serial.println(fTemp);
     Serial.print("temperatura esterna: "); Serial.println(extTemp);
     Serial.print("umidita interna: "); Serial.println(fUmid);
     Serial.print("umidita esterna: "); Serial.println(extUmid);

       
         datastreams[0].setFloat(fTemp);
         datastreams[1].setFloat(extTemp);
         datastreams[2].setFloat(fUmid);
         datastreams[3].setFloat(extUmid);
     

         
         Serial.println("Uploading it to Xively");
         int ret = xivelyclient.put(feed, xivelyKey);
         Serial.print("xivelyclient.put returned ");
         Serial.println(ret);

   lastCheck = millis();
   }
 
}

DHT22 getDHT22value(){

DHT22_ERROR_t errorCode;
delay(500);
 Serial.print("Requesting DHT22: ");
 errorCode = myDHT22.readData();
 switch(errorCode) {
   case DHT_ERROR_NONE:
     Serial.print(myDHT22.getTemperatureC()); Serial.print("C "); Serial.print(myDHT22.getHumidity()); Serial.println("%");
     return myDHT22;
     break;
   case DHT_ERROR_CHECKSUM:
     Serial.print("check sum error "); Serial.print(myDHT22.getTemperatureC()); Serial.print("C "); Serial.print(myDHT22.getHumidity()); Serial.println("%");
     return myDHT22;
     break;
   case DHT_BUS_HUNG:
     Serial.println("BUS Hung ");
     break;
   case DHT_ERROR_NOT_PRESENT:
     Serial.println("Not Present ");
     break;
   case DHT_ERROR_ACK_TOO_LONG:
     Serial.println("ACK time out ");
     break;
   case DHT_ERROR_SYNC_TIMEOUT:
     Serial.println("Sync Timeout ");
     break;
   case DHT_ERROR_DATA_TIMEOUT:
     Serial.println("Data Timeout ");
     break;
   case DHT_ERROR_TOOQUICK:
     Serial.println("Polled to quick ");
     break;
 }

}




prossimo step:
- aggiungere il sensore di pressione nella stazione in casa e trasformarla in una standalone con ethernet e display  8)

lesto

attento a NON confondere il atmega328 con il atmega328P, l'ardiono di defult usa la versione P, che sta per low power, e quindi vari settaggi sono mlto differenti.
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

djscudo


lesto

non ho mai lavorato cn gli spleep, ma questa mi pare una buona guida:

https://www.sparkfun.com/tutorials/309
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

djscudo

Grazie per la guida, questo fine settimana me la studio un po' :)

comunque il codice presente sulla sonda mette il processore in sleep

lesto

#8
May 30, 2013, 02:40 pm Last Edit: May 30, 2013, 02:44 pm by lesto Reason: 1
non so che sleep riesci ad ottenere, ma lì si raggiunge il limite minimo (da datasheet) dell'atmega328p: 1 uA, circa 22 anni con una batteria a bottone da orologio.

esdit:q quello è per il 328, il 328p arriva a 0.1uA
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

djscudo

non vorrei dire fesserie ma dal multimetro mi sembra di stare sul limite minimo quando è in sleep; in funzionamento non mi ricordo proprio.
Stasera riprovo a monitorarlo

leo72

Il limite di 0,1 uA mi pare difficile che lo possa raggiungere se spenge solo l'ADC e lascia alimentato tutto il resto, a cominciare dal watchdog per poi passare ai vari timer, al circuito di brown-out, all'AC.  ;)
Disattivare non vuol dire spengere, volevo far capire questo concetto.  :smiley-sweat:

Quando entra in modalità Power-Down il micro toglie il clock a diverse periferiche ma queste continuano a ricevere comunque l'alimentazione. Consumano poco perché "non girano" ma un minimo di corrente continuano a prendersela. Il core PicoPower permette una gestione capillare di tutte le periferiche integrate, dove si può andare letteralmente a staccare la spina ad ogni cosa che non serve.


lesto

non ved il video, si blocca dopo uno o due secondi
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

leo72

Riesco a vederlo ma non tornano i valori .
Il datasheet dice che con WDT attivo in Power Down il consumo è di minimo 4.2 uA.
Come fa a te a registrare 0.0?  :smiley-sweat:

djscudo

Proprio per questo motivo ho voluto fare un video!
Non riesco a spiegarmelo nemmeno io..

Il Multimetro sembra essere ok, ho provato a utilizzarlo per altre cose; ora sto provando a tenerlo alimentato dalla batteria fino ad esaurimento

Go Up
 

Quick Reply

With Quick-Reply you can write a post when viewing a topic without loading a new page. You can still use bulletin board code and smileys as you would in a normal post.

Warning: this topic has not been posted in for at least 120 days.
Unless you're sure you want to reply, please consider starting a new topic.

Note: this post will not display until it's been approved by a moderator.
Name:
Email:

shortcuts: alt+s submit/post or alt+p preview