[LIB] Interrupt driven DHT11 Lib (idDHT11)

Hello, I'm working with DuinOS and the DHT11 library has some problems working with it 'cause the timing. 'cause of this i had improved the library to use ineterrupts on pins and liberate the cpu meanwhile. I have proved it in a Mega2560 with arduino 1.03 and is working bery well.

You can get this lib at https://github.com/niesteszeck/idDHT11

Looks good!

I can see only one remark that is STOPPED is with double P ;)

I'll make a link in the playground article - http://playground.arduino.cc/Main/DHT11Lib - to this thread so people can find it easier! (done)

Sorry for that (I speek spanish as my native language)
Now is corrected

No need to apologize for a great job!

Hi can someone help please with newb question. Trying to read temp/rh with the dht11. In the code samples and examples I came across a VERY cool code example that not only reads temp/rh BUT reads dewpoint calcs. Which is very useful for me. Only problem is that being a NEWB Im sure that Im doing something wrong in loading the code to the Arduino.

Arduino Mega 2560
Mega shield

So code that has information I want is here-

http://playground.arduino.cc//Main/DHT11Lib?action=sourceblock&num=1

but when I try to compile/upload, i get the error message “DHT11 does NOT have a name” ARRGGHH…

now I notice that along with this code there are two other files
one labeled
dht11.h (code is here http://playground.arduino.cc//Main/DHT11Lib?action=sourceblock&num=2)

the other labeled
dht11.cpp (code is here http://playground.arduino.cc//Main/DHT11Lib?action=sourceblock&num=3)

so not sure (because I am a newb) if these are necessary? help define the name of the DHT or what…

Can someone help please…

thanks again for your patience in advance…

Hello, your question isn’t related to this specific lib. You are using example code and source files from the original DHT11 lib. THIS lib that I published here is another version, that works different (interrupt driven way) and has his own example codes. If you want you can try it downloading it from the link to github in the original post of this thread.

@niesteszeck

Can this DHT22 patch be included in the library? - http://forum.arduino.cc/index.php?topic=175356.0 -

imho it is worth the effort to merge!

I'm talking on the other thread. If the modification is working on a dht22 sensor, I'll analyze how to mix both sensors in the same library, other way we have to make 2 libraries. Other thing is that I dont have a dht22 sensor, so any modification must be proved by others (or someone can gift me one :D)

It should be quite easy to add DHT22 support into one library - add a flag that indicates the type and select the right - bits to data - function in the end.

the code in the other thread looks good to me, so I think you can start designing/integrating to create a first beta.

Yes sure, but the modification to DATA section on the interrupt that is proposed on http://forum.arduino.cc/index.php?topic=175356.0 I need to confirm that is actually working to integrate into the other library.

Or you can build it into the lib and you have something to be verified by someone.

That's right. I'll make it for DHT22 to, but give me some time to do it, I'm working and don't have to much time to my personal projects, so please be patient. I'm goig to continue this conversation on the other thread

Is it possible to use multiple dht11 sensors with this library? The test so far only reports -7 for second sensor.

I’m not pretty sure if it’s working with two sensors, but I have two, and when I was developing it I used the 2. If I’m not wrong it should work with two sensors. The only thing is that you have to use 2 different pins that has interrupts

In a quick review, I can say that looks like the interrupt is not being called. What method are you calling to get the -7 value, can you share the code.

A small example that is based on the example that comes with the lib:

/*
  Board	          int.0	  int.1	  int.2	  int.3	  int.4	  int.5
 Uno, Ethernet	  2	  3
 Mega2560	  2	  3	  21	  20	  19	  18
 Leonardo	  3	  2	  0	  1
 Due	          (any pin, more info http://arduino.cc/en/Reference/AttachInterrupt)
 */

#include <idDHT11.h>

int idDHT11pinA = 2; //Digital pin for comunications
int idDHT11intNumberB = 0; //interrupt number (must be the one that use the previus defined pin (see table above)
int idDHT11pinB = 3; //Digital pin for comunications
int idDHT11intNumberB = 1; //interrupt number (must be the one that use the previus defined pin (see table above)

//declaration
void dht11_wrapperA(); // must be declared before the lib initialization
//declaration
void dht11_wrapperB(); // must be declared before the lib initialization

// Lib instantiate
idDHT11 DHT11A(idDHT11pinA,idDHT11intNumberA,dht11_wrapperA);
idDHT11 DHT11B(idDHT11pinB,idDHT11intNumberB,dht11_wrapperB);

// This wrapper is in charge of calling 
// mus be defined like this for the lib work
void dht11_wrapperA() {
  DHT11A.isrCallback();
}
// This wrapper is in charge of calling 
// mus be defined like this for the lib work
void dht11_wrapperB() {
  DHT11B.isrCallback();
}

if you test this small example (need to be completed the loop and setup functions), please tell me how it goes. If it works, you can make a pull request to add an example that use 2 sensors on github, so everyone wins. If not, we can review why and analyze if it will be possible and add this functionality to the lib, anyway, everyone wins :).

Sorry for the long wait, i was swamped by another aspect of my project. Now it's working. The problem was the missing DHT11B.acquire(); Is there any other reason than debugging purpose for this part of code?

while (DHT11A.acquiring())
    ;
  int result = DHT11A.getStatus();
  switch (result)
  {
    case IDDHTLIB_OK:
      Serial.println("OK");
      break;
    case IDDHTLIB_ERROR_CHECKSUM:
      Serial.println("Error\n\r\tChecksum error");
      break;
    case IDDHTLIB_ERROR_ISR_TIMEOUT:
      Serial.println("Error\n\r\tISR Time out error");
      break;
    case IDDHTLIB_ERROR_RESPONSE_TIMEOUT:
      Serial.println("Error\n\r\tResponse time out error");
      break;
    case IDDHTLIB_ERROR_DATA_TIMEOUT:
      Serial.println("Error\n\r\tData time out error");
      break;
    case IDDHTLIB_ERROR_ACQUIRING:
      Serial.println("Error\n\r\tAcquiring");
      break;
    case IDDHTLIB_ERROR_DELTA:
      Serial.println("Error\n\r\tDelta time to small");
      break;
    case IDDHTLIB_ERROR_NOTSTARTED:
      Serial.println("Error\n\r\tNot started");
      break;
    default:
      Serial.println("Unknown error");
      break;
  }

because it work just fine without it, and i didn't figured out how to change it for the second sensor.

Here is the modified code. Sorry for the bad formating :blush:

/*
  Board              int.0      int.1      int.2      int.3      int.4      int.5
 Uno, Ethernet    2      3
 Mega2560     2      3      21     20     19     18
 Leonardo     3      2      0      1
 Due              (any pin, more info http://arduino.cc/en/Reference/AttachInterrupt)
 */

#include 

int idDHT11pinA = 2; //Digital pin for comunications
int idDHT11intNumberA = 0; //interrupt number (must be the one that use the previus defined pin (see table above)
int idDHT11pinB = 3; //Digital pin for comunications
int idDHT11intNumberB = 1; //interrupt number (must be the one that use the previus defined pin (see table above)

//declaration
void dht11_wrapperA(); // must be declared before the lib initialization
//declaration
void dht11_wrapperB(); // must be declared before the lib initialization

// Lib instantiate
idDHT11 DHT11A(idDHT11pinA, idDHT11intNumberA, dht11_wrapperA);
idDHT11 DHT11B(idDHT11pinB, idDHT11intNumberB, dht11_wrapperB);




void setup()
{
  Serial.begin(115200);
  Serial.println("idDHT11 Example program for two sensors");
  Serial.print("LIB version: ");
  Serial.println(IDDHT11LIB_VERSION);
  Serial.println("---------------");
}
// This wrapper is in charge of calling
// mus be defined like this for the lib work
void dht11_wrapperA() {
  DHT11A.isrCallback();
}
// This wrapper is in charge of calling
// mus be defined like this for the lib work
void dht11_wrapperB() {
  DHT11B.isrCallback();
}
void loop()
{
  Serial.print("\nRetrieving information from sensors: ");
  Serial.print("Read sensor: ");
  //delay(100);
  DHT11B.acquire();
  DHT11A.acquire();
  while (DHT11A.acquiring())
    ;
  int result = DHT11A.getStatus();
  switch (result)
  {
    case IDDHTLIB_OK:
      Serial.println("OK");
      break;
    case IDDHTLIB_ERROR_CHECKSUM:
      Serial.println("Error\n\r\tChecksum error");
      break;
    case IDDHTLIB_ERROR_ISR_TIMEOUT:
      Serial.println("Error\n\r\tISR Time out error");
      break;
    case IDDHTLIB_ERROR_RESPONSE_TIMEOUT:
      Serial.println("Error\n\r\tResponse time out error");
      break;
    case IDDHTLIB_ERROR_DATA_TIMEOUT:
      Serial.println("Error\n\r\tData time out error");
      break;
    case IDDHTLIB_ERROR_ACQUIRING:
      Serial.println("Error\n\r\tAcquiring");
      break;
    case IDDHTLIB_ERROR_DELTA:
      Serial.println("Error\n\r\tDelta time to small");
      break;
    case IDDHTLIB_ERROR_NOTSTARTED:
      Serial.println("Error\n\r\tNot started");
      break;
    default:
      Serial.println("Unknown error");
      break;
  }
  
  Serial.println("************************************************************");
  Serial.println("*********************************Sensor 1*******************");
  Serial.println("************************************************************");
  Serial.print("Humidity (%): ");
  Serial.println(DHT11A.getHumidity(), 2);

  Serial.print("Temperature (oC): ");
  Serial.println(DHT11A.getCelsius(), 2);

  Serial.print("Temperature (oF): ");
  Serial.println(DHT11A.getFahrenheit(), 2);

  Serial.print("Temperature (K): ");
  Serial.println(DHT11A.getKelvin(), 2);

  Serial.print("Dew Point (oC): ");
  Serial.println(DHT11A.getDewPoint());

  Serial.print("Dew Point Slow (oC): ");
  Serial.println(DHT11A.getDewPointSlow());
  Serial.println("************************************************************");
  Serial.println("*********************************Sensor 2*******************");
  Serial.println("************************************************************");
  Serial.print("Humidity (%): ");
  Serial.println(DHT11B.getHumidity(), 2);

  Serial.print("Temperature (oC): ");
  Serial.println(DHT11B.getCelsius(), 2);

  Serial.print("Temperature (oF): ");
  Serial.println(DHT11B.getFahrenheit(), 2);

  Serial.print("Temperature (K): ");
  Serial.println(DHT11B.getKelvin(), 2);

  Serial.print("Dew Point (oC): ");
  Serial.println(DHT11B.getDewPoint());

  Serial.print("Dew Point Slow (oC): ");
  Serial.println(DHT11B.getDewPointSlow());

  delay(2000);
}

I've added an example that use 2 sensor, please try it at https://github.com/niesteszeck/idDHT11/tree/master/examples/idDHT11_Lib_2sensors_example

One problem with your example is that it doesn't check if the B sensor end acquiring. so maybe sometimes you could get error values.

The part that you said is for debugging, is only to know which error was causing a problem. you can erase it, but you should do something like this to be sure you receive a good measure

....
while (DHT11A.acquiring()) // check if first sensor has ended acquiring
    ;
int result = DHT11A.getStatus();
if(result != IDDHTLIB_OK)
   //HANDLE THE ERROR 
   ......  
} else {
   // DO WHATEVER YOU WANT with the data of the sensor
   ......
}

