LM77 Temperature sensor with I2C interface. Provides temperature in celsius and fahrenheit. The device also supports temperature alerts.
LM77.cpp
- Committer:
- wim
- Date:
- 2015-01-10
- Revision:
- 0:8e812deb9f66
File content as of revision 0:8e812deb9f66:
/* 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); }