Sensirion SHT11 Temperature and Humidity Sensor on a MikroElektronika Click Board

In one of my earlier posts (“Using the DHT11/DHT22 Temperature/Humidity Sensor with a FRDM Board“) I’m using the DHT11/DHT22 temperature/humidity sensors with the FRDM-KL25Z board. These sensors are very inexpensive, but have limited measurement range and accuracy. As pointed out by a reader of that article, Sensirion (a Swiss company :-)) has good sensors too, and I decided I would like to try the SHT11 sensor:

  • 0-100% Relative Humidity
  • +/- 3% Relative Humidity accuracy
  • -40 – +125°C
  • 2.4 – 5.5V supply voltage
SHT11 Sensor

SHT11 Sensor

One advantage of the Freescale Freedom boards is that they work with Arduino Shields: a standardized pin out for extension boards. The company MikroElektronika has an interesting concept: they provide ‘click shields‘ for many ‘Arduino compatible’ boards (PIC, STM32, AVR, BeagleBone, …), and add-on ‘Click’ boards. Their shields are well priced (below $10), and they offer a large set of ‘click’ boards. The price for these boards depends on the hardware on it, but are very reasonably priced too. While I could have decided to solder an SHT11 sensor myself, I wanted to try it on a Click module as I think this could be used that way in classroom too.

SHT11 Click Board

The SHT1x Click Board comes in a box with documentation and the headers to solder to the board:

SHT11 Click Board

SHT11 Click Board

The documentation in English includes the schematics and assembly instructions, which are available online too (http://www.mikroe.com/click/sht1x/).

FRDM-KL46Z Click Shield

MikroElektronika has a FRDM-KL46Z click shield which is intended for the Freescale FRDM-KL46Z board:

FRDM-KL46Z Click Shield

FRDM-KL46Z Click Shield

The shields do not have any active components on it: they only provide an electrical connection to the underlying FRDM board.

FRDM-K64F Click Shield

My contact offered me to give me FRDM-K64F click shield to try it out:-):

FRDM-K64F Click Shield

FRDM-K64F Click Shield

💡 I appreciate the fact that they have put a dedicated GND test point on the board. To hook the signals to a logic analyzer, I used the unused click module socket headers.

I decided to use the FRDM-K64F board for my first project with a Click Board. The Click Board can be put on one of the two sockets on the board:

Click Board on Click Shield

Click Board on Click Shield

The Click Shields/Boards are using a so called ‘micro BUS’: basically it is a standard pin out similar to the Arduino shield pin out, but just for fewer pins. It features SPI, I2C, analog signals, digital signals and 3.3V and 5V. Depending on the Click shield, only subset of the pins might be used.

Temperature/Humidity sensors are very sensitive the board temperature, therefore the sensor on the board is isolated from the rest of the board as much as possible:

SHT11 Click Board Details

SHT11 Click Board Details

As the SHT11 is using a ‘something like I2C’, the SCL and SDA signals are used to interface with the sensor. By default, the SHT11 Click Shield is configured for 3.3V (it can be changed for 5V operation), and has two 4.7kOhm pullup-resistors (R1, R2) populated.

Click Shield with Click Board mounted on FRDM-K64F Board

Click Shield with Click Board mounted on FRDM-K64F Board

SHT11 Device Driver

Because the SHT11 is not ‘exactly’ using I2C, a driver with bit-banging has to be used. I adopted the example code from here: http://www.libstock.com/projects/view/211/sht1x-click-example

Example Application

I have put an example application which writes the data to the console:

Console Output

Console Output

The project and sources are available on GitHub:
https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/KDS/FRDM-K64F120M/FRDM-K64F_ClickBoard

All the functionality except the SHT11 driver is implemented with Processor Expert components:

SHT11 Project

SHT11 Project

The driver code is presented here. Make sure you check out the latest version from the GitHub location.

