DHT11 temperature/humidity sensor retrieves "nan" from temperature and a stable meaningful humidity value

Code written in accordance with Tracker Eval Board Tutorials | Tutorials | Particle
The tracker Log retrieves “nan” on temperature and ~38 on humidity. Time to time temperature is measured and retrieved as 23. Serial data output on “Grove_Temperature_And_Humidity_Sensor.cpp” at lines 145-151 yield

27, 0, 2E, 10, 46 =? 65

at nan

27, 0, 17, 8, 46 =? 46

at 23 degrees centigrade.

@rickkas7 - when you have a moment can you take a look?

That is likely to happen because the DHT-11 is not a great sensor to use on Gen 3 Particle devices, even though it’s included in the kit. Any number of I2C sensors such as the DS75 and SHT-31D work far better, especially with the Tracker One.

It’s very common to get nan results with the Grove_Temperature_And_Humidity_Sensor library, because the sensor fails to read properly. Bits slip due to interrupt latency because the BLE radio on the nRF52840 runs at a high priority, and runs even if interrupts are disabled via noInterrupts().

0000099452 [app] INFO: temp=nan hum=19.000000
0000101452 [app] INFO: temp=nan hum=22.000000
0000103452 [app] INFO: temp=nan hum=22.000000
0000105452 [app] INFO: temp=nan hum=22.000000
0000107452 [app] INFO: temp=nan hum=22.000000
0000109452 [app] INFO: temp=nan hum=22.000000
0000111452 [app] INFO: temp=nan hum=22.000000
0000113452 [app] INFO: temp=nan hum=22.000000
0000115452 [app] INFO: temp=nan hum=22.000000
0000117452 [app] INFO: temp=nan hum=22.000000
0000119452 [app] INFO: temp=22.000000 hum=22.000000
0000455453 [app] INFO: temp=nan hum=23.000000
0000457453 [app] INFO: temp=22.000000 hum=22.000000
0000459453 [app] INFO: temp=22.000000 hum=23.000000
0000461453 [app] INFO: temp=22.000000 hum=22.000000
0000463453 [app] INFO: temp=nan hum=23.000000
0000465453 [app] INFO: temp=22.000000 hum=22.000000
0000467456 [app] INFO: temp=nan hum=0.000000
0000469453 [app] INFO: temp=22.000000 hum=23.000000
0000471453 [app] INFO: temp=22.000000 hum=22.000000
0000473453 [app] INFO: temp=nan hum=23.000000
0000475453 [app] INFO: temp=nan hum=22.000000

If you really want to use the DHT11, the best solution is to use the DHT22Gen3_RK library.

Using that library instead produces rock-solid output because it uses the nRF52 I2S (sound) peripheral to sample the bits from the sensor using the hardware DMA peripheral so it’s unaffected by system interrupts.

0000054920 [app] INFO: sampleResult=0 tempF=71.6 tempC=22.0 humidity=20.0 tries=1
0000056920 [app] INFO: sampleResult=0 tempF=71.6 tempC=22.0 humidity=24.0 tries=1
0000058920 [app] INFO: sampleResult=0 tempF=71.6 tempC=22.0 humidity=24.0 tries=1
0000060920 [app] INFO: sampleResult=0 tempF=71.6 tempC=22.0 humidity=24.0 tries=1
0000062920 [app] INFO: sampleResult=0 tempF=71.6 tempC=22.0 humidity=24.0 tries=1
0000064920 [app] INFO: sampleResult=0 tempF=71.6 tempC=22.0 humidity=24.0 tries=1
0000066920 [app] INFO: sampleResult=0 tempF=71.6 tempC=22.0 humidity=24.0 tries=1
0000068921 [app] INFO: sampleResult=0 tempF=71.6 tempC=22.0 humidity=24.0 tries=1
0000070921 [app] INFO: sampleResult=0 tempF=71.6 tempC=22.0 humidity=23.0 tries=1
0000072920 [app] INFO: sampleResult=0 tempF=71.6 tempC=22.0 humidity=24.0 tries=1
0000074920 [app] INFO: sampleResult=0 tempF=71.6 tempC=22.0 humidity=23.0 tries=1

Here’s the full source code:

#include "Particle.h"

#include "tracker_config.h"
#include "tracker.h"

#include "DHT22Gen3_RK.h"
#include "TemperatureHumidityValidatorRK.h"



SerialLogHandler logHandler(115200, LOG_LEVEL_TRACE, {
    { "app.gps.nmea", LOG_LEVEL_INFO },
    { "app.gps.ubx",  LOG_LEVEL_INFO },
    { "ncp.at", LOG_LEVEL_INFO },
    { "net.ppp.client", LOG_LEVEL_INFO },

// The two parameters are any available GPIO pins. They will be used as output but the signals aren't
// particularly important for DHT11 and DHT22 sensors. They do need to be valid pins, however.
DHT22Gen3 dht(A4, A5);

// Library: TemperatureHumidityValidatorRK
TemperatureHumidityValidator validator;

// Sample the temperature sensor every 2 seconds. This is done so the outlier values can be filtered out easily.
const unsigned long CHECK_PERIOD_MS = 2000;
unsigned long lastCheck = 0;

void locationGenerationCallback(JSONWriter &writer, LocationPoint &point, const void *context); // Forward declaration

void setup()
    // Callback to add key press information to the location publish

    // Initialize temperature sensor


void loop()

    if (millis() - lastCheck >= CHECK_PERIOD_MS) {
        lastCheck = millis();

        dht.getSample(A1, [](DHTSample sample) {
            if (sample.isSuccess()) {
                Log.info("sampleResult=%d tempF=%.1f tempC=%.1f humidity=%.1f tries=%d",
                        (int) sample.getSampleResult(), sample.getTempF(), sample.getTempC(), sample.getHumidity(), sample.getTries() );
                // Log.info("dewPointF=%.1f dewPointC=%.1f",
                //        sample.getDewPointF(), sample.getDewPointC() );
                validator.addSample(sample.getTempC(), sample.getHumidity());
        else {
                Log.info("sample is not valid sampleResult=%d", (int) sample.getSampleResult());
        }, &DHT22Gen3::sensorTypeDHT11);

        // Log.info("tempC=%f tempF=%f humidity=%f", validator.getTemperatureC(), validator.getTemperatureF(), validator.getHumidity());

void locationGenerationCallback(JSONWriter &writer, LocationPoint &point, const void *context)
    float tempC = validator.getTemperatureC();
    if (!isnan(tempC)) {
        writer.name("temp").value(tempC, 2);

    float hum = validator.getHumidity();
    if (!isnan(hum)) {
        writer.name("hum").value(hum, 1);


1 Like

Two pins? I thought this was some kind of a one wire protocol?

The DHT11 protocol is one wire. The two extra pins are literally extra pins because the I2S peripheral requires them. That’s the downside of using the DHT22Gen3_RK library.

You can still use the Grove_Temperature_And_Humidity_Sensor library, just expect that a bunch of the results will be nan. That’s why the original example polls every 2 seconds and aggregates the results, so it doesn’t matter that a lot of samples fail to acquire.

1 Like

It seems to work.
There might have been an error made in DHT22Gen3_RK.cpp line 82 (bytes[5] = {0};). Suggesting memset(bytes, 0, 5);
Also the negative temperature shows without a sign, we iced the sensor, it showed 20 centigrade minimum, started gradually going to 0, and then back to 25.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.