This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

DHT22 sensor data pin reading low

Hi Team Nordic,

According to the AM2302 (DHT22) datasheet, the data pin will be pulled to high state in idle state. But in my case, when i am reading the data pin before even sending any signal to the sensor, i am reading 0 on the data pin. I am using p0.07 (pin 9 ) as data pin. VCC -> 5V, GND -> GND.

Am i not reading the pin correctly or is it a communication protocol error that i have to figure out?

Please find attached the image with output. 

Thanks, 

Parents
  • I am using p0.07 (pin 9 ) as data pin. VCC -> 5V, GND -> GND.

    Trying to describe circuit connections in words is a waste of time. Please post a schematic (aka "circuit diagram").

    You haven't said what Nordic part you're using, but the Absolute Maximum voltage at any IO pin on the nRF52832 is 3.9V - I expect others are similar ...

  • I answered this earlier but it seems it got lost .. the DHT22 requires a pull-up to nRF Vdd (note not 5 volt) on the Data line, as do all 1-wire devices. The nominal value is 1k, but you can try simply changing _NOPULL to _PULLUP to see if that works at low data rates. You might also use high Drive for '0' and '1' when in output mode if the is any significant parasitic capacitance or long leads to the DHT22.

  • the DHT22 requires a pull-up

    That's kind of hinted-at in the datasheet, but there is no clear specification at all of the output characteristics: https://cdn-shop.adafruit.com/datasheets/DHT22.pdf 

    Sadly, that is typical of these cheap chinese components.

    However, these are widely used in the "maker" community - so there's no shortage of tutorials and examples on using them.

    My first hit on googling "DHT22" is https://www.adafruit.com/product/385 - which says,

    "Comes with a 4.7K - 10K resistor, which you will want to use as a pullup from the data pin to VCC"

    Which is another clue!

  • Yes that's true. The sensor is indeed very popular and I am sure I will find out soon what is going wrong with it and will post the answer here .

     Thanks 

  • Well, if it needs a pull-up and you haven't provided one, then it obviously won't work!

    In that case, would expect to always read zero from it!

  • Hi,

    Now this is strange.

    I am reading 2.94V voltage on oscilloscope from my data pin of sensor but my program is still reading 0.

    Am i  missing something in my code?

    #include "sdk_common.h"
    #include "dht22.h"
    #include <string.h>
    #include "nrf_gpio.h"
    #include "boards.h"
    #include "nrf_log.h"
    
    
    void read_dht11_dat()
     { 
    	uint8_t laststate	= 1;
    	uint8_t counter		= 0;
    	uint8_t j		= 0, i;
    	float	f; /* fahrenheit */
     
    	
             nrf_gpio_cfg_input(DHTPIN,  NRF_GPIO_PIN_PULLUP) ;
             laststate = nrf_gpio_pin_read( DHTPIN );
             printf( "%d \n" ,laststate );
            
            
            
            dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0;
            
               nrf_gpio_cfg_output(DHTPIN);
               nrf_gpio_pin_write(DHTPIN, 0);
               nrf_delay_ms(10);
    
            
    
             nrf_gpio_pin_write(DHTPIN, 1);
             nrf_delay_us(40);
    
             nrf_gpio_cfg_input(DHTPIN,  NRF_GPIO_PIN_PULLUP );
    
             for ( i = 0; i < MAXTIMINGS; i++ )
    	{
    		counter = 0;
    		while ( nrf_gpio_pin_read(DHTPIN) == laststate)
    		{
    			counter++;
    			nrf_delay_us(1);
    			if ( counter == 255 )
    			{
    				break;
    			}
    		}
    		laststate = nrf_gpio_pin_read( DHTPIN );
     
    		if ( counter == 255 )
    			break;
     
    		/* ignore first 3 transitions */
    		if ( (i >= 4) && (i % 2 == 0) )
    		{
    			/* shove each bit into the storage bytes */
    			dht11_dat[j / 8] <<= 1;
    			if ( counter > 16 )
    				dht11_dat[j / 8] |= 1;
    			j++;
    		}
    	}
    
            if ( (j >= 40) &&
    	     (dht11_dat[4] == ( (dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF) ) )
    	{
    		f = dht11_dat[2] * 9. / 5. + 32;
    		printf( "Humidity = %d.%d %% Temperature = %d.%d *C (%.1f *F)\n",
    			dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3], f );
    	}else  {
    		printf( "Data not good, skip\n" );
    	}
        
        }
      