/*
 * SHT11_driver.c
 *
 *  Created on: 06.03.2015
 *      Author: Erich Styger, adopted from http://www.libstock.com/projects/view/211/sht1x-click-example
 */

/* SHT11 connections and utility interface */
#include "SDA.h"
#include "SCL.h"
#include "WAIT1.h"
#include "SHT11_driver.h"

/* constants for calculating temperature and humidity *
/*- Module constants, see SHT1x datasheet for more information ------------------------------------ */
static const float SHT11_C1=-4.0;              // for 12 Bit
static const float SHT11_C2=+0.0405;           // for 12 Bit
static const float SHT11_C3=-0.0000028;        // for 12 Bit
static const float SHT11_Temp1=+0.01;          // for 14 Bit
static const float SHT11_Temp2=+0.00008;       // for 14 Bit

/* SHT1x definitions */
#define SHT11_noACK 0
#define SHT11_ACK   1
                           //adr  command        r/w
#define SHT11_STATUS_REG_W 0x06   //000   0011    0
#define SHT11_STATUS_REG_R 0x07   //000   0011    1
#define SHT11_MEASURE_TEMP 0x03   //000   0001    1
#define SHT11_MEASURE_HUMI 0x05   //000   0010    1
#define SHT11_RESET        0x1e   //000   1111    0

/**************************************************************************************************
* Generates a transmission start
*       _____         ________
* DATA:      |_______|
*           ___     ___
* SCK : ___|   |___|   |______
**************************************************************************************************/
void SHT11_TransmissionStart(void) {
  /* Initial state */
  SDA_SetInput(); /* release DATA-line */
  SCL_ClrVal(); /* SCL low */

  WAIT1_Waitus(1);
  SCL_SetVal();
  WAIT1_Waitus(1);

  SDA_SetOutput(); /* DATA as output */
  SDA_ClrVal(); /* SDA low */
  WAIT1_Waitus(1);
  SCL_ClrVal();
  WAIT1_Waitus(3);
  SCL_SetVal();
  WAIT1_Waitus(1);

  SDA_SetInput(); /* release DATA-line */
  WAIT1_Waitus(1);
  SCL_ClrVal();
}

/**************************************************************************************************
* Reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"
**************************************************************************************************/
uint8_t SHT11_ReadByte(unsigned char ack) {
  uint8_t i=0x80;
  uint8_t val=0;

  /* Initial state */
  SDA_SetInput(); /* release DATA line */
  SCL_ClrVal(); /* SCL low */
  while(i) {      /* shift bit for masking */
    SCL_SetVal(); /* clk for SENSI-BUS */
    WAIT1_Waitus(1);
    if (SDA_GetVal()==1) {
      val=(val | i);      /* read bit */
    }
    SCL_ClrVal();
    WAIT1_Waitus(1);
    i=(i>>1);
  }
  SDA_SetOutput(); /* DATA as output */
  if (ack) {  /* in case of "ack==1" pull down DATA-Line */
    SDA_ClrVal(); /* SDA low */
  } else {
    SDA_SetVal();
  }
  SCL_SetVal(); /* clk #9 for ack k*/
  WAIT1_Waitus(3);
  SCL_ClrVal();
  WAIT1_Waitus(1);
  SDA_SetInput(); /* release data line */
  return val;
}

/**************************************************************************************************
* Writes a byte on the Sensibus and checks the acknowledge.
**************************************************************************************************/
unsigned char SHT11_WriteByte(unsigned char value) {
  unsigned char i=0x80;
  unsigned char error=ERR_OK;

  SDA_SetOutput(); /* DATA as output */
  while(i) { /* shift bit for masking */
    if (i&value) {
      SDA_SetVal(); /* masking value with i , write to SENSI-BUS */
    } else  {
      SDA_ClrVal();
    }
    SCL_SetVal(); /* clk for SENSI-BUS */
    WAIT1_Waitus(3);
    SCL_ClrVal();
    WAIT1_Waitus(3);
    i=(i>>1);
  }
  SDA_SetInput(); /* release DATA-line */
  SCL_SetVal(); /* clk #9 for ack */
  WAIT1_Waitus(3);
  if (SDA_GetVal() == 1)  {
    error = ERR_FAILED; /* check ack (DATA will be pulled down by SHT11) */
  }
  WAIT1_Waitus(1);
  SCL_ClrVal();
  return error; /* error=ERR_FAILED in case of no acknowledge */
}

