Interrupt driven DHT11/DHT22 library, port of Arduino idDHTLib (https://github.com/niesteszeck/idDHTLib)

Dependents:   NewDHT11Test

idDHTLib.cpp

Committer:
kfigiela
Date:
2013-11-19
Revision:
0:53913db38502

File content as of revision 0:53913db38502:

/*
    FILE:       idDHTLib.cpp
    VERSION:    0.0.3
    PURPOSE:    Interrupt driven Lib for DHT11 and DHT22 for mbed.
    LICENCE:    GPL v3 (http://www.gnu.org/licenses/gpl.html)
    DATASHEET: http://www.micro4you.com/files/sensor/DHT11.pdf
    DATASHEET: http://www.adafruit.com/datasheets/DHT22.pdf
    
    Based on idDHT11 library: https://github.com/niesteszeck/idDHT11
    Based on DHTLib library: http://playground.arduino.cc/Main/DHTLib
    Based on code proposed: http://forum.arduino.cc/index.php?PHPSESSID=j6n105kl2h07nbj72ac4vbh4s5&topic=175356.0
    Mbed port of Arduino library: https://github.com/niesteszeck/idDHTLib
    
    Changelog:
        v 0.0.1
            fork from idDHT11 lib
            change names to idDHTLib
            added DHT22 functionality
        v 0.0.2
            Optimization on shift var (pylon from Arduino Forum)
        v 0.0.3
            Timing correction to finally work properly on DHT22
            (Dessimat0r from Arduino forum)
 */

#include "idDHTLib.h"
#define DEBUG_idDHTLIB

idDHTLib::idDHTLib(PinName pin, void (*callback_wrapper)()): inOut(pin), intIn(pin) {
    init(pin,callback_wrapper);
}

void idDHTLib::init(PinName pin,  void (*callback_wrapper) ()) {
    this->pin = pin;
    this->isrCallback_wrapper = callback_wrapper;
    hum = 0;
    temp = 0;
    inOut.output();
    inOut = 1;
    state = STOPPED;
    status = IDDHTLIB_ERROR_NOTSTARTED;
}

int idDHTLib::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[i] = 0;
        cnt = 7;
        idx = 0;
        hum = 0;
        temp = 0;
    
        // REQUEST SAMPLE
        inOut.output();
        inOut = 0;
        wait_ms(18);
        inOut = 1;
        wait_us(25);
        inOut.input();
        t.start();
 
        handler = intIn.fall(isrCallback_wrapper);
        
        return IDDHTLIB_ACQUIRING;
    } else
        return IDDHTLIB_ERROR_ACQUIRING;
}
int idDHTLib::acquireAndWait() {
    acquire();
    while(acquiring())
        ;
    return getStatus();
}
void idDHTLib::dht11Callback() {
    isrCallback(false);
}
void idDHTLib::dht22Callback() {
    isrCallback(true);
}

void idDHTLib::isrCallback(bool dht22) {
    int delta = t.read_us();
    t.reset();
    if (delta>6000) {
        status = IDDHTLIB_ERROR_TIMEOUT;
        state = STOPPED;
        intIn.fall_remove(handler);
        return;
    }
    switch(state) {
        case RESPONSE:
            if(delta<25){
                break; //do nothing, it started the response signal
            } if(125<delta && delta<190) {
                state = DATA;
            } else {
                intIn.fall_remove(handler);
                status = IDDHTLIB_ERROR_TIMEOUT;
                state = STOPPED;
            }
            break;
        case DATA:
            if(60<delta && delta<145) { //valid in timing
                bits[idx] <<= 1; //shift the data
                if(delta>100) //is a one
                    bits[idx] |= 1;
                if (cnt == 0) {  // when we have fulfilled the byte, go to the next
                        cnt = 7;    // restart at MSB
                        if(++idx == 5) { // go to next byte; when we have got 5 bytes, stop.
                            intIn.fall_remove(handler);
                            // WRITE TO RIGHT VARS 
                            uint8_t sum;
                            if (dht22) {
                                hum = (bits[0] << 8 |  bits[1]) * 0.1;
                                temp = (bits[2] & 0x80 ?
                                    -(bits[2] & 0x7F << 8 | bits[3]) :
                                    (bits[2] << 8 | bits[3]))
                                * 0.1;
                                sum = bits[0] + bits[1] + bits[2] + bits[3];
                                printf("DHT22 Bits: %02d %02d %02d %02d %02d sum=%02d\r\n", bits[0],bits[1],bits[2],bits[3],bits[4],sum&0xff);
                            
                            } else {
                                hum    = bits[0]; 
                                // as bits[1] and bits[3] are always zero they are omitted in formulas.
                                temp = bits[2];
                                sum = bits[0] + bits[2];
                            }  
                            if (bits[4] != (sum&0xFF)) {
                                status = IDDHTLIB_ERROR_CHECKSUM;
                                state = STOPPED;
                            } else {
                                status = IDDHTLIB_OK;
                                state = ACQUIRED;
                            }
                            break;
                        }
                } else cnt--;
            } else if(delta<10) {
                intIn.fall_remove(handler);
                status = IDDHTLIB_ERROR_DELTA;
                state = STOPPED;
            } else {
                intIn.fall_remove(handler);
                status = IDDHTLIB_ERROR_TIMEOUT;
                state = STOPPED;
            }
            break;
        default:
            break;
    }
}
bool idDHTLib::acquiring() {  
    if (state != ACQUIRED && state != STOPPED) {   
        int delta = t.read_us();
        if (delta>6000) {
            status = IDDHTLIB_ERROR_TIMEOUT;
            state = STOPPED;
            intIn.fall_remove(handler);
            return false;
        }    
        return true;
    }
    return false;
}
int idDHTLib::getStatus() {
    return status;
}
float idDHTLib::getCelsius() {
    IDDHTLIB_CHECK_STATE;
    return temp;
}

float idDHTLib::getHumidity() {
    IDDHTLIB_CHECK_STATE;
    return hum;
}

float idDHTLib::getFahrenheit() {
    IDDHTLIB_CHECK_STATE;
    return temp * 1.8 + 32;
}

float idDHTLib::getKelvin() {
    IDDHTLIB_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 idDHTLib::getDewPoint() {
    IDDHTLIB_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 idDHTLib::getDewPointSlow() {
    IDDHTLIB_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