Reply
  • Hi,

    Now this is strange.

    I am reading 2.94V voltage on oscilloscope from my data pin of sensor but my program is still reading 0.

    Am i  missing something in my code?

    #include "sdk_common.h"
    #include "dht22.h"
    #include <string.h>
    #include "nrf_gpio.h"
    #include "boards.h"
    #include "nrf_log.h"
    
    
    void read_dht11_dat()
     { 
    	uint8_t laststate	= 1;
    	uint8_t counter		= 0;
    	uint8_t j		= 0, i;
    	float	f; /* fahrenheit */
     
    	
             nrf_gpio_cfg_input(DHTPIN,  NRF_GPIO_PIN_PULLUP) ;
             laststate = nrf_gpio_pin_read( DHTPIN );
             printf( "%d \n" ,laststate );
            
            
            
            dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0;
            
               nrf_gpio_cfg_output(DHTPIN);
               nrf_gpio_pin_write(DHTPIN, 0);
               nrf_delay_ms(10);
    
            
    
             nrf_gpio_pin_write(DHTPIN, 1);
             nrf_delay_us(40);
    
             nrf_gpio_cfg_input(DHTPIN,  NRF_GPIO_PIN_PULLUP );
    
             for ( i = 0; i < MAXTIMINGS; i++ )
    	{
    		counter = 0;
    		while ( nrf_gpio_pin_read(DHTPIN) == laststate)
    		{
    			counter++;
    			nrf_delay_us(1);
    			if ( counter == 255 )
    			{
    				break;
    			}
    		}
    		laststate = nrf_gpio_pin_read( DHTPIN );
     
    		if ( counter == 255 )
    			break;
     
    		/* ignore first 3 transitions */
    		if ( (i >= 4) && (i % 2 == 0) )
    		{
    			/* shove each bit into the storage bytes */
    			dht11_dat[j / 8] <<= 1;
    			if ( counter > 16 )
    				dht11_dat[j / 8] |= 1;
    			j++;
    		}
    	}
    
            if ( (j >= 40) &&
    	     (dht11_dat[4] == ( (dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF) ) )
    	{
    		f = dht11_dat[2] * 9. / 5. + 32;
    		printf( "Humidity = %d.%d %% Temperature = %d.%d *C (%.1f *F)\n",
    			dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3], f );
    	}else  {
    		printf( "Data not good, skip\n" );
    	}
        
        }
      

Children
  • Hi,

    I have no experience with the DHT22, but I see your code is similar to this example. Your code is missing some of the comments, but referring to the code I linked to it seems that what this is what is supposed to happen:

    1. Configure pin as output.
    2. Pull pin down for some time (I have not read the DHT22 datasheet, but I assume this should tell it to send data).
    3. Configure pin as input
    4. Loop for reading each input bit
      1. Read pin continuously to detect a transition (change in state)
      2. Ignore first 3 transitions (I guess this is for synchronization as there is no clock, but I have not checked 1-wire spec)
      3. shift received bit into correct position in RX buffer
    5. Check that the correct number of bits is received, and that the checksum is correct

    Have you verified the timing of your implementation? Is duration of your waits sensible? I suggest you add a bit of logging along the way printing the data you read so that you can see what happens and that it matches what you would expect. You could also verify that the incoming signal is correct by using a logic analyzer that support the 1-Wire protocol (for instance Saleae Logic Pro).

Related