/**************************************************************************************************
* makes a measurement (humidity/temperature) with checksum
* p_value returns 2 bytes
* mode: 1=humidity 0=temperature
* return value: 0=ok, 1=write error, 2=timeout
**************************************************************************************************/
uint8_t SHT11_Measure(unsigned int *p_value, unsigned char mode) {
  unsigned char i=0;
  unsigned char msb,lsb;
  unsigned char checksum;

  *p_value=0;
  SHT11_TransmissionStart(); /* transmission start */
  if (mode) {
    mode = SHT11_MEASURE_HUMI;
  } else {
    mode = SHT11_MEASURE_TEMP;
  }
  if (SHT11_WriteByte(mode)!=ERR_OK) {
    return ERR_FAILED;
  }
  /* normal delays: temp i=70, humi i=20 */
  SDA_SetInput(); /* release DATA-line */
  while(i<240) {
    WAIT1_Waitms(1);
    WAIT1_Waitms(1);
    WAIT1_Waitms(1);
    if (SDA_GetVal()==0) {
      i=0;
      break;
    }
    i++;
  }
  /* or timeout */
  if (i) {
    return ERR_NOTAVAIL;
  }
  msb=SHT11_ReadByte(SHT11_ACK); //read the first byte (MSB)
  lsb=SHT11_ReadByte(SHT11_ACK); //read the second byte (LSB)
  checksum=SHT11_ReadByte(SHT11_noACK);                //read checksum (8-bit)
  *p_value=(msb<<8)|(lsb);
  return ERR_OK;
}

/**************************************************************************************************
* calculates temperature [C]
* input : temp [Ticks] (14 bit)
* output: temp [C] times 10 (e.g 253 = 25.3'C)
**************************************************************************************************/
float STH11_CalcTemperature(unsigned int t) {
  float t_out;

  t_out =  t*0.01 - 40;
  return t_out;
}

/**************************************************************************************************
* calculates humidity [%RH] with temperature compensation
* input : humi [Ticks] (12 bit), temperature in 'C * 100 (e.g 253 for 25.3'C)
* output: humi [%RH] (=integer value from 0 to 100)
**************************************************************************************************/
float ST11_CalcHumidity(unsigned int h, int t) {
  float rh_lin;                             // rh_lin:  Humidity linear
  float rh_true;                            // rh_true: Temperature compensated humidity
  float t_C;                                // t_C   :  Temperature [°C]

  t_C=t*0.01 - 40;                          //calc. temperature from ticks to [°C]
  rh_lin=SHT11_C3*h*h + SHT11_C2*h + SHT11_C1;                //calc. humidity from ticks to [%RH]
  rh_true=(t_C-25)*(SHT11_Temp1+SHT11_Temp2*h)+rh_lin;  //calc. temperature compensated humidity

  /* now calc. Temperature compensated humidity [%RH]
   * the correct formula is:
   * rh_true=(t/10-25)*(0.01+0.00008*(sensor_val))+rh;
   * sensor_val ~= rh*30
   * we use:
   * rh_true=(t/10-25) * 1/8;
   */

  if (rh_true>100) { /* cut if the value is outside of */
    rh_true=100;
  }
  if (rh_true<0.1) { /* the physical possible range */
    rh_true=0.1;
  }
  return rh_true;
}

