Jump to content
arre

DHT11 temperature & humidity sensor code snippet

Recommended Posts

Hi, 

 

Thought I'd share a small code snippit I built to interface succesfully with the DHT11 temp & humidity sensor (4 bucks on ebay):

#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/systick.h"
#include "driverlib/timer.h"


int temp;
int humidity;


inline long WaitUntilPinState(int clockMhz, long pinbase, long pin, long timerbase, long timer, int previousstate, int usec)
{
// Debounce really not needed unless you have huge noise, but just in case (the processor is fast enough)
#define DEBOUNCEMATCHES 5
	long timermax;
	long timerval;
	int matches = 0;
	TimerDisable(timerbase, timer);
	TimerConfigure(timerbase, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_ONE_SHOT);
	TimerLoadSet(timerbase, timer, usec*clockMhz);
	timermax = TimerValueGet(timerbase, timer);
	timerval = timermax;
	TimerEnable(timerbase, timer);

	while(matches < DEBOUNCEMATCHES){ /* Wait for DHT to pull down */
		if( GPIOPinRead(pinbase, pin) > 0 != previousstate > 0) {
			matches++;
		} else {
			matches = 0;
		}
		timerval = TimerValueGet(timerbase, timer);
		if(!timerval) timerval = 1; /* make sure we never return 0 by mistake */
		if (timerval==timermax){
			return 0;
		}
	}
	return timerval;
}



int ReadDHT()
{
	// bit buffers & timeout
	char bitcount;
	char byte;
	char bits[5] = {0,0,0,0,0};
	unsigned int bitints[6];
	long timerval;
	int clockMhz;

#define MY_PIN_PERIPH		SYSCTL_PERIPH_GPIOE
#define MY_PIN_PORTBASE		GPIO_PORTE_BASE
#define MY_PINNR			GPIO_PIN_1
#define MY_TIMER_PERIPH		SYSCTL_PERIPH_TIMER0
#define MY_TIMERBASE		TIMER0_BASE
#define MY_TIMER			TIMER_B

	clockMhz = SysCtlClockGet() / 1000000;

	/* Configure hardware counter to check how long we are looping */
	SysCtlPeripheralEnable(MY_TIMER_PERIPH);
	TimerConfigure(MY_TIMERBASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_ONE_SHOT);


	// request reading
	SysCtlPeripheralEnable(MY_PIN_PERIPH);

	GPIOPinTypeGPIOOutput(MY_PIN_PORTBASE, MY_PINNR);
	GPIOPinWrite(MY_PIN_PORTBASE, MY_PINNR, 0x0);

	// #loops = loops_per_us*time_in_us = time in us * loops/us = time_in_us *(clockfreq/10000000)
	SysCtlDelay(30000*clockMhz); // -> 30 ms
	/////// SET PIN HIGH (putting it to input will do)
	GPIOPinTypeGPIOInput(MY_PIN_PORTBASE, MY_PINNR);

	SysCtlDelay(10*clockMhz);

	/* Wait for DHT pull down */
	if(!WaitUntilPinState(clockMhz,MY_PIN_PORTBASE,MY_PINNR,MY_TIMERBASE,MY_TIMER,1,50)) return 0;

	/* Wait for dummy up */
	if(!WaitUntilPinState(clockMhz,MY_PIN_PORTBASE,MY_PINNR,MY_TIMERBASE,MY_TIMER,0,90)) return 0;

	/* Wait for dummy down */
	if(!WaitUntilPinState(clockMhz,MY_PIN_PORTBASE,MY_PINNR,MY_TIMERBASE,MY_TIMER,1,90)) return 0;

	// start receiving 40 bits
	char i;
	bitcount = 7;
	byte = 0;
	for (i=0; i < 40; i++)
	{
		/* Wait for pull up */
		if(!WaitUntilPinState(clockMhz,MY_PIN_PORTBASE,MY_PINNR,MY_TIMERBASE,MY_TIMER,0,60)) return 0;

		/* Wait for pull down and count */
		timerval = WaitUntilPinState(clockMhz,MY_PIN_PORTBASE,MY_PINNR,MY_TIMERBASE,MY_TIMER,1,90);

		if(!timerval) return 0;

		if (timerval < 40*clockMhz) bits[byte] |= (1 << bitcount);
		if (bitcount == 0)
		{
			bitcount = 7;
			byte++;
		}else{
			bitcount--;
		}
	}

	// checksum

	/* Little Endian */
	bitints[0] = ((unsigned int) bits[0]  & (0x000000FF));
	bitints[1] = ((unsigned int) bits[1]  & (0x000000FF));
	bitints[2] = ((unsigned int) bits[2]  & (0x000000FF));
	bitints[3] = ((unsigned int) bits[3]  & (0x000000FF));
	bitints[4] = ((unsigned int) bits[4]  & (0x000000FF));
	if(((bitints[0] + bitints[1] + bitints[2] + bitints[3]) & (0x000000FF)) == bitints[4]){
		temp = bitints[2];
		humidity =  bitints[0];
		return 1;
	}else{
		return 0;
	}

}



int main(void)
{

	SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);	//Configure the system clock to 40MHz

	if(ReadDHT() == 0)
	{
		//Failed result
	} else {
		// Stored in temp and humidity
	}
}

Share this post


Link to post
Share on other sites

I´am using TM4C1294XL and I wasn't able to communicate, so I  changed your code a little bit and is working, its not very polished but works.... So here is the code to EK launchpad.

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "drivers/pinout.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/timer.h"
#include "utils/uartstdio.h"



int temp;
int humidity;

uint32_t g_ui32SysClock;

#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

void
ConfigureUART(void)
{
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    UARTStdioConfig(0, 115200, g_ui32SysClock);
}





