DHT22, DHT11 and similar (Blocking version)

Thanks! It’s running on a 30 second cycle now, so I don’t think that’s it. I prefer the DHT22 anyways, so I’ll try that and see how it goes.

Hi @ClintonKeith, my dht11 is running on a one second interval. Works fine.


1 Like

Thanks @PaulRB & @wgbartley I plugged in a DHT22 into the same spot, changed the define to DHT22 and it works fine. I’m tracking down another DHT11 to test if the first was bad.

1 Like

I am working on porting the idDHTLib code to Spark. One problem I find with the DHT22 is that if starting conditions are not just right, it will sit there and not respond to anything. I had this problem using it with other micros as well.At this point, the code loops waiting for an response from the DHT22 after the initial “command” pulse. Unfortunately, it is not responding and the code sits in a loop waiting for the ISR to do its thing. The problem may be a timing issue which I will be testing tonight. I had to make a few adjustments to the code. There was no construct for word(), which I added and I noticed that variables being set to micros() were cast as “int”. The code works fine on a teensy 3 because “int” is actually 4 bytes but I have no idea how the Web IDE does it. So I cast the vars as unsigned longs. Because that code is in the ISR, I can’t do standard Serial.print debugging so I have to figure out something else.

I will be setting up a toolchain on my computer cause using the Web IDE is just not efficient at the stage. Hopefully, I can get the code working soon :smile:

Hi peekey, I can do Serial.print from inside interrupt code, works ok. What heppens when you try?


PaulRB, it’s just not considered good form since IRS are usually time sensitive, especially for the DHT22 ISR. It can be done, but there are side effects. However, if I just want to see if some vars are working properly, I could use Serial.print and not worry about timing actually working.

To get there though, I have to make sure the DHT22 is actually responding. Running those things at 3.3V is a hit and miss in my experience so I will have to make sure everything is good. Stay tuned!

@peekay123, yes I understand interrupt code should be as short & fast as possible. I incorrectly assumed you were saying Serial.print did not work at all for some reason. When I’ve done Serial.print in interrupt code, I’ve kept the messages short & simple and cranked the baud up to 38400.

I don’t posess a DHT22, but I do have a DHT11, and I’m not impressed with its accuracy!

I can recommend SHT21, which has accuracy similar to DHT22 but an i2c interface, which is very convenient and easy. A bit more expensive than DHT22 though. I got one from China on eBay for around £15.


PaulRB, I agree with the accuracy and the voltage impacts the readings as well I have three DHT22’s I bought for cheap but I am definitely looking at the SHTxx series for my next project. I can get an SHT10, the cheaper SHT family member, for $9 CDN on ebay and it is easy to solder. The SHT21 goes for $13 but is a difficult package to work with when prototyping. There is a board from Taiwan on eBay that goes for about $18 CDN that might be interesting. In the meantime, I will keep trying to make my DHT22 work. Thanks for the info!

Did anyone get the interrupt driven library (idDHT11) ported and taking readings from the DHT11?

I had a go and got it to compile and flash, but it appears not to be generating interrupts. I have it wired as described above. I know the sensor is good as I had it working on an Arduino previously.

A little bit of progress on my port of the interrupt driven library, I now get:

Humidity (%): 0.00
Temperature (C): 0.00
Temperature (F): 32.00

But only once, instead of every 10 seconds (its reading in a loop with a 10 second delay) and obviously the readings are wrong!

chrisb2, I can’t seem to get the DHT22 to “start up”. First the setup:

  1. A DHT22 proven to work at 3.3v (on a teensy 3) setup with and without a pull-up resistor on the data pin
  2. Modified the idDHT11 code to compile on the web IDE and extended the initiation pulse slightly to match those of the blocking version of the code.

So, I see the initiation pulse going out to the DHT22 but it does not reply. I have had this problem in the past when, on power up or restart, the data pin the the DHT is “noisy” and this causes the DHT22 to essentially lock up. I have not been able to get past this point, even with delays in the boot-up sequence.

Here is my code so far: Spark_idDHT11.cpp

I have this code working beautifully on a teensy 3 so there is no reason for it NOT to work.

My :spark: just got here!! Yay, so it’s time for the noob questions to start. I just copied and pasted the code, and it compiled fine. I hooked up my DHT22 to D2, then went into my Terminal and pasted this:

https://api.spark.io/v1/devices/DEV_ID/t \
-d access_token=SECRET_STUFF -d params=D2

The reply I get is: “error”: “Function not found”

What am I doing wrong?

1 Like

So looks like I need to use a -G? Now I’m getting an error with my access token. I’m sure it’s something stupid i’m doing.

curl https://api.spark.io/v1/devices/ID/t -G access_token=TOKEN -d params=D2

My new error is:
“code”: 400,
“error”: “invalid_request”,
“error_description”: “The access token was not found”

Your request should be:

curl -G https://api.spark.io/v1/devices/ID/t -d access_token=TOKEN

To explain what’s going on here:

curl is the tool, which generates HTTP requests
-G means that it should be a GET request (this happens by default, but when you add -d patameters it uses POST by default, so you have to explicitly state that it’s a GET)
-d access_token=TOKEN sends the access token data

Alternately, you could do:

curl "https://api.spark.io/v1/devices/ID/t?access_token=TOKEN"

This would include the access_token as a query string, and since you’re not sending any -d data, it uses GET by default, so you don’t have to explicitly say -G.

Alternately, you could type https://api.spark.io/v1/devices/ID/t?access_token=TOKEN into your web browser, since web browsers use GET requests, you’d get the same info. This doesn’t work for POST, PUT, and DELETE requests.

Hope that’s helpful! We definitely need more documentation on this stuff…

