This is the TMP116 a high accuracy, low power digital temperature sensor with SMBus and i2c interface from Texas Instruments. This device runs on low power in a high precision temperature sensor with integrated memory. The TMP116 features a 16bit temperature result with a resolution of 0.0078 degree Celsius and an accuracy of up to -0.2 / +0.2 degree Celsius with no calibration. This device runs on i2C and SMBus-interface, it has programmable alert functionality and can support up to four devices on a single bus.
The TMP116 consumes minimal current that can provide a power saving option minimize self-heating and improves measurement accuracy. The TMP116 operates from 1.9v to 5.5v and typically consumes 3.5 uA. Across the device operating temperature range of -55 degree Celsius to 125 degree Celsius the TMP116 exceeds the accuracy of a class A RTD while consuming less than 1-5th of the typical excitation current for a PT100 RTD.
The TMP116 is easier to use than RTDs calibration is not required, external circuitry, matched traces and kelvin connections. This device is suitable for used in environmental monitoring/ thermostats, Environmental Air Temperature Monitoring, wearable devices, asset tracking/cold chain, gas meters and heat meters, test measurement, and cold junction compensation of thermocouple. For further reading please refer to the datasheet.
Required Components
- Arduino IDE | Atmel Studio | Energia
- Microcontroller – Arduino, NodeMCU, Teensy Board, TeensyDuino, ESP8266 12, 12E, ESP32, LinkItOne, ESP8266 NodeMCU, ESPDuino, ATMEGA328 16/12, ATMEGA32u4 16/8/ MHz, ESP8266, MSP430 ,ATMEGA250 16 MHz, ATSAM3x8E, ATSAM21D, ATTINY85 16/8 MHz Note: The Diagram below is using NANO. (please refer to each MCU’s respective pin-outs & bus configurations)
- Texas Instruments TMP116/TMP116N Digital Temperature Sensor (see below diagram)
- Capacitors (See below required values)
- Resistors (See below required values)
- Jumper Wire (Optional)
- Prototyping Board
- PCB board
Wiring Guide
Source Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
/* TEST CODE FOR TI TMP116 > Credit to Jan Stegenga 2017 * Sample code for reading out a Texas Instruments TMP116(N). * The code simply puts a device in periodic/alarm mode. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <Wire.h> #include <arduino.h> #include <SoftwareSerial.h> const byte RXPin = 2; const byte TXPin = 3; SoftwareSerial doSerial (RXPin, TXPin); /* Wiring 4 device uint8_t addrGND = 0x48; // 1001000 uint8_t addrVCC = 0x49; // 1001001 uint8_t addrSDA = 0x4A; // 1001010 -> ADD0 pin connected to SDA uint8_t addrSCL = 0x4B; // 1001011 uint8_t tempAddr = addrSDA; uint8_t addrGND = 0x48; // 1001000 uint8_t addrVCC = 0x49; // 1001001 -> ADD0 pin connected to VCC uint8_t addrSDA = 0x4A; // 1001010 uint8_t addrSCL = 0x4B; // 1001011 uint8_t tempAddr = addrVCC; uint8_t addrGND = 0x48; // 1001000 uint8_t addrVCC = 0x49; // 1001001 uint8_t addrSDA = 0x4A; // 1001010 uint8_t addrSCL = 0x4B; // 1001011 -> ADD0 pin connected to SCL uint8_t tempAddr = addrSCL; */ uint8_t addrGND = 0x48; // 1001000 -> Seven bit addresses with ADD0 pin connected to GND uint8_t addrVCC = 0x49; // 1001001 uint8_t addrSDA = 0x4A; // 1001010 uint8_t addrSCL = 0x4B; // 1001011 uint8_t tempAddr = addrGND; uint8_t Reg_T = 0x00; // register addresses for the commonly used ones uint8_t Reg_C = 0x01; uint8_t Reg_HL = 0x02; uint8_t Reg_LL = 0x03; uint8_t Reg_ID = 0x0F; // device ID uint8_t Reg_current = 0x00; // keep track of the current register pointer uint8_t mode = 2; // MOD 0: continuous conversion, 1: shutdown, 2: continuous conversion, 3: one-shot uint8_t conv = 4; // CONV 0: afap, 1: 0.125s, 2: 0.250s, 3: 0.500s, 4: 1s, 5: 4s, 6: 8s, 7: 16s uint8_t avg = 0; // AVG 0: no_avg (15.5ms), 1: 8 avg(125ms), 2: 32 avg(500ms), 3: 64 avg(1000ms) uint8_t flags = 0; // FLAGS : last three bits representing: [2: hi alert, 1: lo alert, 0: data ready] /* * sets the register pointer if necessary * returns 0 if successful */ byte SetPointer( uint8_t reg ) { if( Reg_current != reg ) { Wire.beginTransmission(tempAddr); uint8_t bytes_written = Wire.write( reg ); byte return_code = Wire.endTransmission(); //doSerial.println( "bytes written " + String( bytes_written ) + " to " + String( tempAddr, BIN ) + " with return code " + String( return_code ) ); Reg_current = reg; return return_code; } } /* * reads a T, HL or LL register * returns a float with the converted value */ float ReadRegister( uint8_t reg ){ SetPointer( reg ); uint8_t bytes_returned = Wire.requestFrom( tempAddr, 2 ); //doSerial.println( "Read " + String( bytes_returned ) + " from register " + String( reg ) ); if( bytes_returned == 2){ uint8_t c[bytes_returned]; for( int i=0; i<bytes_returned; i++ ) { // slave may send less than requested{ c[i] = Wire.read(); //doSerial.println( "\t" + String( c[i], BIN ) + "\t" + String( c[i], DEC ) ); } return float( c[0]*256 + c[1] )*0.0078125; } return bytes_returned == 2; } /* * sets a HL or LL register * returns 0 if successful */ byte SetRegister( uint8_t reg, float value ){ //set control register-> addr+0, register address, value(s) int16_t val = (int16_t) ( value/0.0078125 ); doSerial.println( String(value) + " converted to: " + String( val, BIN ) ); byte data[3]; data[0] = reg; data[1] = (byte) ( val >> 8 ) & 0xFF; data[2] = (byte) val & 0xFF; doSerial.println( "Setting " + String( reg ) + " register with " + String( data[1], BIN ) + String( data[2], BIN ) ); Wire.beginTransmission(tempAddr); uint8_t bytes_written = Wire.write( data, 3 ); byte return_code = Wire.endTransmission(); doSerial.println( "bytes written " + String( bytes_written ) + " to register " + String( reg, BIN ) + " with return code " + String( return_code ) ); Reg_current = reg; return return_code; } /* * Sets the control register * MOD 0: continuous conversion, 1: shutdown, 2: continuous conversion, 3: one-shot * CONV 0: afap, 1: 0.125s, 2: 0.250s, 3: 0.500s, 4: 1s, 5: 4s, 6: 8s, 7: 16s * AVG 0: no_avg (15.5ms), 1: 8 avg(125ms), 2: 32 avg(500ms), 3: 64 avg(1000ms) * returns 0 if successful */ byte SetControlRegister( uint8_t MOD, uint8_t CONV, uint8_t AVG ){ uint16_t c_reg = 0x00; //doSerial.println( "MOD bits: " + String( ( MOD & 0x03 ) << 10, BIN ) ); c_reg = c_reg | ( MOD & 0x03 ) << 10; //2 bits of mod go to position 11:10 c_reg = c_reg | ( CONV & 0x07 ) << 7; //3 of conv go to 9:7 c_reg = c_reg | ( AVG & 0x03 ) << 5; //2 of AVG go to 6:5 c_reg = c_reg | 1 << 3; //always in make alert pin active high //set control register-> addr+0, register address, value(s) uint8_t data[3]; data[0] = Reg_C; data[1] = uint8_t( c_reg >> 8 ); data[2] = uint8_t( c_reg && 0xF ); Wire.beginTransmission( tempAddr ); uint8_t bytes_written = Wire.write( data, 3 ); byte return_code = Wire.endTransmission(); doSerial.println( "Writing control register with: " + String( c_reg , BIN ) ); doSerial.println( "bytes written " + String( bytes_written ) + " to register " + String( Reg_C, BIN ) + " with return code " + String( return_code ) ); Reg_current = Reg_C; return return_code; } /* * reads the control register * FLAGS: uint8_t with last three bits representing: [2: hi alert, 1: lo alert, 0: data ready] * returns 0 if successful */ byte ReadControlRegister( uint8_t *MOD, uint8_t *CONV, uint8_t *AVG, uint8_t *FLAGS ){ SetPointer( Reg_C ); byte bytes_returned = Wire.requestFrom( tempAddr, 2 ); //DEBUGING //doSerial.println( "Read " + String( bytes_returned ) + " from register " + String( Reg_C ) ); if( bytes_returned == 2){ uint8_t c[bytes_returned]; for( int i=0; i<bytes_returned; i++ ) { // slave may send less than requested{ c[i] = Wire.read(); //DEBUGING //doSerial.println( "\t" + String( c[i], BIN ) ); } uint16_t c_reg = uint16_t( c[0] ) << 8 | c[0] ; //doSerial.println( c_reg, BIN ); *FLAGS = ( c_reg >> 13 ) & 0x07; *MOD = ( c_reg >> 10 ) & 0x03; *CONV = ( c_reg >> 7 ) & 0x07; *AVG = ( c_reg >> 5 ) & 0x03; } return bytes_returned == 2; } void setup() { doSerial.begin(115200); Wire.begin(); delay(3000); doSerial.println( "start program" ); SetRegister( Reg_HL, 29.25 ); SetRegister( Reg_LL, 19.00 ); if( SetControlRegister( mode, conv, avg ) ){ doSerial.println( "Control Register Set" ); } } void loop() { // put your main code here, to run repeatedly: ReadControlRegister( &mode, &conv, &avg, &flags ); // DEBUGING // doSerial.println( "mode: " + String( mode ) ); // doSerial.println( "conv: " + String( conv ) ); // doSerial.println( "avg: " + String( avg ) ); // doSerial.println( "flags: " + String( flags) ); // DEBUGING if( (flags >> 2) & 0x01 ) { doSerial.println( "ALERT HIGH" ); } if( (flags >> 1) & 0x01 ){ doSerial.println( "ALERT LOW" ); } if( flags & 0x01 ){ //data ready doSerial.println( String( millis()/1000 ) + "\ttemperature: \t" + String( ReadRegister( Reg_T ) ) ); } delay( 100 ); } |
Downloads
- Download TI TMP116 Air Temperature Monitoring User Guide
- Download TI TMP116 Datasheet
- Download TI TMP116 PCB Mounting User Guide