Luchtvochtigheid – AM2303 humidity and temperature sensor

Deze kleine lelijke luchtvochtigheidsensor am2303 (datasheet) van Aosong(Guangzhou) Electronics Co.,Ltd. is de enige die misschien iets in de buurt komt van een echt mooie sensor als de SHT15 van Senserion. Deze laatste heeft een temepratuur resolutie die 10 x zo hoog ligt en een dubbele relatieve luchtvochtigheids resolutie t.o.v. de AM2303.

De Chip van Senserion is alleen 6x zo duur. Dan ga ik wel uit van een een goedkope aanbieding op ebay t.o.v. Sparkfun.com inclusief breakout board.

Conclusie:

Als je op 0,01 graad precies wil weten hoe snel bijvoorbeeld een kopje koffie afkoelt moet je de dure chip nemen. De omgevingstemperatuur en luchtvochtigheid worden door beide ongeveer even accuraat weergegeven.

Dus even accuraat, maar de 6x duurdere is 10 x preciezer.

Ik vond dit op het wetenschapsforum (.nl):

Accuratie is gekoppeld aan systematische fouten terwijl precisie (of nauwkeurigheid) gekoppeld is aan toevallige fouten.Een simpele korte vuistregel;
- Bij een precieze meting zullen alle meetuitslagen relatief dicht bij elkaar liggen, ook al ligt het geheel van uitslagen soms ver van de echte waarde.
- Bij accurate meting zullen de meetuitslagen verder van elkaar verwijderd kunnen zijn maar zal het gemiddelde van de gevonden waarden nog grosso modo overeenkomen met de echte waarde.

a) * * * X * * *
b) ***X***
c) **** X
d) * * * * * X

a: accuraat – niet precies
b: accuraat en precies
c: precies – niet accuraat
d: niet accuraat en niet precies

Maar natuurlijk zitten – of zaten – er addertjes onder het gras. De RH & Temp van de AM2303 zijn goed zat, maar de interface is lang zo mooi niet als bij de Senserion chip. De dure chip heeft naast een data lijn waarover de informatie aan de microcontroller wordt gegeven, maar ook een klok-lijn, waarmee je zelf het tempo kunt aangeven waarin de informatieoverdracht wordt afgehandeld.

De AM2303 chip daarentegen, heeft maar één lijn. Dus alle communicatie verloopt via afspraken vooraf. 70 nanoseconden tussen ‘van nul naar 1′ is een één en 40 ns =0.

Ik schrijf het extra abracadabra op, omdat het gewoon lastig is zo’n chip goed stabiel aan de praat te krijgen. Timing is alles.

Gelukkig zijn er mensen die die dingen al hebben uitgezocht. Voor de relatief nieuwe Sensor vond ik welgeteld 1 werkend voorbeeld. En dat was nog voor een mindere sensor (DHT11).

Ik ondervond twee problemen: Allereerst viel de sensor vaak zomaar uit. Nadat ik ergens een weerstandje op een plaatje van een vergelijkbare sensor zag, was het tweede probleem met een simpel 4,7 kilo ohm weerstand tussen pin 1 en 2 opgelost.

Daarnaast kreeg ik een rare read-out. Luchtvochtigheid was 1,224% en temperatuur 0,228 graden. Na een paar keer diep blazen, kreeg ik een uitslag van 3,255.

Ik herkende dit als 00000011 11111111. Dus gewoon tien bits: maximaal 4 x 256 = 1024. Ik heb de code hierop aangepast. Bij temperatuur heb ik hetzelfde gedaan. Moet alleen nog uitzoeken welk bitje aangeeft of de temperatuur boven of onder nul zit. Dat wordt weer een arduino in de vriezer…

Hier wat ik heb toegevoeg aan de kode:

voor:

    ...
    Serial.print("Current humdity = ");
    Serial.print(dht11_dat[0]);
    Serial.print(".");
    Serial.print(dht11_dat[1]);
    Serial.print("%  ");
    Serial.print("temperature = ");
    Serial.print(dht11_dat[2]);
    Serial.print(".");
    Serial.print(dht11_dat[3]);
    Serial.println("C  ");

    delay(800);//Don't try to access too frequently
}

