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

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...