int ReadDHT()
{
    // bit buffers & timeout
    char bitcount;
    char byte;
    char bits[5] = {0,0,0,0,0};
    unsigned int bitints[6];
    long timerval;
    int clockMhz;

    unsigned int loopCnt = 10000;

    #define MY_PIN_PERIPH       SYSCTL_PERIPH_GPIOM
    #define MY_PIN_PORTBASE     GPIO_PORTM_BASE
    #define MY_PINNR            GPIO_PIN_6

    #define MY_TIMER_PERIPH     SYSCTL_PERIPH_TIMER0
    #define MY_TIMERBASE        TIMER0_BASE
    #define MY_TIMER            TIMER_B

    SysCtlPeripheralEnable(MY_TIMER_PERIPH);
    TimerConfigure(MY_TIMERBASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_ONE_SHOT);


    SysCtlPeripheralEnable(MY_PIN_PERIPH);

    ROM_GPIOPinTypeGPIOOutput(MY_PIN_PORTBASE, MY_PINNR);


    GPIOPinWrite(MY_PIN_PORTBASE, MY_PINNR, 0x0);

    // #loops = loops_per_us*time_in_us = time in us * loops/us = time_in_us *(clockfreq/10000000)
    SysCtlDelay((g_ui32SysClock/3)/30 ); // -> 30 ms

    ROM_GPIOPinTypeGPIOInput(MY_PIN_PORTBASE, MY_PINNR);


    loopCnt = g_ui32SysClock/100;
    while(GPIOPinRead(MY_PIN_PORTBASE, MY_PINNR))
    {
        loopCnt = loopCnt -1;
        if (loopCnt == 0)
            return 0;
    }


    loopCnt = g_ui32SysClock/100;
    while(!(GPIOPinRead(MY_PIN_PORTBASE, MY_PINNR)))  //0
    {
        loopCnt = loopCnt -1;
        if (loopCnt == 0)
            return 0;
    }

    loopCnt = g_ui32SysClock/100;
    while(GPIOPinRead(MY_PIN_PORTBASE, MY_PINNR))
    {
        loopCnt = loopCnt -1;
        if (loopCnt == 0)
            return 0;
    }

    // start receiving 40 bits
    char i;
    bitcount = 7;
    byte = 0;

    int conta = 0;
    int timerval2=0;

    int largest = 0;
    int lowest  = 99999;

    for (i=0; i < 40; i++)
    {
                loopCnt = g_ui32SysClock/100;
        while(!(GPIOPinRead(MY_PIN_PORTBASE, MY_PINNR)))
        {
            loopCnt = loopCnt -1;
            if (loopCnt == 0)
                return 0;
        }

        
        TimerDisable(MY_TIMERBASE, MY_TIMER);
        TimerConfigure(MY_TIMERBASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_ONE_SHOT);
        TimerLoadSet(MY_TIMERBASE, MY_TIMER, g_ui32SysClock/4000);
        TimerEnable(MY_TIMERBASE, MY_TIMER);
        timerval = TimerValueGet(MY_TIMERBASE, MY_TIMER);

        loopCnt = g_ui32SysClock/100;
        while(GPIOPinRead(MY_PIN_PORTBASE, MY_PINNR))
        {
            loopCnt = loopCnt -1;
            if (loopCnt == 0)
                return 0;
        }

        timerval2 = TimerValueGet(MY_TIMERBASE, MY_TIMER);


        conta =  timerval - timerval2;

        if (conta>largest)
            largest = conta;

        if (conta<lowest)
            lowest = conta;

        if ((conta) > (1000))
               bits[byte] |= (1 << bitcount);
        if (bitcount == 0)
        {
            bitcount = 7;
            byte++;
        }else{
            bitcount--;
        }
    }

    bitints[0] = ((unsigned int) bits[0]  & (0x000000FF));
    bitints[1] = ((unsigned int) bits[1]  & (0x000000FF));
    bitints[2] = ((unsigned int) bits[2]  & (0x000000FF));
    bitints[3] = ((unsigned int) bits[3]  & (0x000000FF));
    bitints[4] = ((unsigned int) bits[4]  & (0x000000FF));
    
    if(((bitints[0] + bitints[1] + bitints[2] + bitints[3]) & (0x000000FF)) == bitints[4]){
        temp = bitints[2];
        humidity =  bitints[0];
        return 1;
    }else{
        return 0;
    }

}


int
main(void)
{
    g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
                SYSCTL_CFG_VCO_480), 40000000);

    PinoutSet(false, false);

    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1);

    ConfigureUART();

    UARTprintf("Its runing at : %d\n",g_ui32SysClock);


    while(1)
    {
        //
        // Turn on D1. LED 1
        //
        LEDWrite(CLP_D1, 1);

        SysCtlDelay(g_ui32SysClock  / 3); //%1s Delay its required because if the sensor is ready to fast the comunication goes down.

        LEDWrite(CLP_D1, 0);

        SysCtlDelay(g_ui32SysClock  / 3);

        if(ReadDHT() == 0)
            {
             UARTprintf("Erro!\n");
            }
        else
        {
            UARTprintf("Temp %d !\n",temp);
            UARTprintf("Hum %d !\n",humidity);

        }

    }
}

Share this post


Link to post
Share on other sites

arre, can you explain

 

if(timerval<40*clockMhz) bit[byte]|=(1<<bitcount);

 

I think it has to be if(timerval>40*clockMhz) as this will decide data"1" that takes long time. Also, how can you relate the 40*clockMhz to the 28usec time interval to decide data"0" or the 70usec time interval to decide data "1".  clockMhz=40 in the code so this value will be 40*40=1600 that is too large for the time values in the data sheet of the sensor !

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×