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;
}