← index #611Issue #3562
Off-topic · high · value 0.417
QUERY · ISSUE

Problem with dht library

openby gandipgopened 2023-02-12updated 2023-03-03

Hello
Problem with dht library not working properly in subzero temperatures with dht22 module.
reports (-3264.4°C)
it is written here about a domestic problem https://forums.raspberrypi.com/viewtopic.php?t=296097

2 comments
Keelando · 2023-02-28

Indeed! I'm not well-versed enough to suggest a proper solution at this time but I've just been adding the offset value corresponding to -0.1C and then multiplying by -1

dpgeorge · 2023-03-03

I tested the dht driver with a DHT22 and it works OK for me at temperatures less than 0 Celsius.

The dht driver here assumes that the top bit of the returned temperature value is a sign bit. But if you are getting values like -3264.4 then it could be that your DHT22 returns a 2's complement signed value.

After you do a reading can you print out the buffer, like this:

dht.measure()
print(dht.temperature(), dht.buf)

That will help narrow down the problem.

If it is 2's complement then you have a non-standard DHT22 module and you'll need to use conversion like this:

def dht_temp(dht):
    value = dht.buf[2] << 8 | dht.buf[3]
    if value & 0x8000:
        value -= 0x10000
    return value * 0.1
CANDIDATE · ISSUE

STM32F407DiscBoard : Interfacing DHT22 sensor

closedby nikhil1983opened 2018-01-12updated 2018-01-31

Hello,
So i am currently stuck on interfacing DHT22 sensor (without I2C) to stm disc board using micropython. I have source file written in C++ for interfacing DHT22 with stm board, and it works fine. It gives correct O/P on terminal.

Using that C module as reference, I have made my python code for displaying sensor output on LCD using async method. But whenever i run the code, "DHT22 Not Responding " is getting printted on LCD. I don't know why my MCU is unable to read the data from sensor. I guess their is timing issues, but i cant see it.

Note: Sensor is given supply voltage of 5 V and its working properly.

I have tried to referred DHT22 drivers for esp28...,but it didn't helped either. If anyone have knowledge about this, please kindly help me out.

Please have a look at my stm32f4_dht22.c and Python code ( .c file is just for reference)

Source file written in C

Source file :
/****************************************************************//

  • @file stm32f4_dht22.c

/* Includes ------------------------------------------------------------------- */
#include "stm32f4_dht22.h"

/**

  • @brief Initialize Pin For DHT22
  • @param mode Pin mode output or input
  •    @arg GPIO_MODE_INPUT
    
  •    @arg GPIO_MODE_OUTPUT_PP
    

*/
void DHT22_PinConfig(uint8_t mode)
{
GPIO_InitTypeDef GPIO_InitStruct;

/* Enable the GPIOC Clock */

__GPIOC_CLK_ENABLE();

/* Configure the GPIO_ALED pin */
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = mode;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;

HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
/**

  • @brief Initialize Pin for DHT22
  • @return none
    */
    void DHT22_Init(void)
    {
    DHT22_PinConfig(GPIO_MODE_INPUT);
    }

/**

  • @brief Read DHT22 data and display it on UART4
    */
    void DHT22_read(void)
    {
    uint16_t lastHumidity1;
    uint16_t lastHumidity2;
    uint16_t lastTemperature1;
    uint16_t lastTemperature2;
    uint8_t i, j, retryCount;
    uint16_t currentTemperature=0;
    uint16_t currentHumidity=0;
    uint32_t checkSum = 0, csPart1, csPart2, csPart3, csPart4;
    uint32_t bitTimes[41];

    for (i = 0; i < 41; i++)
    {
    bitTimes[i] = 0;
    }

    retryCount = 0;
    // Pin needs to start HIGH, wait unit it is HIGH with a timeout
    while(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_6) == 0)// exit on DHT22 return 'High' Signal within 250us
    {
    if (retryCount > 125)
    {
    uprintf(&huart4,"DHT22 Bus busy!\r\n");
    }
    retryCount ++;
    Delay_Us(2);
    }
    /**

    • Send the activate pulse
    • Step 1: MCU send out start signal to DHT22 and DHT22 send
    • response signal to MCU.
    • If signal is high-voltage-level, it means DHT22 is not
    • working properly, please check the electrical connection status.
      */
      DHT22_PinConfig(GPIO_MODE_OUTPUT_PP); // set pin to output data

    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET); // MCU send out start signal to DHT22
    HAL_Delay(18); // 18 ms wait (spec: at least 1ms)
    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_SET); // MCU pull up
    Delay_Us(40);
    DHT22_PinConfig(GPIO_MODE_INPUT); // set pin to receive data

    // Find the start of the ACK Pulse
    retryCount = 0;
    while(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_6) == 1) // Exit on DHT22 pull low within 40us
    {
    if (retryCount > 40) // (Spec is 20-40 us high)
    {
    uprintf(&huart4,"DHT22 not responding!\r\n");
    }
    retryCount++;
    Delay_Us(1);
    }

    Delay_Us(80); // DHT pull up ready to transmit data

