# Get DHT22 Pulse Timing with Micros()

**URL:** <https://community.particle.io/t/get-dht22-pulse-timing-with-micros/2689>\
**Category:** General\
**Created:** [February 7, 2014, 11:52pm UTC](https://community.particle.io/t/get-dht22-pulse-timing-with-micros/2689 "2014-02-07T23:52:35Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ric](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/ric/32/514_2.png) [@Ric](https://community.particle.io/u/Ric)\
**Post date:** [February 7, 2014, 11:52pm UTC](https://community.particle.io/t/get-dht22-pulse-timing-with-micros/2689/1 "2014-02-07T23:52:35Z")

</div>

I’ve gotten the DHT22 temperature-humidity sensor working using a modified version of the code posted by @wgbartley ([https://community.spark.io/t/dht22-dht11-and-similar-blocking-version/998](https://community.spark.io/t/dht22-dht11-and-similar-blocking-version/998) ). I’ve also looked at the pulse lengths using a variation of that program that uses a 1 microsecond delay and a counter inside the while loop (rather than using micros() as below). I was trying to do a similar thing using micros() to get a more accurate view of the pulse lengths, but I get bizarre readings that I can’t make sense of. Here is the code I’m using,

```
int dataPin = D4;

void setup() {
    Serial.begin(19200);
    pinMode(dataPin, OUTPUT);
    digitalWrite(dataPin, HIGH);
    read();
}

void loop() {
}

void read(void) {
    noInterrupts();
    for (int k = 0; k<4; k++) {
        delay(3000);
        
        uint8_t lastState = HIGH;
        uint8_t j = 0, i;
        unsigned long results[85];
        uint8_t state[85];
        unsigned long t0 = 0;
        unsigned long t1 = 0;
        
        Serial.println("");
        Serial.println("started!");
    
        pinMode(dataPin, OUTPUT);
        digitalWrite(dataPin, HIGH);
        delay(250);
        digitalWrite(dataPin, LOW);
        delay(20);
        
        digitalWrite(dataPin, HIGH);
        delayMicroseconds(40);
        pinMode(dataPin, INPUT);
    
        // read in timings
        for (i=0; i< 85; i++) {
            t0 = micros();
            while (digitalRead(dataPin) == lastState) {
                t1 = micros();
                if ((t1 - t0) > 1000)
                    break;
            }
    
            lastState = digitalRead(dataPin);
            results[i] = t1 - t0;
            state[i] = lastState;
    
            if ((t1 - t0) > 1000)
                break;
    
        }
    
        for (j=0; j< 85; j++) {
            delay(2);
            Serial.print(j);
            delay(2);
            Serial.print(" ");
            delay(2);
            Serial.print(results[j]);
            delay(2);
            Serial.print(" ");
            delay(2);
            Serial.print(state[j]);
            delay(2);
            Serial.print(" ");
            delay(2);
            Serial.println("");
            delay(2);
        }
    }
    Serial.println("");
    Serial.println("");
    Serial.println("Ending serial");
    interrupts();
    Serial.end();
}

```

I print out the index of the loop, the time difference in microseconds (t1 - t0), and the state of the pin. Here is a sample of the results,

```
started!
0 4279527169 0  
1 0 0  
2 16 0  
3 536871520 0  
4 134257971 0  
5 536879020 0  
6 1073756172 0  
7 536871520 0  
8 16 124  
9 16 78  
10 0 0  
11 128 32  
12 0 3  
13 0 16  
14 0 0  
15 12288 0  
16 0 177  
17 16 31  
18 536879030 0  
19 16 32  
20 536877892 124  
21 536879020 78  
22 1 0  
23 536891300 32  
24 134248479 77  
25 536877892 122 

```

Given the code, the time difference should never be bigger than 1000, and the pin state should be either 0 or 1. As you can see, the time difference values are sometimes as large as 9 figures, and the pin state, while sometimes 0, is never 1, and frequently some other number. Interestingly, the numbers are not random – I run the loop 4 times, and I get the same printout each time. Is there something wrong wight he way I’m using micros()?

---

<div class="post-metadata">

**Author:** ![BDub](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/bdub/32/5137_2.png) [@BDub](https://community.particle.io/u/BDub)\
**Post date:** [February 8, 2014, 8:03am UTC](https://community.particle.io/t/get-dht22-pulse-timing-with-micros/2689/2 "2014-02-08T08:03:43Z")

</div>

You had me at “Timing”… I’ve been working on solving this freaking crap all damn night. It’s not you, it’s this damn micros() and code… really REALLY not cool.

I don’t have a DHT22 so I first set off to write a timing emulator. This just bangs away on D4 output low for 50us, high for 27us, low for 50us, high for 70us (repeat 5000 times).

```cpp
// http://www.adafruit.com/datasheets/DHT22.pdf
// DHT22 Emulator
bool s,b = false;
void setup() {
  pinMode(D4,OUTPUT);
}

void loop() {
  for(int x=0; x<10000; x++) {
    s = !s; // toggle bit vs start transmit
    if(s) {
      digitalWrite(D4,HIGH); // 2us
      delayMicroseconds(25); // 25us (27us total HIGH = Bit 0)
      if(b) delayMicroseconds(43); // 43us (70us total HIGH = Bit 1)
      digitalWrite(D4,LOW); // 2us
      b = !b; // toggle bit value
    }
    else {
      delayMicroseconds(48); // 48us (50us total LOW = start transmit)
    }
  } 
}

```

I started with your code, and just commented out the parts that output on D4… and I did see some valid numbers very briefly at the start of the night. But then I kept seeing the weird patterns.

I went digging all over and see problems everywhere.

- digitalRead() and analogRead() return type int32\_t (signed 32 bit!) why? Could this contribute to the problem, perhaps. I tried all kinds of typecasting… not sure if it helped.
- noInterrupts() and interrupts() will do nothing for you because there are no arduino style interrupts used.
- it’s bad to do a digitalRead() twice when you are trying to track edges.
- you were saving lastState as a result after you read the “newState”
- I’m really starting to wondering if 'break;" works in this compiler!
- In the process of trying to find an answer, I re-wrote most of your code to make it easier for me to test. Now you get the Decoding side up and running, open your serial monitor, and then press the Mode button to perform a read(). If you hold down Mode it read()'s over and over. Once in a blue moon you’ll see a 2000 number, that’s when the DHT22 emulator is done with it’s 10000 loops, and takes 5-6ms to run the background tasks.
- micros() wraps at 60,000,000 which is every minute -\_-
- delay() needs to be re-written slightly

Here’s the decoder. It works pretty good… honestly I don’t know what bits started to make it work properly. This one really frustrated me! Probably 4 hours screwing with it. Just imagine how many times you could re-write this code and flash it over the air in 4 hours… yeah, that’s about how many times I did. 😄

```cpp
// DHT22 Decoder
uint32_t startTime = 0;
uint16_t dataPin = D4;
uint8_t lastState = HIGH;
uint8_t newState = HIGH;
uint32_t results[86];
uint8_t state[86];
uint32_t t0 = 0;
uint32_t t1 = 0;
uint32_t tim0[86];
uint32_t tim1[86];
bool timeOut = false;
        
void setup() {
    startTime = millis(); // capture the time that our app starts
    pinMode(dataPin, INPUT);
    Serial.begin(115200);
}

inline void read(void) {
    Serial.println("");
    Serial.println("started!");

    // read in timings
    int i,j;
    timeOut = false;
    for (i=0; (i<85) && !timeOut; i++) {
        t0 = (uint32_t)micros();
        while ((newState == lastState) && !timeOut) {
            t1 = (uint32_t)micros();
            newState = digitalRead(dataPin);
            if ((uint32_t)(t1 - t0) >= 2000) {
                timeOut = true; //break;
            }
        }
        // save the elapsed time with the correct state (lastState)
        state[i] = lastState;
        // at this point in time, newState is the new lastState ;-)
        lastState = newState;
        results[i] = (uint32_t)(t1 - t0);
        tim0[i] = (uint32_t)t0;
        tim1[i] = (uint32_t)t1;
    }
    // Only print up until a timeOut, or end of array
    for (j=0; j<i; j++) {
        delay(2);
        Serial.print(j);
        delay(2);
        Serial.print(" ");
        delay(2);
        Serial.print(results[j]);
        delay(2);
        Serial.print(" ");
        delay(2);
        Serial.print(state[j]);
        delay(2);
        Serial.print(" ");
        delay(2);
        Serial.print(tim1[j]);
        delay(2);
        Serial.print(" ");
        delay(2);
        Serial.print(tim0[j]);
        delay(2);
        Serial.print(" ");
        delay(2);
        Serial.print(tim1[j] - tim0[j]);
        delay(2);
        Serial.print(" ");
        delay(2);
        Serial.println("");
        delay(2);
    }
    Serial.println("");
    Serial.println("Ending serial");
}

void loop() {
    if(ModeBtnPressed()) {
        read();
        BUTTON_ResetDebouncedState(BUTTON1);
    }
}

bool ModeBtnPressed() {
    if(millis() - startTime > 3000) { // wait at least 3s for smart config
        if(BUTTON_GetDebouncedTime(BUTTON1) >= 250) {
            return 1;
        }
    }
    return 0;
}

```

And some sample output:

```cpp
//index, pulse time, pulse state, t1, t0, t1-t0
started!
0 51 0 56275255 56275204 51
1 24 1 56275283 56275259 24
2 48 0 56275335 56275287 48
3 68 1 56275406 56275338 68
4 47 0 56275457 56275410 47
5 25 1 56275486 56275461 25
6 47 0 56275537 56275490 47
7 64 1 56275605 56275541 64
8 48 0 56275660 56275612 48
9 24 1 56275688 56275664 24
10 47 0 56275739 56275692 47
11 68 1 56275811 56275743 68
12 47 0 56275862 56275815 47
13 24 1 56275890 56275866 24
14 48 0 56275942 56275894 48
15 67 1 56276013 56275946 67
16 48 0 56276065 56276017 48
17 24 1 56276093 56276069 24
18 47 0 56276144 56276097 47
19 68 1 56276216 56276148 68
20 47 0 56276267 56276220 47
21 24 1 56276295 56276271 24
22 48 0 56276347 56276299 48
23 67 1 56276418 56276351 67
24 48 0 56276470 56276422 48
25 27 1 56276501 56276474 27
26 48 0 56276553 56276505 48
27 70 1 56276627 56276557 70
28 48 0 56276679 56276631 48
29 24 1 56276707 56276683 24
30 47 0 56276758 56276711 47
31 68 1 56276830 56276762 68
32 47 0 56276881 56276834 47
33 24 1 56276909 56276885 24
34 48 0 56276961 56276913 48
35 67 1 56277032 56276965 67
36 48 0 56277084 56277036 48
37 24 1 56277112 56277088 24
38 47 0 56277163 56277116 47
39 68 1 56277235 56277167 68
40 47 0 56277286 56277239 47
41 25 1 56277315 56277290 25
42 48 0 56277366 56277318 48
43 68 1 56277438 56277370 68
44 48 0 56277489 56277441 48
45 24 1 56277517 56277493 24
46 48 0 56277569 56277521 48
47 67 1 56277640 56277573 67
48 47 0 56277691 56277644 47
49 24 1 56277719 56277695 24
50 48 0 56277771 56277723 48
51 67 1 56277842 56277775 67
52 48 0 56277894 56277846 48
53 24 1 56277922 56277898 24
54 47 0 56277973 56277926 47
55 68 1 56278045 56277977 68
56 47 0 56278096 56278049 47
57 24 1 56278124 56278100 24
58 48 0 56278176 56278128 48
59 67 1 56278247 56278180 67
60 48 0 56278299 56278251 48
61 24 1 56278327 56278303 24
62 47 0 56278378 56278331 47
63 68 1 56278450 56278382 68
64 51 0 56278505 56278454 51
65 24 1 56278533 56278509 24
66 47 0 56278584 56278537 47
67 67 1 56278655 56278588 67
68 47 0 56278706 56278659 47
69 24 1 56278734 56278710 24
70 48 0 56278786 56278738 48
71 67 1 56278857 56278790 67
72 48 0 56278909 56278861 48
73 24 1 56278937 56278913 24
74 47 0 56278988 56278941 47
75 68 1 56279060 56278992 68
76 51 0 56279115 56279064 51
77 21 1 56279139 56279118 21
78 51 0 56279194 56279143 51
79 68 1 56279266 56279198 68
80 47 0 56279317 56279270 47
81 24 1 56279345 56279321 24
82 48 0 56279397 56279349 48
83 67 1 56279468 56279401 67
84 48 0 56279520 56279472 48

Ending serial

```

😴 💤 g’night

---

<div class="post-metadata">

**Author:** ![Ric](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/ric/32/514_2.png) [@Ric](https://community.particle.io/u/Ric)\
**Post date:** [February 8, 2014, 11:21pm UTC](https://community.particle.io/t/get-dht22-pulse-timing-with-micros/2689/3 "2014-02-08T23:21:11Z")

</div>

@BDub, thanks for all your hard work, I appreciate it. I too worked for several days on this – having to flash the core over and over definitely slows things down (I’m used to the Xcode build cycle using the iPhone simulator which is very fast). After trying your code (which worked), I started removing things to see if I could find out what made the difference. I didn’t see any problems related to micros(), data types or the break command. I’m pretty sure the thing that made the difference was not doing the double read of the pin. This is the code, in that block that worked after sifting things out,

```
for (uint8_t i=0; i<85; i++) {
        t0 = micros();
        while (newState == lastState) {
            t1 = micros();
            newState = digitalRead(dataPin);
            if (t1 - t0 >= 500) break;
        }
    
        lastState = newState;
        state[i] = lastState;
        results[i] = t1 - t0;
        if (t1 - t0 >= 500) break;

```

The thing that still baffles me, is why I was getting values other than 0 or 1 for the pin state. Anyway, here is my modified code for reading the DHT22 using micros() instead of a delay and a counter. I changed the output to a single int so I can get both values (as well as a failed read indication) with one GET, and I parse that in an iOS app ([DHTTempAndHumidityReader](http://jmp.sh/b/5SJLRWQOzksRoArks19d)) to present the data on my iPhone.

```
#define MAXTIMINGS 85

uint8_t data[5];
int tAndH;
int dataPin = D4;

void setup() {
    Spark.variable("tAndH", &tAndH, INT);
    pinMode(dataPin, INPUT);
} 

void loop() {
    delay(2000);
    tAndH = readValues();
}

int readValues(void) {
    int _h, _t, _tAndH;
    if (read()) {
        _h = data[0];
        _h *= 256;
        _h += data[1];
        
        _t = data[2] & 0x7F;
        _t *= 256;
        _t += data[3];

        if (data[2] & 0x80)
         _t *= -1;
         _t <<= 16;    
         _tAndH = _t + _h; // combine values to get both with one GET
        return _tAndH;
    }

    return -1; // return -1 if the read fails
}

bool read(void) {
    uint8_t i, j=0;
    uint8_t lastState = HIGH;
    uint8_t newState = HIGH;
    unsigned long results[85];
    uint8_t state[85];
    unsigned long t0 = 0;
    unsigned long t1 = 0;

    data[0] = data[1] = data[2] = data[3] = data[4] = 0;

    // send start sequence to the DHT22
    pinMode(dataPin, OUTPUT);
    digitalWrite(dataPin, LOW);
    delay(20);
    digitalWrite(dataPin, HIGH);
    delayMicroseconds(40);
    pinMode(dataPin, INPUT); // switch to input to read from the DHT22

    for (i=0; i< MAXTIMINGS; i++) {
        
        t0 = micros();
        while (newState == lastState) {
            t1 = micros();
            newState = digitalRead(dataPin);
            if (t1 - t0 >= 500) break;
        }

        lastState = newState;

        if ((t1 - t0) > 500) break;

        // ignore first 4 transitions
        if (i >= 4 && lastState == 0) {
            // shove each bit into the storage bytes
            data[j/8] <<= 1;

            if ((t1 - t0) > 40) // in tests, low values were 22 to 26, and high values were 67 to 73
                data[j/8] |= 1;

            j++;
        }
    }

    // check we read 40 bits and that the checksum matches
    if ((j >= 40) && (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)))
        return true;

    return false;
}

```

---

<div class="post-metadata">

**Author:** ![BDub](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/bdub/32/5137_2.png) [@BDub](https://community.particle.io/u/BDub)\
**Post date:** [February 9, 2014, 12:29am UTC](https://community.particle.io/t/get-dht22-pulse-timing-with-micros/2689/4 "2014-02-09T00:29:22Z")

</div>

Very cool @Ric. You should put that all up on a github repo 😉

EDIT: and by the way… the state saves were weird, and so were the really large micros() values that should never be seen. Still trying to forget about this nightmare 😄

---

<div class="post-metadata">

**Author:** ![josefdz](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@josefdz](https://community.particle.io/u/josefdz)\
**Post date:** [November 13, 2014, 3:02pm UTC](https://community.particle.io/t/get-dht22-pulse-timing-with-micros/2689/6 "2014-11-13T15:02:15Z")

</div>

Hello Guys, Does anyone have a way on how to expose the sensor outside without damage it? I being using the sparkcore inside a nema box with the temp36 out on the bottom of the box and it works fine, But I like to try one of this sensors, but it looks that they it can not get wet? Or am I wrong? or Yes can they get wet? or we have to use something like this?  
[http://shop.boxtec.ch/digital-humidity-temperature-sensor-dht44-rht05-p-40846.html?language=en](http://shop.boxtec.ch/digital-humidity-temperature-sensor-dht44-rht05-p-40846.html?language=en)  
Thank You.
