Sensirion SHT11 library

sht11.cpp

Committer:
timm
Date:
2015-04-19
Revision:
0:56bbfad2d592

File content as of revision 0:56bbfad2d592:

/**
@file sht11.cpp

@brief Member functions implementations

*/
#include "mbed.h"
#include "sht11.h"

                            //adr  command  r/w
#define STATUS_REG_W 0x06   //000   0011    0
#define STATUS_REG_R 0x07   //000   0011    1
#define MEASURE_TEMP 0x03   //000   0001    1
#define MEASURE_HUMI 0x05   //000   0010    1
#define RESET        0x1e   //000   1111    0

SHT11::SHT11(PinName clkPin, PinName dataPin)
{
    clk = new DigitalOut(clkPin);
    data = new DigitalInOut(dataPin);
}

/*
 * To initiate a transmission, a .Transmission Start. sequence
 * has to be issued. It consists of a lowering of the DATA line
 * while SCK is high, followed by a low pulse on SCK and
 * raising DATA again while SCK is still high.
 *
 *         ______             _________
 *  DATA:        \___________/
 *              _____       _____
 *   SCK:  ___/      \____/      \_____
 */
 
void SHT11::sendTransmissionStart()
{
    data->output();
    
    clk->write(0);
    data->write(1);
    wait_ms(10);
    
    clk->write(1);
    wait_ms(10);
    
    data->write(0);
    wait_ms(10);
    
    clk->write(0);
    wait_ms(10);
    
    clk->write(1);
    wait_ms(10);
    
    data->write(1);
    wait_ms(10);
    
    clk->write(0);
    wait_ms(10);
}

/* 
 * connection reset: release the data line high and clock out >= 9 SCK cycles 
 * followed by transaction start cycle
 */
void SHT11::connectionReset()
{
    int i;
    
    data->output();
    data->write(1);
    clk->write(0);
    wait_ms(10);
    
    for(i=0; i<10; i++)
    {
        clk->write(1);
        wait_ms(10);
        clk->write(0);
        wait_ms(10);
    }
}

void SHT11::init() 
{
    connectionReset();
}

int SHT11::writeByte(unsigned char writeData)
{
    unsigned char writeMask = 0x80;
    int ack = 0;
    
    // Ensure initial condition: clock low, data is an output
    clk->write(0);
    data->output();
    wait_ms(10);
    
    while(writeMask != 0)
    {
        if ((writeData & writeMask) != 0) {
            data->write(1);
            }
        else {
            data->write(0);
            }
        
        // delay for data to stabilize
        wait_ms(10);
        
        clk->write(1);
        wait_ms(10);
        clk->write(0);
        wait_ms(10);
        
        writeMask >>= 1;
    }
    
    // release the data line
    data->write(1);
    data->input();
    wait_ms(10);
    
    // 9th clock for ack, read the ack, return clk to low
    clk->write(1);
    wait_ms(10);   
    ack = data->read();
    clk->write(0);
    wait_ms(10);
    
    return((int)ack);   
}

void SHT11::softReset()
{
    connectionReset();
    writeByte(RESET);
}

int SHT11::readByte(unsigned char *pReadData, bool doAck)
{
    unsigned char retData = 0x00;
    unsigned char readMask = 0x80;
    int bitVal;
    
    // Ensure start conditions: clock low; data is input
    clk->write(0);
    data->write(1);
    data->input();
    wait_ms(10);
    
    while(readMask != 0)
    {
        clk->write(1);
        wait_ms(10);
        bitVal = data->read();
        if (bitVal != 0)
            retData |= readMask;
        clk->write(0);
        wait_ms(10);
        readMask >>= 1;
    }
    
    // If clocking out an ack; 
    if (doAck == true)
    {
        data->output();
        data->write(0);
    }

    wait_ms(10);
    clk->write(1);
    wait_ms(10);
    clk->write(0);
    data->input();
    
    *pReadData = retData;
    return 1;
}

int SHT11::readStatus(unsigned char *pRetStatus)
{
    unsigned char retStatus, checksum;
    int retVal = -1;
    
    sendTransmissionStart();
    
    if (writeByte(STATUS_REG_R) == 0)
    {
        readByte(&retStatus, true);
        readByte(&checksum, false);
        *pRetStatus = retStatus;
        retVal = 0;
    }
    
    return retVal;
}
    
