Wim Huiskamp / LM77

Dependents:   mbed_HP03SA_LM77

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LM77.cpp Source File

LM77.cpp

00001 /* mbed LM77 Library, for an I2C Temperature sensor
00002  * Copyright (c) 2015, v01: WH, Initial version
00003  * 
00004  * The LM77 is a digital temperature sensor and thermal window comparator with an I2C Serial Bus interface. 
00005  * The open-drain Interrupt (INT) output becomes active whenever temperature goes outside a programmable window,
00006  * while a separate Critical Temperature Alarm (T_CRIT_A) output becomes active when the temperature exceeds a 
00007  * programmable critical limit. The INT output can operate in either a comparator or event mode, while the T_CRIT_A 
00008  * output operates in comparator mode only. The host can program both the upper and lower limits of the window as 
00009  * well as the critical temperature limit. Programmable hysterisis as well as a fault queue are available to minimize 
00010  * false tripping. Two pins (A0, A1) are available for address selection. The sensor powers up with default thresholds 
00011  * of 2°C THYST, 10°C TLOW, 64°C THIGH, and 80°C TCRIT.
00012  * 
00013  * Permission is hereby granted, free of charge, to any person obtaining a copy
00014  * of this software and associated documentation files (the "Software"), to deal
00015  * in the Software without restriction, including without limitation the rights
00016  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00017  * copies of the Software, and to permit persons to whom the Software is
00018  * furnished to do so, subject to the following conditions:
00019  *
00020  * The above copyright notice and this permission notice shall be included in
00021  * all copies or substantial portions of the Software.
00022  *
00023  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00024  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00025  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00026  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00027  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00028  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00029  * THE SOFTWARE.
00030  */
00031 #include "LM77.h"
00032 
00033 /** Create an LM77 device instance
00034   *
00035   * @param i2c    I2C Bus 
00036   * @param char deviceAddress I2C slaveaddress
00037   */ 
00038 LM77::LM77(I2C *i2c, char deviceAddress) : _i2c(i2c), _slaveAddress(deviceAddress) {
00039 
00040 }
00041 
00042 /** Get Status
00043  *
00044  * @return bool Sensor ready 
00045  */ 
00046 bool LM77::getStatus(void) {
00047   char buffer[2];      
00048   int status;
00049     
00050   // Dummy operation to check status
00051   buffer[0] = 0x00;
00052   status=_i2c->write(_slaveAddress, buffer, 0);
00053 
00054   return (status==0);           // True when device found   
00055 }
00056 
00057 
00058 /** Get the current power mode of the LM77
00059   *
00060   * @returns The current power mode as a PowerMode enum.
00061   */
00062 LM77::PowerMode LM77::getPowerMode() {
00063 
00064     //Read the 8-bit register value
00065     char value = _readReg8(LM77_REG_CONF);
00066 
00067     //Return the status of the SHUTDOWN bit
00068     if (value & LM77_PWR_MSK) {
00069         return POWER_SHUTDOWN;
00070     }    
00071     else {
00072         return POWER_NORMAL;
00073     }    
00074 }
00075 
00076 
00077 /** Set the power mode of the LM77
00078   *
00079   * @param mode The new power mode as a PowerMode enum.
00080   */
00081 void LM77::setPowerMode(PowerMode mode) {
00082     
00083     //Read the current 8-bit register value
00084     char value = _readReg8(LM77_REG_CONF);
00085 
00086     //Set or clear the SHUTDOWN bit
00087     if (mode == POWER_SHUTDOWN) {
00088         value |= LM77_PWR_DWN;
00089     }    
00090     else {
00091         value &= ~LM77_PWR_DWN;
00092     }    
00093 
00094     //Write the value back out
00095     _writeReg8(LM77_REG_CONF, value);
00096 }
00097 
00098 
00099 /** Get the current INT pin mode of the LM77
00100   *
00101   * @returns The current INT pin mode as an IntMode enum.
00102   */
00103 LM77::IntMode LM77::getIntMode() {
00104     
00105     //Read the 8-bit register value
00106     char value = _readReg8(LM77_REG_CONF);
00107 
00108     //Return the status of the INT_MODE bit
00109     if (value & LM77_INT_MSK) {
00110         return INT_EVENT;
00111     }    
00112     else {
00113         return INT_COMPARATOR;
00114     }    
00115 }
00116 
00117 
00118 /** Set the INT pin mode of the LM77
00119   *
00120   * @param mode The new INT pin mode as an IntMode enum.
00121   */
00122 void LM77::setIntMode(IntMode mode) {
00123 
00124     //Read the current 8-bit register value
00125     char value = _readReg8(LM77_REG_CONF);
00126 
00127     //Set or clear the OS_COMP_INT bit
00128     if (mode == INT_EVENT) {
00129         value |= LM77_INT_EVENT;
00130     }    
00131     else {
00132         // Comparator mode 
00133         value &= ~LM77_INT_EVENT;
00134     }    
00135 
00136     //Write the value back out
00137     _writeReg8(LM77_REG_CONF, value);
00138 }
00139 
00140 
00141 /** Get the current INT pin polarity of the LM77
00142   *
00143   * @returns The current INT pin polarity as an PinPolarity enum.
00144   */
00145 LM77::PinPolarity LM77::getIntPolarity() {
00146     
00147     //Read the 8-bit register value
00148     char value = _readReg8(LM77_REG_CONF);
00149 
00150     //Return the status of the POL_INT bit
00151     if (value & LM77_POL_INT_MSK) {
00152         return ACTIVE_HIGH;
00153     }    
00154     else {
00155         return ACTIVE_LOW;
00156     }    
00157 }
00158 
00159 /** Set the INT pin polarity of the LM77
00160   *
00161   * @param polarity The new INT pin polarity as an PinPolarity enum.
00162   */
00163 void LM77::setIntPolarity(PinPolarity polarity)
00164 {
00165     //Read the current 8-bit register value
00166     char value = _readReg8(LM77_REG_CONF);
00167 
00168     //Set or clear the POL_INT bit
00169     if (polarity == ACTIVE_HIGH) {
00170         value |= LM77_POL_INT_H;
00171     }    
00172     else {
00173         value &= ~LM77_POL_INT_H;
00174     }    
00175 
00176     //Write the value back out
00177     _writeReg8(LM77_REG_CONF, value);
00178 }
00179 
00180 /** Get the current T_CRIT_A pin polarity of the LM77
00181   *
00182   * @returns The current T_CRIT_A pin polarity as an PinPolarity enum.
00183   */
00184 LM77::PinPolarity LM77::getTCritPolarity() {
00185     
00186     //Read the 8-bit register value
00187     char value = _readReg8(LM77_REG_CONF);
00188 
00189     //Return the status of the POL_TCRIT bit
00190     if (value & LM77_POL_TCRIT_MSK) {
00191         return ACTIVE_HIGH;
00192     }    
00193     else {
00194         return ACTIVE_LOW;
00195     }    
00196 }
00197 
00198 /** Set the T_CRIT_A pin polarity of the LM77
00199   *
00200   * @param polarity The new T_CRIT_A pin polarity as an PinPolarity enum.
00201   */
00202 void LM77::setTCritPolarity(PinPolarity polarity)
00203 {
00204     //Read the current 8-bit register value
00205     char value = _readReg8(LM77_REG_CONF);
00206 
00207     //Set or clear the POL_TCRIT bit
00208     if (polarity == ACTIVE_HIGH) {
00209         value |= LM77_POL_TCRIT_H;
00210     }    
00211     else {
00212         value &= ~LM77_POL_TCRIT_H;
00213     }    
00214 
00215     //Write the value back out
00216     _writeReg8(LM77_REG_CONF, value);
00217 }
00218 
00219 
00220 /** Get the current pin and flag fault queue length of the LM77
00221   *
00222   * @returns The current pin and flag fault queue length as an FaultQueue enum.
00223   */
00224 LM77::FaultQueue LM77::getFaultQueue()
00225 {
00226     //Read the 8-bit register value
00227     char value = _readReg8(LM77_REG_CONF);
00228 
00229     //Return the status of the FAULT_QUE bit
00230     if (value & LM77_FQU_MSK) {
00231         return FAULT_QUEUE_4;
00232     }    
00233     else {
00234         return FAULT_QUEUE_1;
00235     }    
00236 }
00237 
00238 
00239 /** Set the pin and flag fault queue length of the LM77
00240   *
00241   * @param queue The new pin and flag fault queue length as an FaultQueue enum.
00242   */
00243 void LM77::setFaultQueue(FaultQueue queue)
00244 {
00245     //Read the current 8-bit register value
00246     char value = _readReg8(LM77_REG_CONF);
00247 
00248     //Set the new FAULT_QUE bit
00249     if (queue == FAULT_QUEUE_4) {
00250         value |= LM77_FQU_4;
00251     }    
00252     else {
00253         value &= ~LM77_FQU_4;
00254     }    
00255 
00256     //Write the value back out
00257     _writeReg8(LM77_REG_CONF, value);
00258 }
00259 
00260 /** Get the current Critical alert temperature threshold of the LM77
00261   * Reset value is 80.0 °C.   
00262   *
00263   * @returns The current Critical alert temperature threshold in °C.
00264   */
00265 float LM77::getCritAlertTemp() {
00266     
00267   //Use the 9-bit helper to read the TCRIT register
00268   return _readTempHelper(LM77_REG_TCRIT);
00269 }
00270 
00271 /** Set the critical alert temperature threshold of the LM77
00272   * Reset value is 80.0 °C.   
00273   *
00274   * @param temp The new critical alert temperature threshold in °C.
00275   */
00276 void LM77::setCritAlertTemp(float temp) {
00277     
00278   //Use the 9-bit helper to write to the TCRIT register
00279   _writeTempHelper(LM77_REG_TCRIT, temp);
00280 }
00281 
00282 /** Get the current Low temperature alert threshold of the LM77
00283   * Reset value is 10.0 °C.   
00284   *
00285   * @returns The current Low temperature alert threshold in °C.
00286   */
00287 float LM77::getLowAlertTemp() {
00288 
00289   //Use the 9-bit helper to read the TLOW register
00290   return _readTempHelper(LM77_REG_TLOW);
00291 }
00292 
00293 /** Set the current Low temperature alert threshold of the LM77
00294   * Reset value is 10.0 °C.   
00295   *
00296   * @param temp The new Low alert temperature threshold in °C.
00297   */
00298 void LM77::setLowAlertTemp(float temp){
00299   
00300   //Use the 9-bit helper to write to the TLOW register  
00301   _writeTempHelper(LM77_REG_TLOW, temp);
00302 }    
00303 
00304 /** Get the current High temperature alert threshold of the LM77
00305   * Reset value is 64.0 °C.   
00306   *
00307   * @returns The current High temperature alert threshold in °C.
00308   */
00309 float LM77::getHighAlertTemp(){
00310 
00311   //Use the 9-bit helper to read the THIGH register
00312   return _readTempHelper(LM77_REG_THIGH);
00313 }    
00314     
00315 /** Set the High temperature alert threshold of the LM77
00316   * Reset value is 64.0 °C.   
00317   *
00318   * @param temp The new High temperature alert threshold in °C.
00319   */
00320 void LM77::setHighAlertTemp(float temp) {
00321 
00322   //Use the 9-bit helper to write to the THIGH register  
00323   _writeTempHelper(LM77_REG_THIGH, temp);   
00324 }
00325 
00326 
00327 /** Get the current alert temperature hysteresis of the LM77
00328   * Reset value is 2.0 °C.
00329   *
00330   * @returns The current alert temperature hysteresis in °C.
00331   */ 
00332 float LM77::getAlertHyst() {
00333     
00334   //Use the 9-bit helper to read the THYST register
00335   return _readTempHelper(LM77_REG_THYST);
00336 }
00337 
00338 /** Set the alert temperature hysteresis of the LM77
00339   * Reset value is 2.0 °C.
00340   *
00341   * @param temp The new alert temperature hysteresis in °C.
00342   */
00343 void LM77::setAlertHyst(float temp) {
00344     
00345   //Use the 9-bit helper to write to the THYST register
00346   _writeTempHelper(LM77_REG_THYST, temp);
00347 }
00348 
00349 
00350 /** Get Temperature as int in °Celsius x 10
00351   *
00352   * @return int Temperature in °Celsius x 10
00353   */ 
00354 int LM77::getTemperatureInt(void) {
00355   
00356     //Signed return value
00357     int16_t value;
00358 
00359     //Read the 9-bit raw temperature value in 0.5 degree resolution
00360     value = _readReg16(LM77_REG_TEMP) >> 3;
00361 
00362     //Sign extend negative numbers
00363     if (value & (1 << 9))
00364         value |= 0xFE00;
00365 
00366     //Return the temperature in °C x 10
00367     return (int) value * 5;    // x 10 x 0.5
00368 }
00369 
00370 /** Get the Alert flags of the LM77
00371   *
00372   * @returns The current Alert flags as int.
00373   */
00374 int LM77::getAlertFlags() {
00375 
00376     //Signed return value
00377     int16_t value;
00378 
00379     //Read the 9-bit raw temperature value and the flags
00380     value = _readReg16(LM77_REG_TEMP);
00381     
00382     //Return the flag bits
00383     // LM77_FLAG_LOW    0x01
00384     // LM77_FLAG_HIGH   0x02
00385     // LM77_FLAG_CRIT   0x04
00386     // LM77_FLAG_MSK    0x07   
00387     return (value & LM77_FLAG_MSK);
00388 }
00389 
00390 
00391 /** Get Temperature as float in °Celsius
00392   *
00393   * @return float Temperature in °Celsius
00394   */ 
00395 float LM77::getTemperature(void) {
00396   
00397   return _readTempHelper(LM77_REG_TEMP);
00398 }
00399 
00400 #ifdef MBED_OPERATORS
00401 LM77::operator float() {
00402 
00403   //Return the current temperature reading
00404   return getTemperature();
00405 }
00406 #endif
00407 
00408 /** Convert Temperature from °Celsius into °Fahrenheit
00409   *
00410   * @param  float celsius in °Celsius  
00411   * @return float temperature in °Fahrenheit
00412   */ 
00413 float LM77::celsiusToFahrenheit(float celsius) {
00414   
00415   return ((celsius * 9.0f) / 5.0f) + 32.0f; // Convert to Fahrenheit
00416 }
00417 
00418 
00419 /** Read 8 bit value from register
00420   *
00421   * @param reg Index of register
00422   * @return data value from register
00423   */     
00424 char LM77::_readReg8(char reg) {
00425     
00426     //Select the register
00427     _i2c->write(_slaveAddress, &reg, 1, true);
00428 
00429     //Read the 8-bit register
00430     _i2c->read(_slaveAddress, &reg, 1);
00431 
00432     //Return the byte
00433     return reg;
00434 }
00435 
00436 /** Write 8 bit value to register
00437   *
00438   * @param reg Index of register
00439   * @param data value to write
00440   */     
00441 void LM77::_writeReg8(char reg, char data) {
00442     
00443     //Create a temporary buffer
00444     char buf[2];
00445 
00446     //Load the register address and 8-bit data
00447     buf[0] = reg;
00448     buf[1] = data;
00449 
00450     //Write the data
00451     _i2c->write(_slaveAddress, buf, 2);
00452 }
00453 
00454 /** Read 16 bit value from register
00455   * Used for Critical temp threshold, Low and High temp threshold window and Hysteresis
00456   *
00457   * @param reg Index of register
00458   * @return data value from register  
00459   */     
00460 int16_t LM77::_readReg16(char reg) {
00461     
00462     //Create a temporary buffer
00463     char buf[2];
00464     
00465     //Select the register
00466     _i2c->write(_slaveAddress, &reg, 1, true);
00467 
00468     //Read the 16-bit register
00469     _i2c->read(_slaveAddress, buf, 2);
00470 
00471     //Return the combined 16-bit value
00472     return (buf[0] << 8) | buf[1];
00473 }
00474 
00475 /** Write 16 bit value to register
00476   * Used for Critical temp threshold, Low and High temp threshold window and Hysteresis
00477   *
00478   * @param reg Index of register
00479   * @param data value to write
00480   */     
00481 void LM77::_writeReg16(char reg, int16_t data) {
00482     
00483     //Create a temporary buffer
00484     char buf[3];
00485 
00486     //Load the register address and 16-bit data
00487     buf[0] = reg;
00488     buf[1] = data >> 8;
00489     buf[2] = data;
00490 
00491     //Write the data
00492     _i2c->write(_slaveAddress, buf, 3);    
00493 }
00494 
00495 /** Get Temperature as float in °Celsius
00496   * Used for Critical temp threshold, Low and High temp threshold window and Hysteresis
00497   *
00498   * @param reg Index of register to read temp value
00499   * @return float Temperature in °Celsius
00500   */     
00501 float LM77::_readTempHelper(char reg) {
00502 
00503     //Signed return value
00504     int16_t value;
00505        
00506 #if(1)
00507     //Read the 9-bit raw temperature value in 0.5 degree resolution
00508     value = _readReg16(reg) >> 3;
00509 #else
00510     int16_t readreg;
00511     
00512     //Test neg temps
00513     readreg   = 0xFE70;  //-25 degree
00514     value = readreg >> 3;
00515 #endif   
00516     
00517     //Sign extend negative numbers
00518     if (value & (1 << 9))
00519         value |= 0xFE00;
00520 
00521     //Return the temperature in °C
00522     return (float) value * 0.5f; 
00523 }
00524 
00525 
00526 /** Set Temperature as float in °Celsius
00527  * Used for Critical temp threshold, Low and High temp threshold window and Hysteresis
00528  *
00529  * @param reg Index of register to write temp value
00530  * @param temp float Temperature value in °Celsius
00531  */        
00532 void LM77::_writeTempHelper(char reg, float temp) {
00533     //Signed value
00534     int16_t value;    
00535 
00536     //Range limit temp
00537     if (temp < -55.0)
00538         temp = -55.0;
00539     else if (temp > 125.0)
00540         temp = 125.0;
00541 
00542     //Extract and shift the signed integer
00543     value =  temp * 2.0f;
00544     value <<= 3;
00545 
00546     //Send the new value
00547     _writeReg16(reg, value);
00548 }