/**************************************************************************************************
* reads temperature and humidity
**************************************************************************************************/
uint8_t SHT11_Read(float *fT, float *fRH) {
  unsigned int t;
  unsigned int h;
  float value;
  uint8_t res;
  int iSHT_Temp;
  int iSHT_Humi;

  res = SHT11_Measure(&t, 0);
  if (res!=ERR_OK) {
    return res;
  }
  iSHT_Temp = (int)(STH11_CalcTemperature(t) * 10);

  res = SHT11_Measure(&h, 1);
  if (res!=ERR_OK) {
    return res;
  }
  iSHT_Humi = (int)(ST11_CalcHumidity(h, t) * 10);

  value = (float)iSHT_Temp;
  *fT = value / 10;
  value = (float)iSHT_Humi;
  *fRH = value / 10;
}

/**************************************************************************************************
* reads the status register with checksum (8-bit)
**************************************************************************************************/
uint8_t SHT11_ReadStatusReg(uint8_t *p_value) {
  uint8_t checksum = 0;

  SHT11_TransmissionStart();  /* transmission start */
  if(SHT11_WriteByte(SHT11_STATUS_REG_R)!=ERR_OK) {  /* send command to sensor */
    return ERR_FAILED;
  }
  *p_value=SHT11_ReadByte(SHT11_ACK);   /* read status register (8-bit) */
  checksum=SHT11_ReadByte(SHT11_noACK); /* read checksum (8-bit) */
  return ERR_OK;
}

/**************************************************************************************************
* writes the status register with checksum (8-bit)
* input: status register value
* return value: ERR_OK=ok, ERR_FAILED=write error
**************************************************************************************************/
uint8_t SHT11_write_statusreg(uint8_t value) {
  SHT11_TransmissionStart();                  //transmission start
  if (SHT11_WriteByte(SHT11_STATUS_REG_W)!=ERR_OK) { //send command to sensor
    return ERR_FAILED;
  }
  if (SHT11_WriteByte(value)!=ERR_OK) { //send value of status register
    return ERR_FAILED;
  }
  return ERR_OK;
}

/**************************************************************************************************
* communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
*       _____________________________________________________         ________
* DATA:                                                      |_______|
*          _    _    _    _    _    _    _    _    _        ___     ___
* SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______
**************************************************************************************************/
void SHT11_ConnectionReset(void) {
  int i;

  SDA_SetInput();
  SCL_ClrVal();
  for(i=0; i<9; i++) {  /* 9 SCK cycles */
    SCL_SetVal();
    WAIT1_Waitus(3);
    SCL_ClrVal();
    WAIT1_Waitus(3);
  }
  SHT11_TransmissionStart(); /* transmission start */
}

/**************************************************************************************************
* Resets the sensor by a softreset
**************************************************************************************************/
uint8_t SHT11_SoftReset(void) {
  SHT11_ConnectionReset();  /* reset communication, send RESET-command to sensor */
  return SHT11_WriteByte(SHT11_RESET); /* return ERR_FAILED in case of no response form the sensor */
}

/**************************************************************************************************
* End of File
**************************************************************************************************/

The following source demonstrates how to write the sensor values to the console:

  CLS1_SendStr("\r\n-----------------------\r\nSHT11 Example\r\n-----------------------\r\n", CLS1_GetStdio()->stdOut);
  res = SHT11_SoftReset();
  if (res!=ERR_OK) {
    CLS1_SendStr("FAILED to reset device\r\n ", CLS1_GetStdio()->stdErr);
    for(;;){}
  }
  for(;;) {
    SHT11_Read(&temperature, &humidity);
    CLS1_SendStr("Temperature ", CLS1_GetStdio()->stdOut);
    buf[0] = '\0';
    UTIL1_strcatNum32sDotValue100(buf, sizeof(buf), temperature*100);
    CLS1_SendStr(buf, CLS1_GetStdio()->stdOut);
    CLS1_SendStr("°C, Humidity ", CLS1_GetStdio()->stdOut);
    buf[0] = '\0';
    UTIL1_strcatNum32sDotValue100(buf, sizeof(buf), humidity*100);
    CLS1_SendStr(buf, CLS1_GetStdio()->stdOut);
    CLS1_SendStr("%\r\n", CLS1_GetStdio()->stdOut);
    WAIT1_Waitms(1000);
    LED1_Neg();
  }