int SHT11::writeStatus(unsigned char writeValue)
{
    int retVal = -1;
    
    sendTransmissionStart();
    
    if (writeByte(STATUS_REG_W) == 0)
    {
        writeByte(writeValue);
        retVal = 0;
    }
    
    return retVal;
}

int SHT11::measureTemp(unsigned short *pRetTempRaw)
{
    int retVal = -1;
    unsigned int waitCount;
    union {
        unsigned short u16;
        unsigned char u8[2];
        } u;
    unsigned char checksum;
    
    sendTransmissionStart();
    
    retVal = writeByte(MEASURE_TEMP);
    
    if (retVal == 0)
    {
        data->input();
        waitCount = 65535; // UINT_MAX
        while(waitCount > 0)
        {
            if (data->read() == 0)
            {
                break;
            }
            wait_ms(10);
            waitCount -= 1;
        }
    }
    else
    {
        return -1;
    }
    
    readByte(&(u.u8[1]), true);
    readByte(&(u.u8[0]), true);
    readByte(&checksum, false);

    *pRetTempRaw = u.u16;
    retVal = 0;
    
    return retVal;
}

int SHT11::measureHumid(unsigned short *pRetHumidRaw)
{
    int retVal = -1;
    unsigned int waitCount;
    union {
        unsigned short u16;
        unsigned char u8[2];
        } u;
    unsigned char checksum;
    
    sendTransmissionStart();
    
    retVal = writeByte(MEASURE_HUMI);
    
    if (retVal == 0)
    {
        data->input();
        waitCount = 65535; // UINT_MAX;
        while(waitCount > 0)
        {
            if (data->read() == 0)
            {
                break;
            }
            wait_ms(10);
            waitCount -= 1;
        }
    }
    else
    {
        return -1;
    }
    
    readByte(&(u.u8[1]), true);
    readByte(&(u.u8[0]), true);
    readByte(&checksum, false);

    *pRetHumidRaw = u.u16;
    retVal = 0;
    
    return retVal;
}

float SHT11::convertTempCelsius(unsigned short rawTempIn)
{
    return ((((float)rawTempIn) * 0.010) - 40.0);
}


float SHT11::convertTempFahrenheit(unsigned short rawTempIn)
{
    return ((((float)rawTempIn) * 0.018) - 40.0);
}

float SHT11::convertHumid(unsigned short rawHumidIn, unsigned short rawTempIn)
{
    const float C1 = -4.0;
    const float C2 = 0.0405;
    const float C3 = -0.0000028;
    const float T1 = 0.01;
    const float T2 = 0.00008;
    
    float tempOut;
    float humidLinearOut;
    float humidOutTrue;
    
    tempOut = convertTempCelsius(rawTempIn);
    
    humidLinearOut = (float)rawHumidIn;
    humidLinearOut = (C3 * humidLinearOut * humidLinearOut) + (C2 * humidLinearOut) + C1;
    
    humidOutTrue = (tempOut - 25.0) * (T1 + T2 * ((float)rawHumidIn)) + humidLinearOut;
    
    humidOutTrue = ((humidOutTrue > 100.0) ? 100.0 : humidOutTrue);
    
    humidOutTrue = ((humidOutTrue < 0.0) ? 0.0 : humidOutTrue);
    
    return humidOutTrue;
}

int SHT11::getTemperature(float * pRetTemperature)
{
  unsigned short rawValue;
  int retVal = -1;
    
  if (measureTemp(&rawValue) == 0) {
    lastTemperature = convertTempCelsius(rawValue);
    *pRetTemperature = lastTemperature;
    retVal = 0;
    }

  return retVal;
}

int SHT11::getTempHumid(float * pRetTemperature, float * pRetHumidity)
{
  unsigned short rawTempValue;
  unsigned short rawHumidValue;
  int retVal = -1;
    
  if (measureTemp(&rawTempValue) == 0) {
    if (measureHumid(&rawHumidValue) == 0) {
      lastHumidity = convertHumid(rawHumidValue, rawTempValue);
      lastTemperature = convertTempCelsius(rawTempValue);
      *pRetHumidity = lastHumidity;
      *pRetTemperature = lastTemperature;
      retVal = 0;
      }
    }

  return retVal;
}