mbed Weather Platform firmware http://mbed.org/users/okini3939/notebook/mbed-weather-platform-firmware/

Dependencies:   ChaNFSSD EthernetNetIf I2CLEDDisp Agentbed ChaNFSUSB ILinterpreter mbed BMP085 WeatherMeters ConfigFile ChaNFS I2CLCD

SHT_v1/SHT.cpp

Committer:
okini3939
Date:
2012-03-16
Revision:
8:bed0b81794ba
Parent:
0:bdb53686c194

File content as of revision 8:bed0b81794ba:

/* 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"

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;
   printf("constructor\n");
}

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(1);                   //ensure sclk is low for min time
        sclk=1;                       //clk for SENSI-BUS
        wait_us(1);                   //pulsewith approx. 2 us
        sclk=0;
    }
    data.input();                     //release DATA-line
    wait_us(1);                       //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(1);
    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(1);
        sclk=1;                       //clk for SENSI-BUS
        if (data) val=(val | i);      //read bit
        wait_us(1);
        sclk=0;
    }
    wait_us(1);
    if (send_ack) data.output();      // if ack needed then drive data low
    sclk=1;                           //clk #9 for ack
    wait_us(1);
    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(1);
    sclk=1;
    wait_us(1);
    data.output();            // data low
    wait_us(1);
    sclk=0;
    wait_us(1);
    sclk=1;
    wait_us(1);
    data.input();            // allow data to high
    wait_us(1);
    sclk=0;
    wait_us(1);
}

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(1);
        sclk=1;
        wait_us(1);
        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 [&#65533;C] and humidity [%RH]
// input :  hum  [Ticks] (12 bit)
//          temp [Ticks] (14 bit)
// output:  humidity [%RH]
//          temperature [&#65533;C]
{
    const float C1=-4.0;              // for 12 Bit
    const float C2=+0.0405;           // for 12 Bit
    const float C3=-0.0000028;        // for 12 Bit
    //const float T1=+0.01;             // for 14 Bit @ 5V
    //const float T2=+0.00008;           // for 14 Bit @ 5V

    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=t*0.01 - 40;                  //calc. temperature from ticks to [&#65533;C]
    humidity=C3*rh*rh + C2*rh + C1;     //calc. humidity from ticks to [%RH]
    // =(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;
}

void SHT::update(SHT_acc acc) {   // update stored values from sensor
    int error=0;
    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();

}