SHT11 humidity sensor library (sensirion manufacture)

March 25, 20131 comment Coded in C

Platform independent library for SHT11 humidity sensor. To avoid long blocking piece of code, main function is written as a state machine. To read all desired data from the sensor, appropriate function must be called in the loop. Sample usage is at the end of the snippet.

To adapt code for different architecture, sht_low_level_drv.h should be defined by user. User must also provide sys_timer_ticks variable, which is incremented each 1ms.

/*********** begin of library header file sht11.h ***************/

#ifndef _SHTXX_H
#define _SHTXX_H

#include <inttypes.h>

#define HUMIDITY_BYTE    0x05
#define TEMPERATURE_BYTE 0x03

//State machine states

#define SHT_DATA_WAIT_INITIAL_STATE     0
#define SHT_DATA_WAIT_TIMEOUT_STATE     1

#define SHT_PROC_RESET_COND_STATE       0   
#define SHT_PROC_START_COND_STATE       1
#define SHT_PROC_SEND_STATE             2
#define SHT_PROC_WAIT_STATE             3
#define SHT_PROC_RETURN_STATE           4

#define SHT_RH_READ_TEMPERATURE_STATE   0
#define SHT_RH_READ_HUMIDITY_STATE      1
#define SHT_RH_CONVERT_RH_STATE         2

#include <sht_low_level_drv.h>

void shtxx_init(void);

int shtxx_proc(uint8_t sht_param,uint16_t *ret_value);

int shtxx_get_temp(uint16_t *ret_temperature);
int shtxx_get_temp_RH( int16_t *ret_temperature, int16_t *ret_humidity );

#endif /* _SHTXX_H */

/*********** begin of library source file sht11.c ***************/
#include "sht11.h"

void shtxx_init( void )
{
    shtxx_set_db();
    shtxx_set_cb();
}

void shtxx_wait( void ) //SHT_WAIT should be tuned acording to MCU clock
{
    volatile int wait_cnt;
    for ( wait_cnt = 0; wait_cnt < SHT_WAIT;wait_cnt )
    {
        wait_cnt++;
    }
}

void shtxx_reset_condition( void )
{
    uint8_t i;
    shtxx_set_db();
    shtxx_set_out_data_dir();
    for ( i = 0;i < 12;i++ )
    {
        if ( i % 2 == 0 )
            shtxx_set_cb();
        else
            shtxx_clr_cb();
        shtxx_wait();
    }
}

void shtxx_start_condition( void )
{
    shtxx_set_db();
    shtxx_set_out_data_dir();
    shtxx_wait();
    shtxx_set_cb();
    shtxx_wait();
    shtxx_clr_db();
    shtxx_wait();
    shtxx_clr_cb();
    shtxx_wait();
    shtxx_wait();
    shtxx_set_cb();
    shtxx_wait();
    shtxx_set_db();
    shtxx_wait();
    shtxx_clr_cb();
    shtxx_wait();

}

int shtxx_send_byte( uint8_t sht_data2send )
{
    uint8_t i = 0;
    while ( i <= 7 )
    {
        if ( ( ( sht_data2send << i++ ) & 0x80 ) == 0x80 )
            shtxx_set_db();
        else
            shtxx_clr_db();
        shtxx_set_out_data_dir();
        shtxx_wait();
        shtxx_set_cb();
        shtxx_wait();
        shtxx_clr_cb();

    }
    shtxx_set_in_data_dir();
    shtxx_wait();
    shtxx_set_cb();
    shtxx_wait();
    if ( shtxx_get_db() == 0 )
        return 1;

    else
        return -1;
}

int shtxx_data_wait( sht_ticks_t sht_timeout )
{
    static uint8_t sht_wait_state;
    static sht_ticks_t sht_previous_ticks;

    switch ( sht_wait_state )
    {
    case SHT_DATA_WAIT_INITIAL_STATE:
        sht_previous_ticks = sht_msec_ticks;
        sht_wait_state = SHT_DATA_WAIT_TIMEOUT_STATE;
        shtxx_set_in_data_dir();
        shtxx_clr_cb();

    case SHT_DATA_WAIT_TIMEOUT_STATE:
        if ( shtxx_get_db() == 0 )
        {
            sht_wait_state = SHT_DATA_WAIT_INITIAL_STATE;
            return 1;
        }
        else
        {
            if ( ( sht_msec_ticks - sht_previous_ticks ) > sht_timeout )
            {
                sht_wait_state = SHT_DATA_WAIT_INITIAL_STATE;
                return -1;
            }
            else
                return 0;
        }
    }
}

uint8_t sht_read_byte( uint8_t sht_ack )
{
    shtxx_set_in_data_dir();
    uint8_t temp_rx_buff = 0;
    int8_t i = 7;
    while ( i >= 0 )
    {
        shtxx_wait();
        shtxx_set_cb();
        temp_rx_buff |= ( ( shtxx_get_db() & 0x01 ) << i );
        i--;
        shtxx_wait();
        shtxx_clr_cb();

    }

    if ( sht_ack == 1 )
    {
        shtxx_clr_db();
        shtxx_set_out_data_dir();
        shtxx_wait();
        shtxx_set_cb();
        shtxx_wait();
        shtxx_clr_cb();
        shtxx_set_in_data_dir();

    }
    return temp_rx_buff;
}

