PLEASE NOTE: This article is obsolete or related to a discontinued product.

Interfacing the Sensirion humidity and temperature sensor

The Sensirion SHT71 is a fully calibrated, pluggable relative humidity and temperature sensors. This article shows how to interface it with to the FOX Board LX


Humidity and temperature sensor
Sensirion SHT71

Wiring


SHT71 wiring

Source code

Thanks to Douglas Gilbert here is a fixed and improved version of the source code in C language that reads the humidity and temperature measurements and show it on the console:

// Example of user space C program to read a humidity and temperature
// sensor Sensirion SHT71 (http://www.acmesystems.it/?id=89)

// Version improved by by Douglas Gilbert 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#ifdef __CRIS__
#include "linux/gpio_syscalls.h"
#endif

// -----------------------------------------------------------------------
// SHT71 sensor define
// -----------------------------------------------------------------------

#define CLOCK_BIT         25    // IO line on port G (was OG25)
#define DATA_BIT          24    // IO line on port G 

#define CLOCK_MSK         (1 << CLOCK_BIT)
#define DATA_MSK          (1 << DATA_BIT)

#ifdef __CRIS__
// Macro to set the data line direction
#define DATA_LINE_IN      gpiosetdir(PORTG,DIRIN,DATA_MSK)
#define DATA_LINE_OUT     gpiosetdir(PORTG,DIROUT,DATA_MSK)

#define DATA_LINE_LOW     gpiosetdir(PORTG,DIROUT,DATA_MSK);gpioclearbits(PORTG,DATA_MSK)
#define DATA_LINE_HIGH    gpiosetdir(PORTG,DIRIN,DATA_MSK)
#define DATA_LINE_READ    gpiogetbits(PORTG,DATA_MSK)?(1):(0)

#define CLOCK_LINE_LOW    gpioclearbits(PORTG,CLOCK_MSK)
#define CLOCK_LINE_HIGH   gpiosetbits(PORTG,CLOCK_MSK)
#endif

#define CMD_READ_TEMP     0x03
#define CMD_READ_HUM      0x05


static int verbose = 0;
static const char * version_str = "1.02 20090128";


static void
usage(void)
{
    fprintf(stderr, "Usage: "
            "sht_test [-h] [-r] [-v] [-V]\n"
            "  where:\n"
            "    -h       print usage message\n"
            "    -r       send reset to SHT before fetching info\n"
            "    -v       increase verbosity (more written to log)\n"
            "    -V       print version string then exit\n\n"
            "Test Sensirion SHT-71, CLK=(I)OG%d DATA=IOG%d\n", CLOCK_BIT,
            DATA_BIT);
}

#ifdef __CRIS__
// -----------------------------------------------------------------------
// Send the start sequence
// -----------------------------------------------------------------------
static void
SendStart(void)
{
    DATA_LINE_OUT;

    CLOCK_LINE_HIGH;
    usleep(1000);
    DATA_LINE_IN;
    DATA_LINE_LOW;
    CLOCK_LINE_LOW;
    CLOCK_LINE_HIGH;
    usleep(1000);
    DATA_LINE_HIGH;
    CLOCK_LINE_LOW;
    DATA_LINE_IN;
}

// -----------------------------------------------------------------------
// Sensor reset
// -----------------------------------------------------------------------
static void
SendReset (void)
{
    int k;

    for (k = 0; k < 12; k++) {
        CLOCK_LINE_HIGH;
        usleep(1000);
        CLOCK_LINE_LOW;
    }
}

// -----------------------------------------------------------------------
// Send a byte to the sensor
// -----------------------------------------------------------------------
static int
SendByte(unsigned char byte)
{
    unsigned char tempbyte;
    int k;

    DATA_LINE_OUT;
    tempbyte = byte;
    for (k = 0x80; k > 0; k /= 2) {

        if (tempbyte & k)
            DATA_LINE_HIGH;
        else
            DATA_LINE_LOW;

        CLOCK_LINE_HIGH;
        usleep(1000);
        CLOCK_LINE_LOW;
    }
    DATA_LINE_IN;
    CLOCK_LINE_HIGH;
    CLOCK_LINE_LOW;
    return 1;
}

// -----------------------------------------------------------------------
// Read a byte from the sensor
// withack
//   1 = send the ACK
//   0 = don't send the ACK
// -----------------------------------------------------------------------
static unsigned char
ReadByte(int withack)
{
    unsigned char tempbyte;
    int k;

    tempbyte = 0;
    DATA_LINE_IN;
    for (k = 0x80; k > 0; k /= 2) {
        CLOCK_LINE_HIGH;
        if (DATA_LINE_READ)
            tempbyte |= k;
        CLOCK_LINE_LOW;
    }
    if (withack) {
        // Acknowledge del byte
        DATA_LINE_OUT;
        DATA_LINE_LOW;
        CLOCK_LINE_HIGH;
        CLOCK_LINE_LOW;
        DATA_LINE_IN;
    } else {
        // Senza acknowledge
        DATA_LINE_OUT;
        DATA_LINE_HIGH;
        CLOCK_LINE_HIGH;
        CLOCK_LINE_LOW;
        DATA_LINE_IN;
    }
    return tempbyte;
}

