Simple library for the DHT11 temperature and humidity sensor. Forked from an existing Mbed DHT11 project.

Dependents:   UoY-DHT11-test

Simple DHT11 temperature and humidity library.

Example usage

#include "mbed.h"
#include "DHT11.h"

DHT11 dht(D8); // Change pin name here if required

main()
{
    printf("T:%d, H:%d\r\n", dht.readTemperature(), dht.readHumidity());
}

The sensor may be read as often as desired, but temperature and humidity values are cached and will only be updated if they are more than 2 seconds old. This is the underlying sensor update rate.

Please note that this project has been modified only enough to make it work for its intended purpose. Various parts of this project still need work, and the source code should not be seen as an example of best practice.

DHT11.cpp

Committer:
ajp109
Date:
2021-09-15
Revision:
13:11d0770eb603
Parent:
12:af1eadec17e5

File content as of revision 13:11d0770eb603:

/* Copyright (c) 2014 Shigenori Inoue, MIT License
 * Modified by Andy Pomfret 2021
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
 * and associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "DHT11.h"

// Constructor
DHT11::DHT11(PinName pin) : io(pin, PIN_INPUT, OpenDrain, 1), io_irq(pin)
{
    io_irq.rise(callback(this, &DHT11::pos_edge));
    io_irq.fall(callback(this, &DHT11::neg_edge));
    io_irq.disable_irq();
    t.start();
    readNewData();
}

// Destructor
DHT11::~DHT11(void) {}

// Constants
const int DHT11::t_tol_start = 2;
const int DHT11::t_tol_pulse = 10;

// Reading the data bits from the DHT11
int DHT11::readData(void)
{
    // Checking the measurement frequency
//    if (chrono::duration_cast<chrono::milliseconds>(t.elapsed_time()).count() < 2000) {
//        t.reset();
//        return READ_TOO_OFTEN;
//    }
    
    // Initialize
    init();

    // Checking the data bus
    if (io == 0) {
        t.reset();
        return BUS_BUSY;
    }

    // Sending start signal, low signal for around 10 ms
    t.reset();
    io.output();
    io = 0;
    thread_sleep_for(10 + t_tol_start);
    io.input();
    io = 1;
    

    // Waiting for the start of the response signal
    t.reset();
    do {
        if (t.elapsed_time().count() > 100) {
            t.reset();
            return NOT_PRESENT;
        }
    } while (io == 1);

    // Waiting for the start of the ready signal
    t.reset();
    do {
        if (t.elapsed_time().count() > 100) {
            t.reset();
            return NOT_READY;
        }
    } while (io == 0);

    // Waiting for the end of the ready signal
    t.reset();
    do {
        if (t.elapsed_time().count() > 100) {
            t.reset();
            return WATCHDOG_ERR;
        }
    } while (io == 1);

    // Starting the pulse width sensing
    // by the use of interrupts
    io_irq.enable_irq();

    do {
        wait_us(100);
        if (wdt > 50) {
            t.reset();
            return WATCHDOG_ERR;
        }
        wdt++;
    } while (eod == false);

    // Calculating the check sum
    chksum = (data >> 32)
             + (data >> 24)
             + (data >> 16)
             + (data >> 8);

    if ((chksum & 0xff) != (data & 0x00000000ff)) {
        t.reset();
        return CHKSUM_ERR;
    } else {
        t.reset();
        return OK;
    }
}

void DHT11::readNewData(void) {
    do; while (readData() != OK);
}

// Extracting humidity data from the received data
int DHT11::readHumidity(void)
{
    if (t.elapsed_time() >= 2000ms) {
        readNewData();
    }
    return (data & 0xff00000000) >> 32;
}

// Extracting temperature data from the received data
int DHT11::readTemperature(void)
{
    if (t.elapsed_time() >= 2000ms) {
        readNewData();
    }
    return (data & 0x0000ff0000) >> 16;
}

// Initialization of variables
void DHT11::init(void)
{
    t_pulse_us = 0;
    data = 0;
    chksum = 0;
    cnt = 0;
    wdt = 0;
    eod = false;
    t.reset();
}

void DHT11::pos_edge(void)
{
    // Disabling the interrupts
    io_irq.disable_irq();

    // Initializing the Timer
    t.reset();

    // Enabling the interrupts
    io_irq.enable_irq();
}

void DHT11::neg_edge(void)
{
    // Disabling the interrupts
    io_irq.disable_irq();

    // Reading the positive pulse width
    t_pulse_us = t.elapsed_time().count();

    // Detecting 0 if the pulse width ranges around 25 us
    if (25 - t_tol_pulse <= t_pulse_us && t_pulse_us <= 30 + t_tol_pulse) {
        // Shifting the data buffer and not adding 1 (because this bit is zero)
        data = data << 1;

        // Counting up the bits
        cnt++;
    }

    // Detecting 1 if the pulse width ranges from 70 us
    else if (70 - t_tol_pulse <= t_pulse_us && t_pulse_us <= 70 + t_tol_pulse) {
        // Shifting the data buffer and adding 1 (because this bit is one)
        data = data << 1;
        data++;

        // Counting up the bits
        cnt++;
    }

    // Detecting the end of Data
    if (cnt < 40) {
        // Enabling the interruptions
        io_irq.enable_irq();
    } else {
        eod = true;
    }
}