SHT V4 5V UART

Dependencies:   mbed

Fork of SHT_v1 by Stephen McGarry

SHT.cpp

Committer:
fblanc
Date:
2016-02-23
Revision:
1:0dbbb4802508
Parent:
0:df1c8f2961a1

File content as of revision 1:0dbbb4802508:

/* mbed module to use a Sensirion SHT1x /SHT7x sensor
 * Copyright (c) 2007-2009 Stephen McGarry
 * Released under the MIT License: http://mbed.org/license/mit
 */

#include "SHT.h"

#include "mbed.h"
#define MICROSECONDE 10//1

SHT::SHT(PinName p_sclk, PinName p_data, SHT_acc p_accuracy) : sclk(p_sclk), data(p_data), accuracy(p_accuracy) {
    sclk=0;
    data=0;               // data pin will be used as open collector pin
    data.mode(PullUp);    // with the pull up internally active
    data.input();        // with line released to go high
    temperature = humidity = dewpoint=0.0f;
  
}

char SHT::write_byte(byte value)
//----------------------------------------------------------------------------------
// writes a byte on the Sensibus and checks the acknowledge
{
    int i;
    char error=0;

    for (i=0x80;i>0;i/=2) {           //shift bit for masking
        if (i & value) data.input();  //masking value with i , write to SENSI-BUS
        else data.output();
        wait_us(MICROSECONDE);                   //ensure sclk is low for min time
        
        sclk=1;                       //clk for SENSI-BUS
        wait_us(MICROSECONDE);                   //pulsewith approx. 2 us
        sclk=0;
    }
    data.input();                     //release DATA-line
    wait_us(MICROSECONDE);                       //ensure sclk is low for min time
    sclk=1;                           //clk #9 for ack
    error=data;                       //check ack (DATA will be pulled down by SHT11)
    wait_us(MICROSECONDE);
    sclk=0;
    return error;                     //error=1 in case of no acknowledge
}

byte SHT::read_byte(bool send_ack)
//----------------------------------------------------------------------------------
// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"
{
    byte i,val=0;
    data.input();                     //release DATA-line
    for (i=0x80;i>0;i/=2) {           //shift bit for masking
        wait_us(MICROSECONDE);
        sclk=1;                       //clk for SENSI-BUS
        if (data) val=(val | i);      //read bit
        wait_us(MICROSECONDE);
        sclk=0;
    }
    wait_us(MICROSECONDE);
    if (send_ack) data.output();      // if ack needed then drive data low
    sclk=1;                           //clk #9 for ack
    wait_us(MICROSECONDE);
    sclk=0;
    data.input();                     //release DATA-line
    return val;
}

void SHT::trans_start(void)
//----------------------------------------------------------------------------------
// generates a transmission start
//       _____         ________
// DATA:      |_______|
//           ___     ___
// SCK : ___|   |___|   |______
{
    data.input();
    sclk=0;                   //Initial state
    wait_us(MICROSECONDE);
    sclk=1;
    wait_us(MICROSECONDE);
    data.output();            // data low
    wait_us(MICROSECONDE);
    sclk=0;
    wait_us(MICROSECONDE);
    sclk=1;
    wait_us(MICROSECONDE);
    data.input();            // allow data to high
    wait_us(MICROSECONDE);
    sclk=0;
    wait_us(MICROSECONDE);
}

void SHT::connection_reset(void)
//----------------------------------------------------------------------------------
// communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
//       _____________________________________________________         ________
// DATA:                                                      |_______|
//          _    _    _    _    _    _    _    _    _        ___     ___
// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______
{
    int i;
    data.input();            // allow data high
    sclk=0;                  // and clk low
    for (i=0;i<9;i++) {      // 9 SCK cycles
        wait_us(MICROSECONDE);
        sclk=1;
        wait_us(MICROSECONDE);
        sclk=0;
    }
}

char SHT::soft_reset(void)
//----------------------------------------------------------------------------------
// resets the sensor by a softreset
{
    char error=0;
    SHT::connection_reset();                //reset communication
    trans_start();
    error+=write_byte(com_reset);       //send RESET-command to sensor
    return error;                     //error=1 in case of no response form the sensor
}

