Sensirion SHT11 library
Diff: sht11.cpp
- Revision:
- 0:56bbfad2d592
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sht11.cpp Sun Apr 19 01:09:46 2015 +0000 @@ -0,0 +1,368 @@ +/** +@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; +}