SHT.cpp
- Committer:
- roselea
- Date:
- 2010-01-24
- Revision:
- 0:df1c8f2961a1
File content as of revision 0:df1c8f2961a1:
/* 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();
}