Thanks @zach! That get’s me a lot closer, And I have a better idea of how this works. Now the only problem is I keep getting a “Variable not found”

@chrisb2 - [quote=“chrisb2, post:30, topic:998”]
Did anyone get the interrupt driven library (idDHT11) ported and taking readings from the DHT11?

Yes, ported an version that uses interrupts. You can find it here - https://github.com/mtnscott/spark-core-examples

Let me know if anyone has problems with this implementation. The file is a complete example of how to read the DHT11 using interrupts.

Just wanted to reply with a complete example I worked up for @shocku992 that you can poll readings from the web:

#define MAXTIMINGS 85

#define cli noInterrupts
#define sei interrupts

#define DHT11 11
#define DHT22 22
#define DHT21 21
#define AM2301 21

#define NAN 999999

class DHT {
        uint8_t data[6];
        uint8_t _pin, _type, _count;
        bool read(void);
        unsigned long _lastreadtime;
        bool firstreading;
        DHT(uint8_t pin, uint8_t type, uint8_t count=6);
        void begin(void);
        float readTemperature(bool S=false);
        float convertCtoF(float);
        float readHumidity(void);


DHT::DHT(uint8_t pin, uint8_t type, uint8_t count) {
    _pin = pin;
    _type = type;
    _count = count;
    firstreading = true;

void DHT::begin(void) {
    // set up the pins!
    pinMode(_pin, INPUT);
    digitalWrite(_pin, HIGH);
    _lastreadtime = 0;

//boolean S == Scale.  True == Farenheit; False == Celcius
float DHT::readTemperature(bool S) {
    float _f;
    if (read()) {
        switch (_type) {
            case DHT11:
                _f = data[2];
                    _f = convertCtoF(_f);
                return _f;
            case DHT22:
            case DHT21:
                _f = data[2] & 0x7F;
                _f *= 256;
                _f += data[3];
                _f /= 10;
                if (data[2] & 0x80)
                    _f *= -1;
                    _f = convertCtoF(_f);
                return _f;
    return NAN;

float DHT::convertCtoF(float c) {
    return c * 9 / 5 + 32;

float DHT::readHumidity(void) {
    float _f;
    if (read()) {
        switch (_type) {
            case DHT11:
                _f = data[0];
                return _f;
            case DHT22:
            case DHT21:
                _f = data[0];
                _f *= 256;
                _f += data[1];
                _f /= 10;
                return _f;
    return NAN;

bool DHT::read(void) {
    uint8_t laststate = HIGH;
    uint8_t counter = 0;
    uint8_t j = 0, i;
    unsigned long currenttime;
    // pull the pin high and wait 250 milliseconds
    digitalWrite(_pin, HIGH);
    currenttime = millis();
    if (currenttime < _lastreadtime) {
        // ie there was a rollover
        _lastreadtime = 0;
    if (!firstreading && ((currenttime - _lastreadtime) < 2000)) {
        //delay(2000 - (currenttime - _lastreadtime));
        return true; // return last correct measurement
    firstreading = false;
    Serial.print("Currtime: "); Serial.print(currenttime);
    Serial.print(" Lasttime: "); Serial.print(_lastreadtime);
    _lastreadtime = millis();
    data[0] = data[1] = data[2] = data[3] = data[4] = 0;
    // now pull it low for ~20 milliseconds
    pinMode(_pin, OUTPUT);
    digitalWrite(_pin, LOW);
    digitalWrite(_pin, HIGH);
    pinMode(_pin, INPUT);
    // read in timings
    for ( i=0; i< MAXTIMINGS; i++) {
        counter = 0;
        while (digitalRead(_pin) == laststate) {
            if (counter == 255)
        laststate = digitalRead(_pin);
        if (counter == 255)
        // ignore first 3 transitions
        if ((i >= 4) && (i%2 == 0)) {
            // shove each bit into the storage bytes
            data[j/8] <<= 1;
            if (counter > _count)
                data[j/8] |= 1;

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

#define DHTPIN D2    // Digital pin D2

// IMPORTANT !! Make sure you set this to your 
// sensor type.  Options: [DHT11, DHT22, DHT21, AM2301]
#define DHTTYPE DHT22  


float h;      // humidity
float t;      // temperature
char h1[10];  // humidity string
char t1[10];  // temperature string
int f = 0;    // failed?

void setup() {
    Spark.variable("humidity", &h1, STRING);
    Spark.variable("temperature", &t1, STRING);
    Spark.variable("status", &f, INT);

void loop() {
    f = 0;
    h = dht.readHumidity();
    t = dht.readTemperature();
    if (t==NAN || h==NAN) {
        f = 1; // not a number, fail.
    else {
        f = 0; // both numbers! not failed.
        sprintf(h1, "%.2f", h); // convert Float to String
        sprintf(t1, "%.2f", t);

Read with:
curl https://api.spark.io/v1/devices/55555555/humidity?access_token=99999999

curl https://api.spark.io/v1/devices/55555555/temperature?access_token=99999999

curl https://api.spark.io/v1/devices/55555555/status?access_token=99999999

55555555 = Your Device ID
99999999 = Your Access Token ID

You can also put the URL’s for variable requests right in your browser’s address bar because they are GET requests:




1 Like

You are awesome! Thank you @BDub. Slowly but surely I’m beginning to understand how this works. One last question for the evening. I saw there was a convertCtoF function in the library. How do I go about using it?

1 Like

If you want temperatures in Fahrenheit:

Change this line:
t = dht.readTemperature();

To this:
t = dht.readTemperature(true);


1 Like

I need to adapt this for the DHT22 before I can test it. Thanks!