Stephen McGarry
/
SHT_v1
Diff: SHT.cpp
- Revision:
- 0:df1c8f2961a1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SHT.cpp Sun Jan 24 22:00:35 2010 +0000 @@ -0,0 +1,224 @@ +/* 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 [°C] and humidity [%RH] +// input : hum [Ticks] (12 bit) +// temp [Ticks] (14 bit) +// output: humidity [%RH] +// temperature [°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 [°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(); + +}