Thank you, that works like a charm.

Hello,

I'm trying to use idDHTLib with a DHT22 on a Pro 5V, using port 3 on the Pro (and therefore interrupt number 1). But I cannot read any value, everytime I've got a CheckSum error.

Any idea of what I'm doing wrong ?

Regards,

edit : ok my very bad, I do not noticed I had to change the callback method. Sorry !

buenos dias,

cordial saludo serian tan amables de ayudarmen en este error que me sale al cargar el programa.

soy novato o nuevo en este campo.

sketch_may27a.ino:17:17: fatal error: DHT.h: No such file or directory compilation terminated. Error de compilación

gracias david

Hi, very nice library.

I would like to make an addition to catch a transmission timeout while recieving a talagram, for example due to a bad connection (dupont wires anyone):

/*
FILE: idDHT11.cpp
VERSION: 0.1
PURPOSE: Interrupt driven Lib for DHT11 with Arduino.
LICENCE: GPL v3 (http://www.gnu.org/licenses/gpl.html)
DATASHEET: http://www.micro4you.com/files/sensor/DHT11.pdf

Based on DHT11 library: http://playground.arduino.cc/Main/DHT11Lib
*/

#include “idDHT11.h”
#define DEBUG_IDDHT11

idDHT11::idDHT11(int pin, int intNumber,void (*callback_wrapper)()) {
init(pin, intNumber,callback_wrapper);
}

