lib for working with ltc2991s

Dependents:   ece495_firmware

Fork of ltc2991_test by Logan Rooper

Committer:
bdk9
Date:
Thu Jan 19 02:55:42 2017 +0000
Revision:
8:c0ae66611a12
Parent:
5:8aa0f4e6788c
Final Code

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lrdawg99 0:1473318f27b6 1 /*!
lrdawg99 0:1473318f27b6 2 LTC2991: 14-bit Octal I2C Voltage, Current, and Temperature Monitor
lrdawg99 0:1473318f27b6 3
lrdawg99 0:1473318f27b6 4 @verbatim
lrdawg99 0:1473318f27b6 5
lrdawg99 0:1473318f27b6 6 The LTC2991 is used to monitor system temperatures, voltages and currents.
lrdawg99 0:1473318f27b6 7 Through the I2C serial interface, the eight monitors can individually measure
lrdawg99 0:1473318f27b6 8 supply voltages and can be paired for differential measurements of current sense
lrdawg99 0:1473318f27b6 9 resistors or temperature sensing transistors. Additional measurements include
lrdawg99 0:1473318f27b6 10 internal temperature and internal VCC. The internal 10ppm reference minimizes
lrdawg99 0:1473318f27b6 11 the number of supporting components and area required. Selectable address and
lrdawg99 0:1473318f27b6 12 configurable functionality give the LTC2991 flexibility to be incorporated in
lrdawg99 0:1473318f27b6 13 various systems needing temperature, voltage or current data. The LTC2991 fits
lrdawg99 0:1473318f27b6 14 well in systems needing submillivolt voltage resolution, 1% current measurement
lrdawg99 0:1473318f27b6 15 and 1 degree Celsius temperature accuracy or any combination of the three.
lrdawg99 0:1473318f27b6 16
lrdawg99 0:1473318f27b6 17 @endverbatim
lrdawg99 0:1473318f27b6 18
lrdawg99 0:1473318f27b6 19 http://www.linear.com/product/LTC2991
lrdawg99 0:1473318f27b6 20
lrdawg99 0:1473318f27b6 21 http://www.linear.com/product/LTC2991#demoboards
lrdawg99 0:1473318f27b6 22
lrdawg99 0:1473318f27b6 23 REVISION HISTORY
lrdawg99 0:1473318f27b6 24 $Revision: 3659 $
lrdawg99 0:1473318f27b6 25 $Date: 2015-07-01 10:19:20 -0700 (Wed, 01 Jul 2015) $
lrdawg99 0:1473318f27b6 26
lrdawg99 0:1473318f27b6 27 Copyright (c) 2013, Linear Technology Corp.(LTC)
lrdawg99 0:1473318f27b6 28 All rights reserved.
lrdawg99 0:1473318f27b6 29
lrdawg99 0:1473318f27b6 30 Redistribution and use in source and binary forms, with or without
lrdawg99 0:1473318f27b6 31 modification, are permitted provided that the following conditions are met:
lrdawg99 0:1473318f27b6 32
lrdawg99 0:1473318f27b6 33 1. Redistributions of source code must retain the above copyright notice, this
lrdawg99 0:1473318f27b6 34 list of conditions and the following disclaimer.
lrdawg99 0:1473318f27b6 35 2. Redistributions in binary form must reproduce the above copyright notice,
lrdawg99 0:1473318f27b6 36 this list of conditions and the following disclaimer in the documentation
lrdawg99 0:1473318f27b6 37 and/or other materials provided with the distribution.
lrdawg99 0:1473318f27b6 38
lrdawg99 0:1473318f27b6 39 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
lrdawg99 0:1473318f27b6 40 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
lrdawg99 0:1473318f27b6 41 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
lrdawg99 0:1473318f27b6 42 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
lrdawg99 0:1473318f27b6 43 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
lrdawg99 0:1473318f27b6 44 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
lrdawg99 0:1473318f27b6 45 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
lrdawg99 0:1473318f27b6 46 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
lrdawg99 0:1473318f27b6 47 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
lrdawg99 0:1473318f27b6 48 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
lrdawg99 0:1473318f27b6 49
lrdawg99 0:1473318f27b6 50 The views and conclusions contained in the software and documentation are those
lrdawg99 0:1473318f27b6 51 of the authors and should not be interpreted as representing official policies,
lrdawg99 0:1473318f27b6 52 either expressed or implied, of Linear Technology Corp.
lrdawg99 0:1473318f27b6 53
lrdawg99 0:1473318f27b6 54 The Linear Technology Linduino is not affiliated with the official Arduino team.
lrdawg99 0:1473318f27b6 55 However, the Linduino is only possible because of the Arduino team's commitment
lrdawg99 0:1473318f27b6 56 to the open-source community. Please, visit http://www.arduino.cc and
lrdawg99 0:1473318f27b6 57 http://store.arduino.cc , and consider a purchase that will help fund their
lrdawg99 0:1473318f27b6 58 ongoing work.
lrdawg99 0:1473318f27b6 59 */
lrdawg99 0:1473318f27b6 60
lrdawg99 0:1473318f27b6 61 //! @defgroup LTC2991 LTC2991: 14-bit Octal I2C Voltage, Current, and Temperature Monitor
lrdawg99 0:1473318f27b6 62
lrdawg99 0:1473318f27b6 63 /*! @file
lrdawg99 0:1473318f27b6 64 @ingroup LTC2991
lrdawg99 0:1473318f27b6 65 Library for LTC2991: 14-bit Octal I2C Voltage, Current, and Temperature Monitor
lrdawg99 0:1473318f27b6 66 */
lrdawg99 0:1473318f27b6 67
lrdawg99 0:1473318f27b6 68 #include <stdint.h>
lrdawg99 0:1473318f27b6 69 #include "Linduino.h"
lrdawg99 0:1473318f27b6 70 #include "LT_I2C.h"
lrdawg99 0:1473318f27b6 71 #include "LTC2991.h"
lrdawg99 0:1473318f27b6 72 #include "mbed.h"
lrdawg99 0:1473318f27b6 73
bdk9 8:c0ae66611a12 74 //Serial pc2(USBTX, USBRX, 115200);
lrdawg99 1:4e4194db7cd6 75
lrdawg99 2:c9e727dcd00e 76 LTC2991::LTC2991() {
lrdawg99 2:c9e727dcd00e 77 lti2c = new LT_I2C();
lrdawg99 2:c9e727dcd00e 78 }
lrdawg99 2:c9e727dcd00e 79
lrdawg99 5:8aa0f4e6788c 80 LTC2991::LTC2991(PinName i2c_sda_, PinName i2c_scl_) {
lrdawg99 4:85017622b676 81 lti2c = new LT_I2C(i2c_sda_, i2c_scl_);
lrdawg99 2:c9e727dcd00e 82 }
lrdawg99 0:1473318f27b6 83
lrdawg99 0:1473318f27b6 84 // Reads a 14-bit adc_code from LTC2991.
lrdawg99 2:c9e727dcd00e 85 int8_t LTC2991::LTC2991_adc_read(uint8_t i2c_address, uint8_t msb_register_address, int16_t *adc_code, int8_t *data_valid)
lrdawg99 0:1473318f27b6 86 {
lrdawg99 0:1473318f27b6 87 int8_t ack = 0;
lrdawg99 0:1473318f27b6 88 uint16_t code;
lrdawg99 2:c9e727dcd00e 89 ack = lti2c->i2c_read_word_data(i2c_address, msb_register_address, &code);
lrdawg99 1:4e4194db7cd6 90
lrdawg99 0:1473318f27b6 91
lrdawg99 0:1473318f27b6 92 *data_valid = (code >> 15) & 0x01; // Place Data Valid Bit in *data_valid
lrdawg99 0:1473318f27b6 93
lrdawg99 0:1473318f27b6 94 *adc_code = code & 0x7FFF; // Removes data valid bit to return proper adc_code value
lrdawg99 1:4e4194db7cd6 95
lrdawg99 1:4e4194db7cd6 96 //pc2.printf("i2c_read_word_data result: raw code: %0x%X, ack %d\n", code, ack);
lrdawg99 0:1473318f27b6 97
lrdawg99 0:1473318f27b6 98 return(ack);
lrdawg99 0:1473318f27b6 99 }
lrdawg99 0:1473318f27b6 100
lrdawg99 0:1473318f27b6 101 // Reads a 14-bit adc_code from the LTC2991 but enforces a maximum timeout.
lrdawg99 0:1473318f27b6 102 // Similar to LTC2991_adc_read except it repeats until the data_valid bit is set, it fails to receive an I2C acknowledge, or the timeout (in milliseconds)
lrdawg99 0:1473318f27b6 103 // expires. It keeps trying to read from the LTC2991 every millisecond until the data_valid bit is set (indicating new data since the previous
lrdawg99 0:1473318f27b6 104 // time this register was read) or until it fails to receive an I2C acknowledge (indicating an error on the I2C bus).
lrdawg99 2:c9e727dcd00e 105 int8_t LTC2991::LTC2991_adc_read_timeout(uint8_t i2c_address, uint8_t msb_register_address, int16_t *adc_code, int8_t *data_valid, uint16_t timeout, uint8_t status_bit)
lrdawg99 0:1473318f27b6 106 {
lrdawg99 0:1473318f27b6 107 int8_t ack = 0;
lrdawg99 0:1473318f27b6 108 uint8_t reg_data;
lrdawg99 0:1473318f27b6 109 uint16_t timer_count; // Timer count for data_valid
lrdawg99 0:1473318f27b6 110
bdk9 8:c0ae66611a12 111 for (timer_count = 0; timer_count < 2000; timer_count++)
lrdawg99 0:1473318f27b6 112 {
lrdawg99 1:4e4194db7cd6 113 //pc2.printf("status_bit: %d\n", status_bit);
lrdawg99 1:4e4194db7cd6 114
lrdawg99 0:1473318f27b6 115 if (status_bit<8)
lrdawg99 0:1473318f27b6 116 {
lrdawg99 0:1473318f27b6 117 ack |= LTC2991_register_read(i2c_address, LTC2991_STATUS_LOW_REG, &reg_data); //! 1)Read status register until correct data valid bit is set
lrdawg99 0:1473318f27b6 118 }
lrdawg99 0:1473318f27b6 119 else
lrdawg99 0:1473318f27b6 120 {
lrdawg99 0:1473318f27b6 121 ack |= LTC2991_register_read(i2c_address, LTC2991_STATUS_HIGH_REG, &reg_data); //! 1)Read status register until correct data valid bit is set
lrdawg99 0:1473318f27b6 122 if (status_bit==8)
lrdawg99 0:1473318f27b6 123 {
lrdawg99 0:1473318f27b6 124 status_bit =1;
lrdawg99 0:1473318f27b6 125 }
lrdawg99 0:1473318f27b6 126 else
lrdawg99 0:1473318f27b6 127 {
lrdawg99 0:1473318f27b6 128 status_bit = 0;
lrdawg99 0:1473318f27b6 129 }
lrdawg99 0:1473318f27b6 130 }
lrdawg99 1:4e4194db7cd6 131
lrdawg99 0:1473318f27b6 132 if ((ack) || (((reg_data>>status_bit)&0x1)==1))
lrdawg99 0:1473318f27b6 133 {
lrdawg99 0:1473318f27b6 134 break;
lrdawg99 0:1473318f27b6 135 }
lrdawg99 0:1473318f27b6 136
bdk9 8:c0ae66611a12 137 wait_us(50);
lrdawg99 0:1473318f27b6 138 }
lrdawg99 0:1473318f27b6 139
lrdawg99 0:1473318f27b6 140 ack |= LTC2991_adc_read(i2c_address, msb_register_address, &(*adc_code), &(*data_valid)); //! 2) It's either valid or it's timed out, we read anyways
lrdawg99 0:1473318f27b6 141 if (*data_valid !=1)
lrdawg99 0:1473318f27b6 142 {
bdk9 8:c0ae66611a12 143 //pc2.printf("Data not valid: 0x%X\n", *data_valid);
lrdawg99 0:1473318f27b6 144 return (1);
lrdawg99 0:1473318f27b6 145 }
lrdawg99 1:4e4194db7cd6 146
lrdawg99 0:1473318f27b6 147 return(ack);
lrdawg99 0:1473318f27b6 148 }
lrdawg99 0:1473318f27b6 149
lrdawg99 0:1473318f27b6 150 // Reads new data (even after a mode change) by flushing old data and waiting for the data_valid bit to be set.
lrdawg99 0:1473318f27b6 151 // This function simplifies adc reads when modes are changing. For example, if V1-V2 changes from temperature mode
lrdawg99 0:1473318f27b6 152 // to differential voltage mode, the data in the register may still correspond to the temperature reading immediately
lrdawg99 0:1473318f27b6 153 // after the mode change. Flushing one reading and waiting for a new reading guarantees fresh data is received.
lrdawg99 0:1473318f27b6 154 // If the timeout is reached without valid data (*data_valid=1) the function exits.
lrdawg99 2:c9e727dcd00e 155 int8_t LTC2991::LTC2991_adc_read_new_data(uint8_t i2c_address, uint8_t msb_register_address, int16_t *adc_code, int8_t *data_valid, uint16_t timeout)
lrdawg99 0:1473318f27b6 156 {
lrdawg99 0:1473318f27b6 157 int8_t ack = 0;
lrdawg99 0:1473318f27b6 158
lrdawg99 0:1473318f27b6 159 ack |= LTC2991_adc_read_timeout(i2c_address, msb_register_address, &(*adc_code), &(*data_valid), timeout, ((msb_register_address/2) - 0x05)); //! 1) Throw away old data
lrdawg99 0:1473318f27b6 160 ack |= LTC2991_adc_read_timeout(i2c_address, msb_register_address, &(*adc_code), &(*data_valid), timeout, ((msb_register_address/2) - 0x05)); //! 2) Read new data
lrdawg99 0:1473318f27b6 161
lrdawg99 0:1473318f27b6 162 return(ack);
lrdawg99 0:1473318f27b6 163 }
lrdawg99 0:1473318f27b6 164
lrdawg99 0:1473318f27b6 165 // Reads an 8-bit register from the LTC2991 using the standard repeated start format.
lrdawg99 2:c9e727dcd00e 166 int8_t LTC2991::LTC2991_register_read(uint8_t i2c_address, uint8_t register_address, uint8_t *register_data)
lrdawg99 0:1473318f27b6 167 {
lrdawg99 0:1473318f27b6 168 int8_t ack = 0;
lrdawg99 2:c9e727dcd00e 169 ack = lti2c->i2c_read_byte_data(i2c_address, register_address, register_data);
lrdawg99 0:1473318f27b6 170 return(ack);
lrdawg99 0:1473318f27b6 171 }
lrdawg99 0:1473318f27b6 172
lrdawg99 0:1473318f27b6 173 // Write one byte to an LTC2991 register.
lrdawg99 0:1473318f27b6 174 // Writes to an 8-bit register inside the LTC2991 using the standard I2C repeated start format.
lrdawg99 2:c9e727dcd00e 175 int8_t LTC2991::LTC2991_register_write(uint8_t i2c_address, uint8_t register_address, uint8_t register_data)
lrdawg99 0:1473318f27b6 176 {
lrdawg99 0:1473318f27b6 177 int8_t ack = 0;
lrdawg99 2:c9e727dcd00e 178 ack = lti2c->i2c_write_byte_data(i2c_address, register_address, register_data);
lrdawg99 0:1473318f27b6 179 return(ack);
lrdawg99 0:1473318f27b6 180 }
lrdawg99 0:1473318f27b6 181
lrdawg99 0:1473318f27b6 182 // Used to set and clear bits in a control register. bits_to_set will be bitwise OR'd with the register.
lrdawg99 0:1473318f27b6 183 // bits_to_clear will be inverted and bitwise AND'd with the register so that every location with a 1 will result in a 0 in the register.
lrdawg99 2:c9e727dcd00e 184 int8_t LTC2991::LTC2991_register_set_clear_bits(uint8_t i2c_address, uint8_t register_address, uint8_t bits_to_set, uint8_t bits_to_clear)
lrdawg99 0:1473318f27b6 185 {
lrdawg99 0:1473318f27b6 186 uint8_t register_data;
lrdawg99 0:1473318f27b6 187 int8_t ack = 0;
lrdawg99 0:1473318f27b6 188
lrdawg99 0:1473318f27b6 189 ack |= LTC2991_register_read(i2c_address, register_address, &register_data); //! 1) Read register
lrdawg99 0:1473318f27b6 190 register_data = register_data & (~bits_to_clear); //! 2) Clear bits that were set to be cleared
lrdawg99 0:1473318f27b6 191 register_data = register_data | bits_to_set;
lrdawg99 0:1473318f27b6 192 ack |= LTC2991_register_write(i2c_address, register_address, register_data); //! 3) Write to register with the cleared bits
lrdawg99 0:1473318f27b6 193 return(ack);
lrdawg99 0:1473318f27b6 194 }
lrdawg99 0:1473318f27b6 195
lrdawg99 0:1473318f27b6 196 // Calculates the LTC2991 single-ended input voltages
lrdawg99 2:c9e727dcd00e 197 float LTC2991::LTC2991_code_to_single_ended_voltage(int16_t adc_code, float LTC2991_single_ended_lsb)
lrdawg99 0:1473318f27b6 198 {
lrdawg99 0:1473318f27b6 199 float voltage;
lrdawg99 0:1473318f27b6 200 int16_t sign = 1;
lrdawg99 0:1473318f27b6 201 if (adc_code >> 14)
lrdawg99 0:1473318f27b6 202 {
lrdawg99 0:1473318f27b6 203 adc_code = (adc_code ^ 0x7FFF) + 1; //! 1) Converts two's complement to binary
lrdawg99 0:1473318f27b6 204 sign = -1;
lrdawg99 0:1473318f27b6 205 }
lrdawg99 0:1473318f27b6 206 adc_code = (adc_code & 0x3FFF);
lrdawg99 0:1473318f27b6 207 voltage = ((float) adc_code) * LTC2991_single_ended_lsb * sign; //! 2) Convert code to voltage from lsb
lrdawg99 0:1473318f27b6 208 return (voltage);
lrdawg99 0:1473318f27b6 209 }
lrdawg99 0:1473318f27b6 210
lrdawg99 0:1473318f27b6 211 // Calculates the LTC2991 Vcc voltage
lrdawg99 2:c9e727dcd00e 212 float LTC2991::LTC2991_code_to_vcc_voltage(int16_t adc_code, float LTC2991_single_ended_lsb)
lrdawg99 0:1473318f27b6 213 {
lrdawg99 0:1473318f27b6 214 float voltage;
lrdawg99 0:1473318f27b6 215 int16_t sign = 1;
lrdawg99 0:1473318f27b6 216 if (adc_code >> 14)
lrdawg99 0:1473318f27b6 217 {
lrdawg99 0:1473318f27b6 218 adc_code = (adc_code ^ 0x7FFF) + 1; //! 1) Converts two's complement to binary
lrdawg99 0:1473318f27b6 219 sign = -1;
lrdawg99 0:1473318f27b6 220 }
lrdawg99 0:1473318f27b6 221
lrdawg99 0:1473318f27b6 222 voltage = (((float) adc_code) * LTC2991_single_ended_lsb * sign) + 2.5; //! 2) Convert code to Vcc Voltage from single-ended lsb
lrdawg99 0:1473318f27b6 223 return (voltage);
lrdawg99 0:1473318f27b6 224 }
lrdawg99 0:1473318f27b6 225
lrdawg99 0:1473318f27b6 226 // Calculates the LTC2991 differential input voltage.
lrdawg99 2:c9e727dcd00e 227 float LTC2991::LTC2991_code_to_differential_voltage(int16_t adc_code, float LTC2991_differential_lsb)
lrdawg99 0:1473318f27b6 228 {
lrdawg99 0:1473318f27b6 229 float voltage;
lrdawg99 0:1473318f27b6 230 int16_t sign = 1;
lrdawg99 0:1473318f27b6 231 if (adc_code >> 14)
lrdawg99 0:1473318f27b6 232 {
lrdawg99 0:1473318f27b6 233 adc_code = (adc_code ^ 0x7FFF) + 1; //! 1)Converts two's complement to binary
lrdawg99 0:1473318f27b6 234 sign = -1;
lrdawg99 0:1473318f27b6 235 }
lrdawg99 0:1473318f27b6 236 voltage = ((float) adc_code) * LTC2991_differential_lsb * sign; //! 2) Convert code to voltage form differential lsb
lrdawg99 0:1473318f27b6 237 return (voltage);
lrdawg99 0:1473318f27b6 238 }
lrdawg99 0:1473318f27b6 239
lrdawg99 0:1473318f27b6 240 // Calculates the LTC2991 temperature
lrdawg99 2:c9e727dcd00e 241 float LTC2991::LTC2991_temperature(int16_t adc_code, float LTC2991_temperature_lsb, boolean unit)
lrdawg99 0:1473318f27b6 242 {
lrdawg99 0:1473318f27b6 243 float temperature;
lrdawg99 0:1473318f27b6 244 adc_code = (adc_code & 0x1FFF); //! 1) Removes first 3 bits
lrdawg99 0:1473318f27b6 245 if (!unit) //! 2)Checks to see if it's Kelvin
lrdawg99 0:1473318f27b6 246 {
lrdawg99 0:1473318f27b6 247 if (adc_code >>12)
lrdawg99 0:1473318f27b6 248 {
lrdawg99 0:1473318f27b6 249 adc_code = (adc_code | 0xE000); //! Sign extend if it's not Kelvin (Celsius)
lrdawg99 0:1473318f27b6 250 }
lrdawg99 0:1473318f27b6 251 }
lrdawg99 0:1473318f27b6 252 temperature = ((float) adc_code) * LTC2991_temperature_lsb; //! 3) Converts code to temperature from temperature lsb
lrdawg99 0:1473318f27b6 253
lrdawg99 0:1473318f27b6 254 return (temperature);
lrdawg99 0:1473318f27b6 255 }
lrdawg99 0:1473318f27b6 256
lrdawg99 0:1473318f27b6 257 // Calculates the LTC2991 diode voltage
lrdawg99 2:c9e727dcd00e 258 float LTC2991::LTC2991_code_to_diode_voltage(int16_t adc_code, float LTC2991_diode_voltage_lsb)
lrdawg99 0:1473318f27b6 259 {
lrdawg99 0:1473318f27b6 260 float voltage;
lrdawg99 0:1473318f27b6 261 adc_code = (adc_code & 0x1FFF); //! 1) Removes first 3 bits
lrdawg99 0:1473318f27b6 262 voltage = ((float) adc_code) * LTC2991_diode_voltage_lsb; //! 2) Convert code to voltage from diode voltage lsb
lrdawg99 0:1473318f27b6 263 return (voltage);
lrdawg99 0:1473318f27b6 264 }