// ----------------------
// Read the temperature
// ----------------------
static int
ReadTemperature(void)
{
    unsigned char Lsb, Msb, Chk;

    SendStart();
    if (! SendByte(CMD_READ_TEMP))
        return 0;
    while (DATA_LINE_READ)
        ;
    Msb = ReadByte(1);
    if (verbose > 1)
        fprintf(stderr, "ReadTemperature: Msb=%d\n", Msb);
    Lsb = ReadByte(1);
    if (verbose > 1)
        fprintf(stderr, "ReadTemperature: Lsb=%d\n", Lsb);
    Chk = ReadByte(0);
    if (verbose > 1)
        fprintf(stderr, "ReadTemperature: Chk=%d\n", Chk);
    if (1 == verbose)
        fprintf(stderr, "ReadTemperature: Msb=%d Lsb=%d Chk=%d\n", Msb, Lsb,
                Chk);
    return (Msb << 8) + Lsb; 
}

// ------------------
// Read the humidity
// ------------------

static int
ReadHumidity(void)
{
    unsigned char Lsb, Msb, Chk;

    SendStart();

    if (! SendByte(CMD_READ_HUM))
        return 0;
    while (DATA_LINE_READ)
        ;
    Msb = ReadByte(1);
    if (verbose > 1)
        fprintf(stderr, "ReadHumidity: Msb=%d\n", Msb);
    Lsb = ReadByte(1);
    if (verbose > 1)
        fprintf(stderr, "ReadHumidity: Lsb=%d\n", Lsb);
    Chk = ReadByte(0);
    if (verbose > 1)
        fprintf(stderr, "ReadHumidity: Chk=%d\n", Chk);
    if (1 == verbose)
        fprintf(stderr, "ReadHumidity: Msb=%d Lsb=%d Chk=%d\n", Msb, Lsb,
                Chk);
    return (Msb << 8) + Lsb ;
}

#else

static int
ReadHumidity(void)
{
    return 0;
}

static int
ReadTemperature(void)
{
    return 0;
}

static void
SendReset(void)
{
}

#endif


// ----------
// main code
// ----------
int
main(int argc, char ** argv)
{
    int opt, soh, sot;
    int do_reset = 0;
    float rel_humidity, temperature_c;

    while ((opt = getopt(argc, argv, "hrvV")) != -1) {
        switch (opt) {
        case 'h':
            usage();
            exit(EXIT_SUCCESS);
        case 'r':
            ++do_reset;
            break;
        case 'v':
            ++verbose;
            break;
        case 'V':
            printf("%s\n", version_str);
            exit(EXIT_SUCCESS);
        default: /* '?' */
            usage();
            exit(EXIT_FAILURE);
        }
    }
    if (optind < argc) {
        if (optind < argc) {
            for (; optind < argc; ++optind)
                fprintf(stderr, "Unexpected extra argument: %s\n",
                        argv[optind]);
            usage();
            exit(EXIT_FAILURE);
        }
    }

    if (verbose)
        fprintf(stderr, "%s: Clock line (I)OG%d, Data line IOG%d\n",
                __FILE__ ,CLOCK_BIT, DATA_BIT);
    if (do_reset > 0)
        SendReset();
    // assume 12 bit (rather than 8 bit) accuracy
    soh = ReadHumidity();
    sot = ReadTemperature();
    if (verbose)
        fprintf(stderr, "soh=%d [0x%x]  sot=%d [0x%x]\n", soh, soh,  sot, sot);
#if 1
    // new formula from SHT7x version 4.1 datasheet
    rel_humidity = -2.0468 + (0.0367 * soh) + (-1.5955E-6 * soh * soh);
#else
    // older formula
    rel_humidity = -4 + (0.0405 * soh) + -2.8E-6;
#endif
    if (rel_humidity > 99.9)
        rel_humidity = 100.0;
    else if (rel_humidity < 0.1)
        rel_humidity = 0.0;
    temperature_c = -39.66 + (0.01 * sot);
    printf ("Rel. Humidity: %.2f %%\n", rel_humidity);
    printf ("Temperature  : %.2f C\n", temperature_c);
    return 0;
}
Its possible to compile it directly on-line with the Webcompiler.
# ./sht71
Humidity   : 60.15 %
Temperature: 22.70 C
#

SHT7x sensor and the FOXZB

The FOXZB board has a placement for the Sensirion SHT71 or SHT75 sensor has shown in the following pictures ():


Placement for the SHT7x sensor on the FOXZB add-on board