void idDHT11::init(int pin, int intNumber, void (*callback_wrapper) ()) {
this->intNumber = intNumber;
this->pin = pin;
this->isrCallback_wrapper = callback_wrapper;
hum = 0;
temp = 0;
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
state = STOPPED;
status = IDDHTLIB_ERROR_NOTSTARTED;
}

int idDHT11::acquire() {
if (state == STOPPED || state == ACQUIRED) {

//set the state machine for interruptions analisis of the signal
state = RESPONSE;

// EMPTY BUFFER and vars
for (int i=0; i< 5; i++) bits = 0;

  • cnt = 7;*

  • idx = 0;*

  • hum = 0;*

  • temp = 0;*

  • // REQUEST SAMPLE*

  • pinMode(pin, OUTPUT);*

  • digitalWrite(pin, LOW);*

  • delay(18);*

  • digitalWrite(pin, HIGH);*

  • delayMicroseconds(40);*

  • pinMode(pin, INPUT);*

  • // Analize the data in an interrupt*

  • us = micros();*

  • us_global = us;*

  • attachInterrupt(intNumber,isrCallback_wrapper,FALLING);*

  • return IDDHTLIB_ACQUIRING;*

  • } else*

  • return IDDHTLIB_ERROR_ACQUIRING;*
    }
    int idDHT11::acquireAndWait() {

  • acquire();*

  • while(acquiring())*

  • ;*

  • return getStatus();*
    }
    void idDHT11::isrCallback() {

  • int newUs = micros();*

  • int delta = (newUs-us);*

  • us = newUs;*

  • if (delta>6000) {*

  • status = IDDHTLIB_ERROR_ISR_TIMEOUT;*

  • state = STOPPED;*

  • detachInterrupt(intNumber);*

  • return;*

  • }*

  • switch(state) {*

  • case RESPONSE:*

  • if(delta<25){*

  • us -= delta;*

  • break; //do nothing, it started the response signal*

  • } if(125<delta && delta<190) {*

  • state = DATA;*

  • } else {*

  • detachInterrupt(intNumber);*

  • status = IDDHTLIB_ERROR_RESPONSE_TIMEOUT;*

  • state = STOPPED;*

  • }*

  • break;*

  • case DATA:*

  • if(delta<10) {*

  • detachInterrupt(intNumber);*

  • status = IDDHTLIB_ERROR_DELTA;*

  • state = STOPPED;*

  • } else if(60<delta && delta<155) { //valid in timing*

  • if(delta>90) //is a one*

  • bits[idx] |= (1 << cnt);*

  • if (cnt == 0) { // whe have fullfilled the byte, go to next*

  • cnt = 7; // restart at MSB*

  • if(idx++ == 4) { // go to next byte, if whe have got 5 bytes stop.*

  • detachInterrupt(intNumber);*

  • // WRITE TO RIGHT VARS*

  • // as bits[1] and bits[3] are allways zero they are omitted in formulas.*

  • hum = bits[0];*

  • temp = bits[2];*

  • uint8_t sum = bits[0] + bits[2]; *

  • if (bits[4] != sum) {*

  • status = IDDHTLIB_ERROR_CHECKSUM;*

  • state = STOPPED;*

  • } else {*

  • status = IDDHTLIB_OK;*

  • state = ACQUIRED;*

  • }*

  • break;*

  • }*

  • } else cnt–;*

  • } else {*

  • detachInterrupt(intNumber);*

  • status = IDDHTLIB_ERROR_DATA_TIMEOUT;*

  • state = STOPPED;*

  • }*

  • break;*

  • default:*

  • break;*

  • }*
    }
    bool idDHT11::acquiring() {

  • int newUs = micros();*

  • if (state != ACQUIRED && state != STOPPED)*

  • {*

  • if (newUs-us_global>6000) *

  • {*

  • status = IDDHTLIB_ERROR_ISR_TIMEOUT;*

  • state = STOPPED;*

  • detachInterrupt(intNumber);*

  • return false;*

  • }*

  • else*

  • {*

  • return true; *

  • }*

  • }*

  • else*

  • {*

  • return false;*

  • }*
    }
    int idDHT11::getStatus() {

  • return status;*
    }
    float idDHT11::getCelsius() {

  • IDDHT11_CHECK_STATE;*

  • return temp;*
    }
    float idDHT11::getHumidity() {

  • IDDHT11_CHECK_STATE;*

  • return hum;*
    }
    float idDHT11::getFahrenheit() {

  • IDDHT11_CHECK_STATE;*
    _ return temp * 1.8 + 32;_
    }
    float idDHT11::getKelvin() {

  • IDDHT11_CHECK_STATE;*

  • return temp + 273.15;*
    }
    // delta max = 0.6544 wrt dewPoint()
    // 5x faster than dewPoint()
    // reference: http://en.wikipedia.org/wiki/Dew_point
    double idDHT11::getDewPoint() {

  • IDDHT11_CHECK_STATE;*

  • double a = 17.271;*

  • double b = 237.7;*
    double temp_ = (a * (double) temp) / (b + (double) temp) + log( (double) hum/100);
    double Td = (b * temp_) / (a - temp_);

  • return Td;*

}
// dewPoint function NOAA
// reference: http://wahiduddin.net/calc/density_algorithms.htm
double idDHT11::getDewPointSlow() {

  • IDDHT11_CHECK_STATE;*
  • double A0= 373.15/(273.15 + (double) temp);*
    _ double SUM = -7.90298 * (A0-1);_
    _ SUM += 5.02808 * log10(A0);_
    _ SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1) ;_
    _ SUM += 8.1328e-3 * (pow(10,(-3.49149*(A0-1)))-1) ;_
  • SUM += log10(1013.246);*
    _ double VP = pow(10, SUM-3) * (double) hum;_
  • double T = log(VP/0.61078); // temp var*
    _ return (241.88 * T) / (17.558-T);_
    }
    // EOF