int shtxx_proc( uint8_t sht_param, uint16_t *ret_value )
{

    static uint8_t sht_proc_state = 0;
    int8_t	wait_status;

    switch ( sht_proc_state )
    {
    case SHT_PROC_RESET_COND_STATE:
        shtxx_reset_condition();
    case SHT_PROC_START_COND_STATE:
        shtxx_start_condition();
    case SHT_PROC_SEND_STATE:
        shtxx_send_byte( sht_param );
    case SHT_PROC_WAIT_STATE:
        wait_status = shtxx_data_wait( 300 );
        if ( wait_status == -1 )
        {
            sht_proc_state = SHT_PROC_RESET_COND_STATE;
            return -1;

        }
        if ( wait_status == 0 )
        {
            sht_proc_state = SHT_PROC_WAIT_STATE;
            return 0;
        }
        else
            sht_proc_state = SHT_PROC_RETURN_STATE;
    case SHT_PROC_RETURN_STATE:
        *ret_value = ( ( uint16_t ) sht_read_byte( 1 ) << 8 );
        shtxx_wait();
        *ret_value += sht_read_byte( 0 );
        sht_proc_state = SHT_PROC_START_COND_STATE;
        return 1;

    }
}

int shtxx_get_temp( uint16_t *ret_temperature )
{
    static uint16_t tmp_temp;
    if ( shtxx_proc( TEMPERATURE_BYTE, &tmp_temp ) == 1 )
    {
        *ret_temperature = tmp_temp - 3965;
        return 1;
    }
    else
        return 0;
}

int shtxx_get_temp_RH( int16_t *ret_temperature, int16_t *ret_humidity )
{

    static uint8_t sht_humidity_state;
    static uint16_t sht_humidity_raw;
    static uint16_t sht_temp_C;

    static float RH_linear;
    static float RH_compensated;

    switch ( sht_humidity_state )
    {
    case SHT_RH_READ_TEMPERATURE_STATE:
        if ( shtxx_get_temp( &sht_temp_C ) )
            sht_humidity_state = SHT_RH_READ_HUMIDITY_STATE;
        break;
    case SHT_RH_READ_HUMIDITY_STATE:
        if ( shtxx_proc( HUMIDITY_BYTE, &sht_humidity_raw ) )
            sht_humidity_state = SHT_RH_CONVERT_RH_STATE;
        break;
    case SHT_RH_CONVERT_RH_STATE:
        RH_linear = ( float ) ( ( 0.0405 * ( float ) sht_humidity_raw ) - ( 0.0000028 * ( float ) sht_humidity_raw * ( float ) sht_humidity_raw ) - 4 );
        RH_compensated = ( float ) ( ( ( ( ( ( float ) sht_temp_C ) / 100 ) - 25 ) * ( 0.01 + ( 0.00008 * ( float ) sht_humidity_raw ) ) ) + RH_linear );
        sht_humidity_state = SHT_RH_READ_TEMPERATURE_STATE;
        *ret_temperature = sht_temp_C;
        *ret_humidity = ( ( int16_t ) ( RH_compensated * 100 ) );
        return 1;
    default:
        sht_humidity_state = SHT_RH_READ_TEMPERATURE_STATE;
    }
	return 0;
}

/*** sample low-level functions (platform dependent) sht_low_level_drv.h ***/

#ifndef _SHT_LOW_LEVEL_DRV_H
#define _SHT_LOW_LEVEL_DRV_H

#include <types.h>
#include <system_def.h> /* for concrete HW,  SHT_PORT, SHT_DATA_BIT must be defined*/

#define SHT_MAX_CLK		100000
#define SHT_WAIT		(CCLK/SHT_MAX_CLK) /* CCLK is MCU clock */
#define sht_ticks_t		uint32_t
#define sht_msec_ticks		sys_timer_ticks /* this variable should be defined in BSP and incremented each ms (usually in some timer interrupt routine) */

static inline void shtxx_set_db(void)
{
	
	SET_OUT_PIN(SHT_PORT,SHT_DATA_BIT);
}

static inline void shtxx_clr_db(void)
{
	CLR_OUT_PIN(SHT_PORT,SHT_DATA_BIT);
}

static inline void shtxx_set_cb(void)
{
	SET_OUT_PIN(SHT_PORT,SHT_CLK_BIT);
}

static inline void shtxx_clr_cb(void)
{
	CLR_OUT_PIN(SHT_PORT,SHT_CLK_BIT);
}

static inline uint8_t shtxx_get_db(void)
{
	return(	GET_IN_PIN(SHT_PORT,SHT_DATA_BIT) );	
}

static inline void shtxx_set_in_data_dir(void)
{
	IO0DIR &=~(SHT_DATA_BIT);
}

static inline void shtxx_set_out_data_dir(void)
{
	IO0DIR |= SHT_DATA_BIT ;
}

#endif /* _SHT_LOW_LEVEL_DRV_H */

/********************* sample usage in main program ************************/

//..............
int16_t temperature, humidity;

while(1) //main loop of the user program
{
    if (shtxx_get_temp_RH( &temperature, &humidity )
    {
        //do something
    }
    //do other operations
    //.....................      
}