Example Code for a TMP102 I2c Thermometer
I've fairly extensively commented the code, hopefully it makes sense.
Example code for talking to a TMP102 I2C thermometer,
like those available from Sparkfun, for example. Rather
heavily based on some code I found in the forums, some
samples, and a bit of personal investigation to make it all
work.
Based on my testing, the sensor overreads by around 5 degrees C at room temperature. Not too sure if it is a percentage or a constant error. I know some of the analogue sensors are prone to incorrect readings if the reference voltages are off, but as we're using a digital output, this shouldn't affect it.
Any ideas? Mention them here.
For those using the Sparkfun logic converters with I2C, here are the pin connections:
- Low voltage to the 3.3v pin of the Arduino
- High voltage to the 5.0v pin
- High voltage Channel 1 Txo to the SDA pin (analog 4)
- High voltage Channel 2 Txo to the SCL pin (analog 5)
- Low voltage Channel 1 Txi to the SDA pin of tmp102
- Low voltage Channel 2 Txi to the SCL pin of tmp102
- The RX pins of the logic converter are not used
- V+ of tmp102 connected to 3.3v
- ADD0 of tmp102 connected to ground
- ALT of tmp102 not connected
- All grounds connected together.
You can instead use resistors to voltage divide the signal lines, but I've not figured out how to do that yet.
#include "Wire.h"
#define TMP102_I2C_ADDRESS 72 /* This is the I2C address for our chip.
This value is correct if you tie the ADD0 pin to ground. See the datasheet for some other values. */
void setup() {
Wire.begin(); // start the I2C library
Serial.begin(115200); //Start serial communication at 115200 baud
}
void getTemp102(){
byte firstbyte, secondbyte; //these are the bytes we read from the TMP102 temperature registers
int val; /* an int is capable of storing two bytes, this is where we "chuck" the two bytes together. */
float convertedtemp; /* We then need to multiply our two bytes by a scaling factor, mentioned in the datasheet. */
float correctedtemp;
// The sensor overreads (?)
/* Reset the register pointer (by default it is ready to read temperatures)
You can alter it to a writeable register and alter some of the configuration -
the sensor is capable of alerting you if the temperature is above or below a specified threshold. */
Wire.beginTransmission(TMP102_I2C_ADDRESS); //Say hi to the sensor.
Wire.send(0x00);
Wire.endTransmission();
Wire.requestFrom(TMP102_I2C_ADDRESS, 2);
Wire.endTransmission();
firstbyte = (Wire.receive());
/*read the TMP102 datasheet - here we read one byte from
each of the temperature registers on the TMP102*/
secondbyte = (Wire.receive());
/*The first byte contains the most significant bits, and
the second the less significant */
val = ((firstbyte) << 4);
/* MSB */
val |= (secondbyte >> 4);
/* LSB is ORed into the second 4 bits of our byte.
Bitwise maths is a bit funky, but there's a good tutorial on the playground*/
convertedtemp = val*0.0625;
correctedtemp = convertedtemp - 5;
/* See the above note on overreading */
Serial.print("firstbyte is ");
Serial.print("\t");
Serial.println(firstbyte, BIN);
Serial.print("secondbyte is ");
Serial.print("\t");
Serial.println(secondbyte, BIN);
Serial.print("Concatenated byte is ");
Serial.print("\t");
Serial.println(val, BIN);
Serial.print("Converted temp is ");
Serial.print("\t");
Serial.println(val*0.0625);
Serial.print("Corrected temp is ");
Serial.print("\t");
Serial.println(correctedtemp);
Serial.println();
}
void loop() {
getTemp102();
delay(5000); //wait 5 seconds before printing our next set of readings.
}
Comments
Hello, thanks too for this code. I noticed that it does not work for negative temperatures now it is getting colder outside ;-) To my opinion the problem is in line 37. If the highest bit is 1 also the 4 highest bit of the integer have to be set. I replaced this line with:
val = firstbyte;
if ((firstbyte & 0x80) > 0) {
val |= 0x0F00;
}
val <<= 4;