char SHT::read_status(byte &value)
//----------------------------------------------------------------------------------
// reads the status register with checksum (8-bit)
{
    //byte checksum;

    char error=0;
    trans_start();                     //transmission start
    error=write_byte(com_read_status_reg); //send command to sensor
    value=read_byte(send_ack);             //read status register (8-bit)
    /* checksum= */
    (void)read_byte(no_ack);         //read checksum (8-bit)
    // check the checksum ??
    return error;                      //error=1 in case of no response form the sensor
}

char SHT::write_status(byte value)
//----------------------------------------------------------------------------------
// writes the status register (8-bit)
{
    char error=0;
    trans_start();                        //transmission start
    error+=write_byte(com_write_status_reg); //send command to sensor
    error+=write_byte(value);            //send value of status register
    return error;                          //error>=1 in case of no response form the sensor
}

char SHT::measure(int &value, byte command)
//----------------------------------------------------------------------------------
// makes a measurement (humidity/temperature) with checksum
{
    unsigned int i;
    byte msb;
    // byte checksum;

    trans_start();                //transmission start
    if (write_byte(command)) return 1; // if command fails return

    for (i=10000;i;i--) {          //wait until sensor has finished the measurement
        wait_us(100);
        if (data==0) break;
    }
    if (data) return 1;            // or timeout (~1 sec.) is reached !!
    msb = read_byte(send_ack);         //read the first byte (MSB)
    value = msb*256 + read_byte(send_ack);    //read the second byte (LSB)
    /* checksum= */
    (void)read_byte(no_ack);    //read checksum
    return 0;
}

void SHT::calculate()
//----------------------------------------------------------------------------------------
// calculates temperature [�C] and humidity [%RH]
// input :  hum  [Ticks] (12 bit)
//          temp [Ticks] (14 bit)
// output:  humidity [%RH]
//          temperature [�C]
{
    //Optimized V4 humidity conversion coefficients
    const float C1=-2.0468;              // for 12 Bit
    const float C2=0.0367;           // for 12 Bit
    const float C3=-1.5955E-6;        // for 12 Bit
    const float T1=0.01;             // for 12 
    const float T2=0.00008;           // for 12 Bit 
    const float D1= -40.1;             //for °C 5V
    const float D2= 0.01 ;            //for °C for 14
    float rh;                         // rh:      Humidity [Ticks] 12 Bit
    float t;                          // t:       Temperature [Ticks] 14 Bit
    float rh_lin;                     // rh_lin:  Humidity linear
    if (accuracy==SHT_low) {
        rh=hum*16;                    // rescale to high accuracy values - 8 to 12 bits
        t=temp*4;                     // and 12 to 14 bits
    } else {
        rh=hum;
        t=temp;
    }

    temperature=D1 + D2*t ;                  //calc. temperature from ticks to [�C]
     rh_lin=C3*rh*rh + C2*rh + C1;     //calc. humidity from ticks to [%RH]
     humidity =(temperature-25)*(T1+T2*rh)+rh_lin;   //calc. temperature compensated humidity [%RH] (ignore as never >0.25%)
    if (humidity>100)humidity=100;      //cut if the value is outside of
    if (humidity<0.1)humidity=0.1;      //the physical possible range
}

float SHT::get_temperature() {     // get the most recent temp reading
    return temperature;
}

float SHT::get_humidity() {        // get the most recent humidity reading
    return humidity;
}

float SHT::get_dewpoint() {        // get the most recent dewpoint value
    return dewpoint;
}

int SHT::update(SHT_acc acc) {   // update stored values from sensor
    int error=0;
    soft_reset();
    //connection_reset();
    if (acc!=accuracy) {
        accuracy=acc;
        error+=write_status((acc==SHT_low)?0x01:0x00);    //set the status reg to high or low accuarcy
    }
    error+=measure(temp,com_measure_temp);
    error+=measure(hum,com_measure_humid);
    if (!error) calculate();
return error;
}