Summary

The MikroElektronika concept with inexpensive shields and click boards are a good way for me to either evaluate a sensor/board or to use one of the many modules in a ‘quick and dirty’ project without the need to make my custom board, either for hobby project or to use the boards in an educational environment. I very much like the amount of information and source code the MikroElektronika web site provides, which made it easy for me to write my driver. With the Freedom board Click Shields it is easy to use the Click Boards with Freedom boards like the KL46Z or K64F. I have as well a Bluetooth Click module (http://www.mikroe.com/click/bluetooth/), but I have not tried that one yet.

The example project and driver is available on GitHub.

Happy Clicking 🙂

Links:

Advertisements

13 thoughts on “Sensirion SHT11 Temperature and Humidity Sensor on a MikroElektronika Click Board

  1. Hi Eric

    I just re-discovered an old video I made of the SHT21 about 5 years ago – connected to a Coldfire:

    Temp/Humidity parts from 8:00 in the video.

    Regards

    Mark

    Like

  2. Hi Eric

    I try to do this project with kl25z and sensor SHT11 and I want to show the result on a parallel LCD. What I need to change to do that. I am beginner in programming microcontrollers.
    Sorry for my English.

    Like

  3. So… I added all the components that you had + LCDHTA… what I don’t know is how I add the code for the temperature value display read by the sensor. The driver made by you for sensor SHT11.. transmits the serial value?

    I tried to do this and it’s showing me the value 2

    #include “SHT11_driver.h”

    /*lint -save -e970 Disable MISRA rule (6.3) checking. */
    int main(void)
    /*lint -restore Enable MISRA rule (6.3) checking. */
    {
    /* Write your local variable definition here */
    float temperature, humidity;
    uint8_t res;
    unsigned char buf[32];

    /*** Processor Expert internal initialization. DON’T REMOVE THIS CODE!!! ***/
    PE_low_level_init();
    /*** End of Processor Expert internal initialization. ***/

    /* Write your code here */
    res = SHT11_SoftReset();
    if (res!=ERR_OK){

    LCD1_WriteLineStr(1, “Eroare”);
    }
    LCD1_Clear();
    LCD1_WriteLineStr(1, “Temp:”);

    for(;;){
    SHT11_Read (&temperature, &humidity);
    UTIL1_Num16uToStr(buf, sizeof(buf), temperature);
    LCD1_GotoXY(1,7);
    LCD1_WriteString((char*)buf);
    WAIT1_Waitms(1000);
    }

    Help me please and sorry for this beginner questions.

    Like

      • Now is showing me this “Temp: 23” on the display.
        Now is showing me the value of the temperature i things, for example 23… but it doesn’t modify when I cool-up or I heat the sensor.

        And I have another problem “Failed to resume target process.Downloading binary to target…” it appears this error when I debug it .

        Like

      • At what pins on board did you connect DATA and SCK of the sensor SHT11? or doesn’t have any importance as long as they are connected at the pins declared in codewarrior?

        Thank you for your answers !

        Like

        • Which pins does not matter as long a) they are correctly connected to the SHT11 pins and b) they are properly configured in the software. Plus make sure that the pins are not used by something else. A logic analyzer is what you need to verify such things.

          Like

  4. Hello Eric,

    I am working on a SHT10 connected to a STM32 card, in order to measure the temperature and the moisture of the soil.
    The goal of the project is to display the measures on a communication terminal like “HyperTerminal” or “Teraterm”.

    Do you have the librairies corresponding to your programms like :

    #include “SDA.h”
    #include “SCL.h”
    #include “WAIT1.h”

    Thank you for your help

    Corentin

    Like

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.