Mijn aanpassing:

    ...
    float rh = ((dht11_dat[0]*0x100)+dht11_dat[1])/10.24;
    float tmp = ((dht11_dat[2]*0x100)+dht11_dat[3])/10.24;

    Serial.print("Current humdity = ");
    Serial.print(rh);
    Serial.print("%  ");
    Serial.print("temperature = ");
    Serial.print(tmp);
    Serial.println("C  ");

    delay(800);//Don't try to access too frequently
}

Ik krijg hier een goede read-out mee. Nu wil ik nog de SHT15 naast deze DHT sensor ansluiten om een en ander te ijken. Wil dan eigenlijk een keer alle temperatuurchips / sensors / thermistors et cetera op één ATmega zetten en alles vergelijken. Komt volgend jaar wel.

Ben blij dat de sensor werkt. Je hebt ook nog de DHT11 en de DHT22 humidity sensors. Deze kosten respectievelijk 1,50 en 5,5 euro. De AM2303 gaat meestal voor 10 euro, maar het lukte mij voor 7 euro inclusief verzendkosten. De DHT11 heeft een nauwkeurigheid van 2 graden celcius en hij gaat maar tot 50 graden. Ook bruikbaar voor ‘veel sensors’ toepassingen.

hier de hele sketch:

//ReadHumTturDHT11alternate
//ver 19Jly10

//See for more information....
//http://sheepdogguides.som/arduino/ar3ne1humDHT11.htm

//N.B. "bit" is used in the narrow, computer "1 or 0"
//   sense throughout.

//Comments on this based on Aosong AM2302, aka DHT22, datasheet.
//Believed to generally apply to DHT11 as well, except in the
//case of the DHT11, I believe the second and fourth bytes are
//always zero.

//***N.B.****
//The code WORKS... the comments may not yet be EXACTLY right.
//See the web-page cited above for latest news.

//This code works with a DHT11 humidity/ temperature sensing module
//from nuelectronics.com, complied with ver 0018 of the Arduino environment
//Sensor attached to P4 (nuelectonics shield)/ analog 0, aka digital 14.

//That "module", according to the
//nuelectronics site, and visual inspection simply provides for easy
//connection of an Aosong DHT11 unit to the nuelectronics datalogging
//shield. Only 3 wires are involved: Vcc, ground, and a single data
//line. One of the DHT11's 4 pins goes nowhere.

//You should not need to change anything except the next line to use
//the software with the sensor on a different line, or for a DHT22.

//Just "huffing" on the sensor from deeply filled lungs should show
//a near instant rise in humidity

#define DHT11_PIN 0      // ADC0...
  //even though we are using it as a digital pin.
  //Other parts of code restrict us to using
  //ADC0-5, aka D14-19

byte read_dht11_dat()
//Collect 8 bits from datastream, return them interpreted
//as a byte. I.e. if 0000.0101 is sent, return decimal 5.

//Code expects the system to have recently entered the
//dataline low condition at the start of every data bit's
//transmission BEFORE this function is called.
{
  byte i = 0;
  byte result=0;
  for(i=0; i< 8; i++){
  //We enter this during the first start bit (low for 50uS) of the byte
  while(!(PINC & _BV(DHT11_PIN)));  // wait until pin goes high
           //signalling end of start of bit's transmission.
  //Dataline will stay high for 27 or 70 uS, depending on if
  //   a 0 or a 1 is being sent, respectively
  delayMicroseconds(30);//AFTER pin is high, wait further period, to be
      //into the part of the timing diagram where a 0 or a 1 denotes
      //the datum being send. The "further period" was 30uS in the software
      //that this has been created from. I believe that a higher number
      //(45?) would be more appropriate.

  if(PINC & _BV(DHT11_PIN))//If pin still high
    result |=(1<<(7-i));// "add" (not just addition) the 1 to the
                //growing byte
  while((PINC & _BV(DHT11_PIN)));  // wait for pin to go low again, which
          //signals he START of the NEXT bit's transmission.
  }//end of "for.."
  return result;
}//end of "read_dht11_dat()"

