Analog Devices make a couple of I²C temperature sensors with a precision of about 0.008̣°C, though rather worse accuracy:

The latter’s obviously a nicer part, but the former’s easier to buy and play with. The LFCSP package is a pain to solder by hand, but you can mount it dead-bug style.

ADT7410 ADT7420

Hardware

Happily the hardware here is trivially simple: we simply need to connect the chip to an I²C bus. We don’t even need to worry too much about voltage levels: both chips are happy with 2.7–5.5V supplies.

Besides the four wires required for power and the I²C bus, the only other pins we have to consider are A0 and A1, which set the sensor’s I²C address: 0x48 to 0x4b.

There are also a couple of outputs which signal outlandish temperatures: I’m ignoring those here.

Actually I am skating over important details. The I²C bus was originally designed for short-runs (I²C is a contraction of Inter IC), so if you want to put the sensor on the end of a long wire you really ought to think carefully about it.

If you want to do the job properly, it’s worth reading the specification3 from Philips (now NXP). Both the power and signal connections need thought, and if you just plonk the sensors on a bit of ribbon cable, it’s effectively an unterminated transmission line4 which implies we’ll see reflections.

However, in practice, I’ve found that a metre of ribbon cable works reliably without taking any precautions. In fact, I think the main problem with my laissez-faire attitude is that there’s noise on the supply rails, which presumably adds noise to the readings. Of course if the application were more important, I’d take more care.

Software

I wanted some software to read the temperatures from a Raspberry Pi. In principle, there’s a module for the Linux kernel which talks to the ADT74x0, but it’s not included in the stock Raspbian distribution and I think life’s too short to keep compiling kernel modules.

Instead I wrote a trivial little user space program which talks to the I²C device in /dev. You can grab the code from the adt74×0 repository on github5

The code is easy to compile:

$ gcc -O9 -std=c99 adt74x0.c -o adt74x0

It’s also easy to run:

$ ./adt74x0
# Scanning /dev/i2c-0 for ADT74x0...
0x4b 20.71094C

The code simply returns the address (here 0x4b) and temperature of all the ADT74x0 devices it finds on the bus.

The client assumes that you’re using /dev/i2c-0. If not, you’ll have to tell it where to look e.g.:

$ ./adt74x0 /dev/i2c-1
# Scanning /dev/i2c-1 for ADT74x0...
0x4b 20.71094C

You’ll need permission to access the device: popular ways to get this include using sudo or adding the user to the i2c group.

I²C buses I have known

It transpires that almost PCs have an external I²C bus on their monitor port. Most monitors send configuration data to the PC via I²C, and accordingly almost all VGA and DVI sockets sport an I²C bus. So, you could connect a sensor to this port, run the software above, and measure the temperature.

Obviously this is easier if there’s no monitor attached to the PC: ironically when I’ve wanted to do this in the past, it was to monitor the state of headless servers.

The Raspberry Pi

Sadly there’s a problem with the Raspberry Pi’s I²C device: it doesn’t like talking to ADT74x0s. I don’t think it’s just me, because it appears to have affected other people too.6

In practice I found that I could read the temperature reliably from single sensor on a short cable, but failed to read anything else e.g. the device’s ID code. Ever the temperature reading failed when more devices were added and the bus got longer.

Happily there’s an easy solution: instead of talking to the Linux I²C device, we can use Mike McCauley’s nice bcm2835 library.7

Note: if you’re using the I²C devices in /dev you need to stop blacklisting the i2c-dev module by editing /etc/modules. Conversely if you want to use Mike’s library, you’ll need to blacklist i2c-dev so that the ports are still free.

There’s a different client program, but it’s on github8 and easy to compile:

$ gcc -O9 -std=c99 adt74x0b.c -lbcm2835 -o adt74x0b

It’s a drop in replacement for the other version, but needs access to mmap the device:

$ sudo ./adt74x0b
0x4a 18.69531C
0x4b 20.59375C

The program also slows the I²C clock down to 10kHz (from 100kHz) to accomodate long cables and dodgy terminators.

Connections

SignalRaspberry Pi GPIO pin9VGA pin10
VDD1 (3.3V)9 (5V)
GND610
SDA312
SCL515

Results

I’ve had a ADT7410 logging the temperature at home every minute for a while now. Here’s a typical result: