NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Example Code for Humidity & Temperature Sensor - DHT11 / DHT22

April 06, 2012
by dtolan
dtolan's Avatar

Hello, Has anyone written up the code (Nerdkit compatible "C") to read the output from the DHT11/DHT22 sensor -

It is a inexpensive Humidity & Temperature sensor - Here is the datasheet - http://www.adafruit.com/datasheets/DHT22.pdf

Please excuse the vendor - I did not see a humidity sensor available from Nerdkits - or I would have picked it up here

April 07, 2012
by pcbolt
pcbolt's Avatar

@ dtolan -

I don't remember seeing anything on these forums about that particular model. It uses a Variable Pulse Width protocol (proprietary?) to communicate with the MCU. Nice thing is it is a single wire bus line and aside from a start trigger, the communication is one way. It is not as simple as other more established protocols so you will need to do some interesting programming to make things work. You will definitely need to implement timer and pin change interrupts, but if you break everything down into manageable subroutines, it should work fine. There are 3 Nerdkit tutorials you should go through if you are not familiar with interrupt programming... "Real Time Clock", "Keyboard" and "ODB II". If you are up for the challenge...keep posting here I'm sure you can get assistance.

April 07, 2012
by esoderberg
esoderberg's Avatar

dtolan,

These functions might help. I used them to measure the pulse width for a two axis accelerometer, but they should give you a start for any pulse width measurement. The functions below allow for pulse width measurement on two pins, PC4 and PC5.

First to set up the interrupts:

 void init_accelerometer(){
//starts and stops time with PWM input from accel

  //make PC4/PC5 input pins
  DDRC &= ~(0b11<<PC4);

  //Enable PIN Change Interrupt 1 - This enables interrupts on pins
  //PCINT14...8 see p70 of datasheet
  PCICR |= (1<<PCIE1);

  //Set the mask on Pin change interrupt 1 so that only PCINT12,13 (PC4,5) triggers
  //the interrupt. see p71 of datasheet
  PCMSK1 |= (1<<PCINT12) | (1<<PCINT13);
}

And then the interrupt that is now called whenever PC4 or PC5 changes:

        ISR(PCINT1_vect){

        //This is the raw input from the PWM accelerometer.

        if(((PINC>>PC4) ^ oldpincstatus) ==0b01) {//true if PC4 has changed

        if(PINC & (1<<PC4)) {t1x = time;}// if change in PC4 plus high ---  ie start of pulse then mark start time t1x

        else {t2x = time; //if change in PC4 plus low -- IE end of pulse, mark time at end t2x --- t2x - t1x = pulse width

        // t2x-t1x = Pulse width from accellerometor.  Ax equation below converts this PW into accel, assumes MEMSIC accel 
        //input at PC4.  Tilt right pos, tilt left neg.  Below gives result in .1 m/sec ^2 units or .01g.

        Ax =(39 - (t2x-t1x));}
        }
         else {

         if(PINC & (1<<PC5)) {t1y = time;}// if change in PC5 plus high ---  ie start of pulse then mark start time t1x

        else {t2y = time; //if change in PC5 plus low -- IE end of pulse, mark time at end t2y --- t2y - t1y = pulse width

        // t2x-t1x = Pulse width from accellerometor.  Ax equation below converts this PW into accel, assumes MEMSIC accel 
        //input at PC4.  Tilt right pos, tilt left neg.  Below gives result in .1 m/sec ^2 units or .01g.

        Ay =(39 - (t2y-t1y));}

        }
        oldpincstatus = ((PINC>>PC4) & 0b11);
        }

These functions rely on having a running clock in the code as well; direct from NK code:

    // Clock set up

    void time_setup() {
      // setup Timer0:
      // CTC (Clear Timer on Compare Match mode)
      // TOP set by OCR0A register
                         TCCR0A |= (1<<WGM01);
      // clocked from CLK/
      // which is 20000000/64, or 312500 increments per second
                         TCCR0B = 0;
                         TCCR0B |= (1<<CS01) | (1<<CS00); 
      // because it counts 0, 1, 2,3,4, 0, 1, 2 ...
      // so 0 through 3 equals 4 events
                       OCR0A = 39;
      // enable interrupt on compare event
      // (312500 / 40 =  7812.5 per second)
                          TIMSK0 |= (1<<OCIE0A);
                             }

    // the_time will store the elapsed time
    // (7812.5 = 1 second)
    // 
    // note that this will overflow eventually
    //
    // This variable is marked "volatile" because it is modified
    // by an interrupt handler.  Without the "volatile" marking,
    // the compiler might just assume that it doesn't change in 
    // the flow of any given function (if the compiler doesn't
    // see any code in that function modifying it -- sounds 
    // reasonable, normally!).
    volatile int64_t time;

    ISR(TIMER0_COMPA_vect) {
      // when Timer0 gets to its Output Compare value,
      // elapsed time (0.000128 seconds per count).
      time++;
    }
April 07, 2012
by dtolan
dtolan's Avatar

Thank you for the feedback , I was thinking that measuring the pulse width was the way to go, and the examples provided should help out a lot.

Thanks again Dan

May 10, 2012
by reddog30jen
reddog30jen's Avatar

I would really love to see someone post code for this sensor as well. I purchased the DHT11 to add into my weather station I am making for a school project.(In/Out Temp+Humidity+barometric pressure+wind speed) After realizing that the coding for it would be rather difficult I decided to go with analog sensors. I would still like to see the type of code required to get the data from this digital sensor. I am trying a variation of esoderberg's code above to read pulse width from wind sensor from Inspeed which is basically a reed switch but havn't tried it yet, also not sure if it will work. Any input anyone??

Post a Reply

Please log in to post a reply.

Did you know that the printf format string "%.3f" will show three digits after the decimal point? Learn more...