Problem with dht library
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
STM32F407DiscBoard : Interfacing DHT22 sensor
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 dataHAL_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[i8+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, PINLISTlcd = 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] = 0global 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 Uptime.sleep_us(40) #40us delay
pyb.udelay(40)
DHT22_PinConfig(Pin.IN) #Set pin to recieve dataFind 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+=1DHT22_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 = 0while True:
#First 16 bits is Humidityfor 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.
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
I tested the
dhtdriver with a DHT22 and it works OK for me at temperatures less than 0 Celsius.The
dhtdriver 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:
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: