Bus Pirate v3 and LM75 temperature sensors

This is a tiny reference for reading the temperature with an LM75a temperature sensor and a Bus Pirate v3 on a Linux computer.

What is a Bus Pirate

The Bus Pirate is a "hacker multi-tool" developed by Dangerous Prototypes. The tool is basically an interface between your computer and a lot of standard communication busses like: spi, i2c, 1-wire, JTAG, uart, midi and ps2-keyboard. It also has a frequency counter (1Hz - 40Mhz) and generator (1kHz - 4Mhz), a low speed logic analyzer (10Hz - 1Mhz) and a lot more. You can read more about this on the features page

What is an LM75

The LM75 is a small temperature measurement chip mostly used inside computers. The Linux tool lm-sensors has built-in support for LM75 temperature sensors connected to an i2c bus supported by Linux. This makes it possible to connect the LM75 temperature sensor to a usb to i2c bridge and connect environment temperature sensors to Linux and use it to control internal and external fans.

The product page for this chip lists the accuracy as 2°c and the accurate range as -25°c - 100°c. Whats unlisted is that the precision of the chip is 0.125°c so if you calibrate the chip with a good thermometer you can measure the temperature in way smaller steps.

Connecting the sensor

The sensor is in a small package so I used a breakout board for easier connecting.

My connections:

Bus Pirate | LM75 | Name
-------------------------------------------
red        | VCC  | Bus Pirate +3.3V source
green      | VCC  | Bus Pirate pull-up voltage
brown      | GND  | Ground
grey       | SDA  | i2c data line
purple     | SCL  | i2c clock line

The exact pins on your LM75 depend on the package. Check the datasheet

Firing up the Bus Pirate

After you connect the Bus Pirate to the computer there should be a new ttyUSB device available. (check this with the dmesg command). The easiest way to use the Bus Pirate is to connect to it with screen. To do this run the following command:

$ screen /dev/ttyUSB0 115200
# if you get a permission issue try:
$ sudo screen /dev/ttyUSB0 115200

After connecting press enter and the Bus Pirate prompt should appear (HiZ>). This prompt means its currently in HiZ mode. To switch the mode press m and press enter. Then enter 4 (i2c). Then it asks for the speed. The LM75a can operate on any i2c speed up to 400Khz so choose any.

After switching to i2c mode the prompt is changed to I2C> now you need to enable the power supply and the pull-up resistors.

I2C>W
Power supplies ON
I2C>P
Pull-up resistors ON
I2C>

Now all the communications are initialized. The next command is dependend on the address of your LM75 chip. The address is set with the 3 address pins. if all address pins are grounded the address is 0x48. The Bus Pirate has a handy macro for finding all i2c slaves on the connected bus. Enter (1), something like this should appear:

I2C>(1)
Searching I2C address space. Found devices at:
0x92(0x49 W) 0x93(0x49 R)

This means that my LM75 is on the address 0x49 and it lists the send and receive address. To get the current temperature enter the following command:

I2C>[0x93 rr]
I2C START BIT
WRITE: 0x93 ACK
READ: 0x12
READ:  ACK 0x20
NACK
I2C STOP BIT
I2C>

This makes it write 0x93 to the bus (The read address of the LM75) and read 2 bytes. The two received bytes are 0x12 and 0x20. The most significant byte is sent first so that makes for a temperature of 0x1220 or 4622 in decimal. To get the real temperature divide this number by 255 and round to the nearest 0.125. This makes the read temperature 18.125°c

Automatic reading

The Bus Pirate has a nice python api for automating communication calledpyBusPirateLite. To read the temperature from my sensor I modified the thermometer.pyscript and created lm75.py.



#!/usr/bin/env python
import sys
from pyBusPirateLite.I2Chigh import *

class LM75:
    def __init__(self, i2c, address=0x48):
        self.i2c = i2c;
        self.address = address;

    def get_temp_reg(self, reg):
        temp = self.i2c.get_word(self.address, reg);
        if temp < 32768:
            return temp/256.0;
        else:
            return (temp-65536)/256.0;

    def get_temp(self):
        return self.get_temp_reg(0x00);

if __name__ == '__main__':
    try:
        # Serial timeout five seconds for debugging mistakes in I2C class
        i2c = I2Chigh("/dev/ttyUSB0", 115200, 5)
    except Exception, e:
        print "Error",e
        sys.exit()

    i2c.BBmode()
    i2c.enter_I2C()

    if not i2c.cfg_pins(I2CPins.POWER | I2CPins.PULLUPS):
        print "Failed to set I2C peripherals."
        sys.exit()
    if not i2c.set_speed(I2CSpeed._100KHZ):
        print "Failed to set I2C Speed."
        sys.exit()
    i2c.timeout(0.2)

    lm75 = LM75(i2c, int(sys.argv[1], base=16))
    print lm75.get_temp()

Run this command with the address of your LM75 sensor and you should get the current temperature

# Read from LM75 on address 0x49
$ ./lm75.py 49
18.125