/**

  • Reading the 5 byte data stream
  • Step 2: DHT22 send data to MCU
  • Start bit -> low volage within 50us (actually could be anything from 35-75us)
  •         0         -> high volage within 26-28us (actually could be 10-40us)
    
  •         1         -> high volage within 70us (actually could be 60-85us)
    

/
for (i = 0; i < 5; i++)
{
for (j = 0; j < 8; j++)
{
retryCount = 0;
while(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_6) == 0)
{
if (retryCount > 75)
{
uprintf(&huart4,"DHT22 timeout waiting for data!\r\n");
}
retryCount++;
Delay_Us(1);
}
// We now wait for 40us
Delay_Us(40);
if (HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_6) == 1)
{
// If pin is still high, bit value is a 1
bitTimes[i
8+j] = 1;
}
else
{
// The bit value is a 0
bitTimes[i*8+j] = 0;
}
uint8_t count = 0;
while (HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_6) == 1 && count < 100)
{
Delay_Us(1); // Delay for 1 microsecond
count++;
}
}
}

DHT22_PinConfig(GPIO_MODE_OUTPUT_PP);    // Re-init DHT22 pin
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_SET); //set value 1


// Now bitTimes have the actual bits
// that were needed to find the end of each data bit
// Note: the bits are offset by one from the data sheet, not sure why
currentHumidity    = 0;
currentTemperature = 0;
checkSum           = 0;
// First 16 bits is Humidity
for (i=0; i<16; i++)
{
    if (bitTimes[i+1] > 0)
    {
        currentHumidity |= ( 1 << (15-i));
    }
}

// Second 16 bits is Temperature
for (i=0; i<16; i ++)
{
    if (bitTimes[i+17] > 0)
    {
        currentTemperature |= (1 <<(15-i));
    }
}

// Last 8 bit is Checksum
for (i=0; i<8; i++)
{
    if (bitTimes[i+33] > 0)
    {
        checkSum |= (1 << (7-i));
    }
}

lastHumidity1 = currentHumidity/10;
lastHumidity2 = currentHumidity%10;

// if first bit of currentTemperature is 1, it is negative value.
if ((currentTemperature & 0x8000)==0x8000)
{
    lastTemperature1 = (currentTemperature & 0x7FFF / 10) * -1;
    lastTemperature2 = currentTemperature%10;
}
else
{
    lastTemperature1 = currentTemperature / 10.0;
    lastTemperature2 = currentTemperature%10;
}

// Calculate Check Sum
csPart1 = currentHumidity >> 8;
csPart2 = currentHumidity & 0xFF;
csPart3 = currentTemperature >> 8;
csPart4 = currentTemperature & 0xFF;
if (checkSum == ((csPart1 + csPart2 + csPart3 + csPart4) & 0xFF))
{
    uprintf(&huart4,"\x1b[4;1HTemperature: %d03.%d01 degC , Humidity:%d03.%d01 %%RH\r\n", lastTemperature1,lastTemperature2, lastHumidity1,lastHumidity2);
}

}

/* --------------------------------- End Of File ------------------------------ */

Now here is my same python code :

#Write a program to interface temp and humidity Sensor and display data on LCD
#Temperature & Humidity Driver File
import pyb
from pyb import Pin,LED
import utime as time
import uasyncio as asyncio
from alcd import LCD, PINLIST

lcd = LCD(PINLIST,cols=16)
sig = pyb.Pin('PC6',Pin.PULL_UP)
lastHumidity1 = lastHumidity2 = 0
lastTemperature1 = lastTemperature2 = 0
i = j = retryCount = count=0
currentTemperature = currentHumidity = checkSum = 0
csPart1 = csPart2 = csPart3 = csPart4 = 0
bitTimes = bytearray(41)

#Pin Configuration
def DHT22_PinConfig(mode): #Mode : Pin.IN, Pin.OUT or Pin.OUT_PP
sig = pyb.Pin('PC6',Pin.PULL_UP)
sig.init(mode)