void setup()
{
    DDRC |= _BV(DHT11_PIN);//set data pin... for now... as out(?)put
              //DDRC is data direction register for pins A0-5 are on
    PORTC |= _BV(DHT11_PIN);//(dis?)-connect internal pull up on line
              //PORTC relates to the pins A0-5 are on.
Serial.begin(9600);
delay(300);//Let system settle
Serial.println("Humidity and temperature\n\n");
delay(700);//Wait rest of 1000ms recommended delay before
  //accessing sensor.
    }

void loop()
{
    byte dht11_dat[5];//Array to hold the bytes sent from sensor. 0-4 should be enough
           //don't belive dht11_dat[5] is used.
    byte dht11_in;
    byte i;
    // Send "start read and report" command to sensor....
    // 1. pull-down i/o pin for 18ms
    PORTC &= ~_BV(DHT11_PIN);
    delay(18);
        delay(5);//TKB, frm Quine at Arduino forum
        //Aosong datasheet for DHT22 says pin should be low at least
        //500us. I infer it can be low longer without any]
        //penalty apart from making "read sensor" process take
        //longer
    PORTC |= _BV(DHT11_PIN);//Bring line high again
    delayMicroseconds(40);//DHT22 datasheet says host should
           //keep line high 20-40us, then watch for sensor taking line
           //low. That low should last 80us. Acknowledges "start read
           //and report" command.

    DDRC &= ~_BV(DHT11_PIN);//Change Arduino pin to an input, to
           //watch for the 80us low explained a moment ago.
    delayMicroseconds(40);

    dht11_in = PINC & _BV(DHT11_PIN);

    if(dht11_in){
        Serial.println("dht11 start condition 1 not met");
        return;
    }
    delayMicroseconds(80);

    dht11_in = PINC & _BV(DHT11_PIN);

    if(!dht11_in){
        Serial.println("dht11 start condition 2 not met");
        return;
    }

        //After 80us low, the line should be taken high for 80us by the
        //sensor. The low following that high is the start of the first
        //bit of the forty to come. The routine "read_dht11_dat()"
        //expects to be called with the system already into this low.
    delayMicroseconds(80);
    //now ready for data reception... pick up the 5 bytes coming from
        //   the sensor
    for (i=0; i<5; i++)
        dht11_dat[i] = read_dht11_dat();

    DDRC |= _BV(DHT11_PIN);//restore pin to in?out?put duties
    PORTC |= _BV(DHT11_PIN);//re-(dis?) connect internal pullup?

        byte dht11_check_sum = dht11_dat[0]+dht11_dat[1]+dht11_dat[2]+dht11_dat[3];
    // check check_sum
    if(dht11_dat[4]!= dht11_check_sum)
        //says "if fifth byte from sensor not the same as the sum of the first four..."
    {
        Serial.println("DHT11 checksum error");
    }
float rh = ((dht11_dat[0]*0x100)+dht11_dat[1])/10.24;
float tmp = ((dht11_dat[2]*0x100)+dht11_dat[3])/10.24;

    Serial.print("Current humdity = ");
    Serial.print(rh);
    Serial.print("%  ");
    Serial.print("temperature = ");
    Serial.print(tmp);
    Serial.println("C  ");

    delay(800);//Don't try to access too frequently
}

2 Responses to Luchtvochtigheid – AM2303 humidity and temperature sensor

  1. Robert says:

    Hoi,

    ikzelf ben ook bezig net de am2302 sensor, uit de chinese docs blijkt zowel de luchtvochtigheid als de temp in graden celcius als de totale waarde van de beide (desbetreffende…) registers gedeeld door 10.
    Een negatieve temp wordt aangegeven door het hoogste bit (1=negatief,0 =positief).
    Robert.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>