LM77 Temperature sensor with I2C interface. Provides temperature in celsius and fahrenheit. The device also supports temperature alerts.
Diff: LM77.cpp
- Revision:
- 0:8e812deb9f66
diff -r 000000000000 -r 8e812deb9f66 LM77.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LM77.cpp Sat Jan 10 19:10:40 2015 +0000 @@ -0,0 +1,548 @@ +/* mbed LM77 Library, for an I2C Temperature sensor + * Copyright (c) 2015, v01: WH, Initial version + * + * The LM77 is a digital temperature sensor and thermal window comparator with an I2C Serial Bus interface. + * The open-drain Interrupt (INT) output becomes active whenever temperature goes outside a programmable window, + * while a separate Critical Temperature Alarm (T_CRIT_A) output becomes active when the temperature exceeds a + * programmable critical limit. The INT output can operate in either a comparator or event mode, while the T_CRIT_A + * output operates in comparator mode only. The host can program both the upper and lower limits of the window as + * well as the critical temperature limit. Programmable hysterisis as well as a fault queue are available to minimize + * false tripping. Two pins (A0, A1) are available for address selection. The sensor powers up with default thresholds + * of 2°C THYST, 10°C TLOW, 64°C THIGH, and 80°C TCRIT. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "LM77.h" + +/** Create an LM77 device instance + * + * @param i2c I2C Bus + * @param char deviceAddress I2C slaveaddress + */ +LM77::LM77(I2C *i2c, char deviceAddress) : _i2c(i2c), _slaveAddress(deviceAddress) { + +} + +/** Get Status + * + * @return bool Sensor ready + */ +bool LM77::getStatus(void) { + char buffer[2]; + int status; + + // Dummy operation to check status + buffer[0] = 0x00; + status=_i2c->write(_slaveAddress, buffer, 0); + + return (status==0); // True when device found +} + + +/** Get the current power mode of the LM77 + * + * @returns The current power mode as a PowerMode enum. + */ +LM77::PowerMode LM77::getPowerMode() { + + //Read the 8-bit register value + char value = _readReg8(LM77_REG_CONF); + + //Return the status of the SHUTDOWN bit + if (value & LM77_PWR_MSK) { + return POWER_SHUTDOWN; + } + else { + return POWER_NORMAL; + } +} + + +/** Set the power mode of the LM77 + * + * @param mode The new power mode as a PowerMode enum. + */ +void LM77::setPowerMode(PowerMode mode) { + + //Read the current 8-bit register value + char value = _readReg8(LM77_REG_CONF); + + //Set or clear the SHUTDOWN bit + if (mode == POWER_SHUTDOWN) { + value |= LM77_PWR_DWN; + } + else { + value &= ~LM77_PWR_DWN; + } + + //Write the value back out + _writeReg8(LM77_REG_CONF, value); +} + + +/** Get the current INT pin mode of the LM77 + * + * @returns The current INT pin mode as an IntMode enum. + */ +LM77::IntMode LM77::getIntMode() { + + //Read the 8-bit register value + char value = _readReg8(LM77_REG_CONF); + + //Return the status of the INT_MODE bit + if (value & LM77_INT_MSK) { + return INT_EVENT; + } + else { + return INT_COMPARATOR; + } +} + + +/** Set the INT pin mode of the LM77 + * + * @param mode The new INT pin mode as an IntMode enum. + */ +void LM77::setIntMode(IntMode mode) { + + //Read the current 8-bit register value + char value = _readReg8(LM77_REG_CONF); + + //Set or clear the OS_COMP_INT bit + if (mode == INT_EVENT) { + value |= LM77_INT_EVENT; + } + else { + // Comparator mode + value &= ~LM77_INT_EVENT; + } + + //Write the value back out + _writeReg8(LM77_REG_CONF, value); +} + + +/** Get the current INT pin polarity of the LM77 + * + * @returns The current INT pin polarity as an PinPolarity enum. + */ +LM77::PinPolarity LM77::getIntPolarity() { + + //Read the 8-bit register value + char value = _readReg8(LM77_REG_CONF); + + //Return the status of the POL_INT bit + if (value & LM77_POL_INT_MSK) { + return ACTIVE_HIGH; + } + else { + return ACTIVE_LOW; + } +} + +/** Set the INT pin polarity of the LM77 + * + * @param polarity The new INT pin polarity as an PinPolarity enum. + */ +void LM77::setIntPolarity(PinPolarity polarity) +{ + //Read the current 8-bit register value + char value = _readReg8(LM77_REG_CONF); + + //Set or clear the POL_INT bit + if (polarity == ACTIVE_HIGH) { + value |= LM77_POL_INT_H; + } + else { + value &= ~LM77_POL_INT_H; + } + + //Write the value back out + _writeReg8(LM77_REG_CONF, value); +} + +/** Get the current T_CRIT_A pin polarity of the LM77 + * + * @returns The current T_CRIT_A pin polarity as an PinPolarity enum. + */ +LM77::PinPolarity LM77::getTCritPolarity() { + + //Read the 8-bit register value + char value = _readReg8(LM77_REG_CONF); + + //Return the status of the POL_TCRIT bit + if (value & LM77_POL_TCRIT_MSK) { + return ACTIVE_HIGH; + } + else { + return ACTIVE_LOW; + } +} + +/** Set the T_CRIT_A pin polarity of the LM77 + * + * @param polarity The new T_CRIT_A pin polarity as an PinPolarity enum. + */ +void LM77::setTCritPolarity(PinPolarity polarity) +{ + //Read the current 8-bit register value + char value = _readReg8(LM77_REG_CONF); + + //Set or clear the POL_TCRIT bit + if (polarity == ACTIVE_HIGH) { + value |= LM77_POL_TCRIT_H; + } + else { + value &= ~LM77_POL_TCRIT_H; + } + + //Write the value back out + _writeReg8(LM77_REG_CONF, value); +} + + +/** Get the current pin and flag fault queue length of the LM77 + * + * @returns The current pin and flag fault queue length as an FaultQueue enum. + */ +LM77::FaultQueue LM77::getFaultQueue() +{ + //Read the 8-bit register value + char value = _readReg8(LM77_REG_CONF); + + //Return the status of the FAULT_QUE bit + if (value & LM77_FQU_MSK) { + return FAULT_QUEUE_4; + } + else { + return FAULT_QUEUE_1; + } +} + + +/** Set the pin and flag fault queue length of the LM77 + * + * @param queue The new pin and flag fault queue length as an FaultQueue enum. + */ +void LM77::setFaultQueue(FaultQueue queue) +{ + //Read the current 8-bit register value + char value = _readReg8(LM77_REG_CONF); + + //Set the new FAULT_QUE bit + if (queue == FAULT_QUEUE_4) { + value |= LM77_FQU_4; + } + else { + value &= ~LM77_FQU_4; + } + + //Write the value back out + _writeReg8(LM77_REG_CONF, value); +} + +/** Get the current Critical alert temperature threshold of the LM77 + * Reset value is 80.0 °C. + * + * @returns The current Critical alert temperature threshold in °C. + */ +float LM77::getCritAlertTemp() { + + //Use the 9-bit helper to read the TCRIT register + return _readTempHelper(LM77_REG_TCRIT); +} + +/** Set the critical alert temperature threshold of the LM77 + * Reset value is 80.0 °C. + * + * @param temp The new critical alert temperature threshold in °C. + */ +void LM77::setCritAlertTemp(float temp) { + + //Use the 9-bit helper to write to the TCRIT register + _writeTempHelper(LM77_REG_TCRIT, temp); +} + +/** Get the current Low temperature alert threshold of the LM77 + * Reset value is 10.0 °C. + * + * @returns The current Low temperature alert threshold in °C. + */ +float LM77::getLowAlertTemp() { + + //Use the 9-bit helper to read the TLOW register + return _readTempHelper(LM77_REG_TLOW); +} + +/** Set the current Low temperature alert threshold of the LM77 + * Reset value is 10.0 °C. + * + * @param temp The new Low alert temperature threshold in °C. + */ +void LM77::setLowAlertTemp(float temp){ + + //Use the 9-bit helper to write to the TLOW register + _writeTempHelper(LM77_REG_TLOW, temp); +} + +/** Get the current High temperature alert threshold of the LM77 + * Reset value is 64.0 °C. + * + * @returns The current High temperature alert threshold in °C. + */ +float LM77::getHighAlertTemp(){ + + //Use the 9-bit helper to read the THIGH register + return _readTempHelper(LM77_REG_THIGH); +} + +/** Set the High temperature alert threshold of the LM77 + * Reset value is 64.0 °C. + * + * @param temp The new High temperature alert threshold in °C. + */ +void LM77::setHighAlertTemp(float temp) { + + //Use the 9-bit helper to write to the THIGH register + _writeTempHelper(LM77_REG_THIGH, temp); +} + + +/** Get the current alert temperature hysteresis of the LM77 + * Reset value is 2.0 °C. + * + * @returns The current alert temperature hysteresis in °C. + */ +float LM77::getAlertHyst() { + + //Use the 9-bit helper to read the THYST register + return _readTempHelper(LM77_REG_THYST); +} + +/** Set the alert temperature hysteresis of the LM77 + * Reset value is 2.0 °C. + * + * @param temp The new alert temperature hysteresis in °C. + */ +void LM77::setAlertHyst(float temp) { + + //Use the 9-bit helper to write to the THYST register + _writeTempHelper(LM77_REG_THYST, temp); +} + + +/** Get Temperature as int in °Celsius x 10 + * + * @return int Temperature in °Celsius x 10 + */ +int LM77::getTemperatureInt(void) { + + //Signed return value + int16_t value; + + //Read the 9-bit raw temperature value in 0.5 degree resolution + value = _readReg16(LM77_REG_TEMP) >> 3; + + //Sign extend negative numbers + if (value & (1 << 9)) + value |= 0xFE00; + + //Return the temperature in °C x 10 + return (int) value * 5; // x 10 x 0.5 +} + +/** Get the Alert flags of the LM77 + * + * @returns The current Alert flags as int. + */ +int LM77::getAlertFlags() { + + //Signed return value + int16_t value; + + //Read the 9-bit raw temperature value and the flags + value = _readReg16(LM77_REG_TEMP); + + //Return the flag bits + // LM77_FLAG_LOW 0x01 + // LM77_FLAG_HIGH 0x02 + // LM77_FLAG_CRIT 0x04 + // LM77_FLAG_MSK 0x07 + return (value & LM77_FLAG_MSK); +} + + +/** Get Temperature as float in °Celsius + * + * @return float Temperature in °Celsius + */ +float LM77::getTemperature(void) { + + return _readTempHelper(LM77_REG_TEMP); +} + +#ifdef MBED_OPERATORS +LM77::operator float() { + + //Return the current temperature reading + return getTemperature(); +} +#endif + +/** Convert Temperature from °Celsius into °Fahrenheit + * + * @param float celsius in °Celsius + * @return float temperature in °Fahrenheit + */ +float LM77::celsiusToFahrenheit(float celsius) { + + return ((celsius * 9.0f) / 5.0f) + 32.0f; // Convert to Fahrenheit +} + + +/** Read 8 bit value from register + * + * @param reg Index of register + * @return data value from register + */ +char LM77::_readReg8(char reg) { + + //Select the register + _i2c->write(_slaveAddress, ®, 1, true); + + //Read the 8-bit register + _i2c->read(_slaveAddress, ®, 1); + + //Return the byte + return reg; +} + +/** Write 8 bit value to register + * + * @param reg Index of register + * @param data value to write + */ +void LM77::_writeReg8(char reg, char data) { + + //Create a temporary buffer + char buf[2]; + + //Load the register address and 8-bit data + buf[0] = reg; + buf[1] = data; + + //Write the data + _i2c->write(_slaveAddress, buf, 2); +} + +/** Read 16 bit value from register + * Used for Critical temp threshold, Low and High temp threshold window and Hysteresis + * + * @param reg Index of register + * @return data value from register + */ +int16_t LM77::_readReg16(char reg) { + + //Create a temporary buffer + char buf[2]; + + //Select the register + _i2c->write(_slaveAddress, ®, 1, true); + + //Read the 16-bit register + _i2c->read(_slaveAddress, buf, 2); + + //Return the combined 16-bit value + return (buf[0] << 8) | buf[1]; +} + +/** Write 16 bit value to register + * Used for Critical temp threshold, Low and High temp threshold window and Hysteresis + * + * @param reg Index of register + * @param data value to write + */ +void LM77::_writeReg16(char reg, int16_t data) { + + //Create a temporary buffer + char buf[3]; + + //Load the register address and 16-bit data + buf[0] = reg; + buf[1] = data >> 8; + buf[2] = data; + + //Write the data + _i2c->write(_slaveAddress, buf, 3); +} + +/** Get Temperature as float in °Celsius + * Used for Critical temp threshold, Low and High temp threshold window and Hysteresis + * + * @param reg Index of register to read temp value + * @return float Temperature in °Celsius + */ +float LM77::_readTempHelper(char reg) { + + //Signed return value + int16_t value; + +#if(1) + //Read the 9-bit raw temperature value in 0.5 degree resolution + value = _readReg16(reg) >> 3; +#else + int16_t readreg; + + //Test neg temps + readreg = 0xFE70; //-25 degree + value = readreg >> 3; +#endif + + //Sign extend negative numbers + if (value & (1 << 9)) + value |= 0xFE00; + + //Return the temperature in °C + return (float) value * 0.5f; +} + + +/** Set Temperature as float in °Celsius + * Used for Critical temp threshold, Low and High temp threshold window and Hysteresis + * + * @param reg Index of register to write temp value + * @param temp float Temperature value in °Celsius + */ +void LM77::_writeTempHelper(char reg, float temp) { + //Signed value + int16_t value; + + //Range limit temp + if (temp < -55.0) + temp = -55.0; + else if (temp > 125.0) + temp = 125.0; + + //Extract and shift the signed integer + value = temp * 2.0f; + value <<= 3; + + //Send the new value + _writeReg16(reg, value); +} \ No newline at end of file