#Sensor Initialisation
def DHT22_Init():
DHT22_PinConfig(Pin.IN) #Input mode

#Reading data
async def DHT22_read():

DHT22_Init()
global bitTimes
for x in range (41):
bitTimes[x] = 0

global retryCount

Pin needs to start HIGH, wait until it is HIGH with a timeout

while (sig.value() == False): #exit on DHT22 return 'High' Signal within 250us
if retryCount > 125 :
lcd[0] = "DHT22 Bus Busy!"
# lcd[1] = " "
await asyncio.sleep(1)
retryCount+=1
pyb.udelay(2)

#" Send the activate pulse

* Step 1: MCU send out start signal to DHT22 and DHT22 send

* response signal to MCU.

* If signal is high-voltage-level, it means DHT22 is not

* working properly, please check the electrical connection status. """

DHT22_PinConfig(Pin.OUT_PP) #Set pin to transmit data
sig.value(0) #MCU sends Start singnal on DHT22
pyb.delay(10) #18ms delay
sig.value(1) #MCU Pull Up

time.sleep_us(40) #40us delay

pyb.udelay(40)
DHT22_PinConfig(Pin.IN) #Set pin to recieve data

Find the start of the ACK Pulse

global retryCount
while (sig.value() == True): #Exit on DHT22 pull low within 40us
if (retryCount > 40):

led2.toggle()

  	lcd[0] = "DHT22 Not "
  	lcd[1] = "Responding"	
  	await asyncio.sleep(1)	
  retryCount+=1
  pyb.udelay(1)

pyb.udelay(80) #DHT pull up ready to transmit data

#* Reading the 5 byte data stream
#* Step 2: DHT22 send data to MCU

* Start bit -> low volage within 50us (actually could be anything from 35-75us)

* 0 -> high volage within 26-28us (actually could be 10-40us)

* 1 -> high volage within 70us (actually could be 60-85us)

for i in range(5):
for j in range(8):
global retryCount
while (sig.value() == False):
if retryCount > 75 :
lcd[0]= 'Dhtt Timeout'
retryCount+=1
pyb.udelay(1)

  	pyb.udelay(40)
  	if (sig.value() == True):
  		bitTimes[i*8+j] = 1
  	else:
  		bitTimes[i*8+j] = 0
  	
  	# lcd[0] ='bt{}'.format(bitTimes[i*8+j])
  	# await asyncio.sleep(1)
  	global count
  	while (sig.value()==True and count<100):
  		pyb.udelay(1)
  		count+=1

DHT22_PinConfig(Pin.OUT_PP) #Re-initalising DHT22 in O/P mode
sig.value(1)

#Now bitTimes have the actual bits that were needed to find the end of each data bit
currentHumidity = currentTemperature = checkSum = 0

while True:

  #First 16 bits is Humidity

for i in range (16):
if (bitTimes[i+1] > 0):
currentHumidity |= ( 1 << (15-i)) #30785

#Second 16 bits is Temperature
for i in range (16):
if (bitTimes[i+17] > 0):
currentTemperature |= ( 1 << (15-i))

#Last 8 bits is checksum
for i in range (8):
if (bitTimes[i+33] > 0):
checkSum |= (1 << (7-i))

lastHumidity1 = currentHumidity/10
lastHumidity2 = currentHumidity%10

#If first bit of currentTemperature is 1, it is negative value.
if ((currentTemperature and int(0x8000))== int(0x8000)):
lastTemperature1 = ((currentTemperature and int(0x7FFF)) / 10) * -1;
lastTemperature2 = currentTemperature % 10
else:
lastTemperature1 = currentTemperature / 10.0
lastTemperature2 = currentTemperature % 10

#Calculate Check Sum
csPart1 = currentHumidity >> 8
csPart2 = currentHumidity and int(0xFF)
csPart3 = currentTemperature >> 8
csPart4 = currentTemperature and int(0xFF)

if (checkSum == ((csPart1 + csPart2 + csPart3 + csPart4) and int(0xFF))):
lcd[0] = 'H1{}'.format(lastHumidity1)
lcd[1] = 'T1{}'.format(lastTemperature1)
await asyncio.sleep(1)
else:
lcd[0] = 'Checksum Error'
lcd[1] = ''
await asyncio.sleep(1)

while True:
loop = asyncio.get_event_loop()
loop.run_until_complete(DHT22_read())

Please Help.

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied