19 April 2008

11. It's hot in here

I think now’s the time to start interacting with other devices – and the one we’re going to start with will tell us what the temperature is. It’s a great opportunity to learn about the i2c protocol, how to interface with other devices and what a decimal place really means.

The chip of our choosing is the LM75, which like most of these sort of devices has many compatible versions from many manufacturers. Grab hold of a copy of the datasheet for this guy. You’ll notice that it’s an 8 pin device. 3 pins define the address of the device – so you can have up to 8 all connected together and yet address them individually. It has two modes, “shutdown” and “normal”, where shutdown mode will put the device into a low power sleep mode, and normal mode will convert the temperature every 100ms. It has two registers that we care about, the config register and the temperature register. The 8 bit config register is, naturally, where the config bits are stored. The 16 bit temperature register is where the temperature gets put every 100ms. The datasheet specifies that you can read the temperature safely at any time without any fear that it will be corrupted by another temperature measurement while you’re actually getting the register sent to you.

The LM75 uses a protocol called “i2c”, although it’s actually I “squared” C and stands for inter intergrated circuit. I write it without the superscript “2”. You might also see referred to as IIC and some chips use it without referring to this name at all. Presumably their lawyers told them to keep quiet. In any case, it’s a very neat way of communicating bi-directionally with different devices with only signal two wires. You can have several devices on the “buss” and distinguish between them. It even has modes where there can be several devices making requests (acting as the “master” in i2c speak), however, personally I think this is reasonably unlikely to happen in practice. The devices you make requests upon, in our case the LM75, are said to be in “slave” mode. They just do as they’re told.

Now, most pics that you’ll come across have some sort of i2c hardware inbuilt. This means they can handle a lot of the hard work themselves. The unfortunate fact is that mostly this is only as a slave and not as a master. To be fair, it’s pretty easy to implement master mode in firmware and you don’t get a lot of advantages out of doing it in hardware (presumably some code space). In any case, looking at the software implementation gives you a chance to understand how the protocol really works.

My intention here is not to cover the i2c protocol itself – there are tonnes of stuff on the net about this, and an excellent article in a recent edition of the excellent Silicon Chip magazine. If you’re into electronics at all, go subscribe to this magazine and support the Australian economy.

What I do want to cover is the use of the picpack library, which as you would expect by now, implements enough of the i2c protocol to get you talking with your LM75 or other i2c device but keeps you protected from any read-before-write problems on 16f devices. Once you have the “temperature” data in your hand, it’s also interesting to see what needs to be done to turn it into something worth displaying – and what that really means.

Open up the lm75 demo in the demos directory and have a look. You’ll see that since the lm75 library is built on top of the i2c library, you need to include the i2c.c file in your project as well. Have a look at the config.h:


// - - - - - - - - - - - - - - - - - - - -
// pic_serial defines
// - - - - - - - - - - - - - - - - - - - -
#define SERIAL_TX_BUFFER_SIZE 16
#define SERIAL_RX_BUFFER_SIZE 4
//#define SERIAL_DEBUG_ON
// - - - - - - - - - - - - - - - - - - - -
// pic i2c defines
// - - - - - - - - - - - - - - - - - - - -
#define i2c_scl_port PORTC
#define i2c_sda_port PORTC
#define i2c_scl_pin 3
#define i2c_sda_pin 4
// - - - - - - - - - - - - - - -
// General platform definitions
// - - - - - - - - - - - - - - -
#define PLATFORM_TYPE SURE_PICDEM_2
#define PLATFORM_CLOCK 12000000



There’s the usual serial defines at the top, followed by the i2c defines. In this case, the project is ready to go on the Sure electronics Picdem 2 board – a great board for getting into 18f chips, LCD and temperature. We’ll talk about prototyping boards a little later on. Don’t forget to set your platform clock correctly, both for the serial communications and also for the delays used by the i2c routines.

Pack in lm75_demo.c, notice that getting the lm75 talking is as simple as:


lm75_setup();
lm75_set_config(LM75_ADDRESS, LM75_NORMAL);


Remember that each lm75 has its own address – the LM75_ADDRESS define is at the top of the file. Make sure you match it correctly to the LM75 address you set on your hardware (the Sure picdem2 board has it set to zero). In lm75_setup() the ports and pins are set up to communicate hardware-wise with the device. lm75_set_config sets the config register to the normal mode (ie, not shutdown). This isn’t really necessary since this is the default state, but hey, it’s a demo and we need to demo something!

The serial communication parts of the program are set up to read the temperature when you press t and , and read the config register when you press c and . Reading the config register is pretty boring, but it does prove it works. Reading
the temperature is a little more interesting.

To read the temperature all you need to do is call:


raw_temp = lm75_get_temp(LM75_ADDRESS);



The LM75 gives you an 11 bit temperature reading via a 16 bit number. The first 8 bits are the integer part, the following 3 bits are the “decimal” part. So we have three “bits” of decimal resolution. That means each bit represents a value of 0.125. If we take the second set of 8 bit, rotate it left by 5 bits, we’ll end up with those 3 bits right aligned in the byte. That makes it easier to process. So, if the left-most byte is 25, and the right most byte (after shifting) is 3, then the reading is 25.375. Now, that sounds like a pretty precise reading. What I haven’t mentioned until now is that according to the datasheet, the LM75 is accurate +/- 2 degrees C. So our reading could really be anywhere between 23.375 or 27.375. That’s pretty broad – and you start to realise that three bits of accuracy are pretty meaningless – especially when you convert them to base 10.

The lm75_demo.c includes two routines to convert the three bits to one or two base-10 decimal places through essentially a look up table. You can work our how I’ve calculated the values (multiplying 0.125 and then rounding). Note that given that we’ve only got 8 values available to us with three bits, you can’t even accurately represent 1 base-10 decimal place! Still, we’re just displaying the temperature here, so I’m not going to get hung up about it. The PicPack library includes support for the DS1307 chip, which has +/- 0.5 degree accuracy as 12 bit resolution, but we’ll be exploring that a little later.


PIC terminal
  <19:55:57>
Commands:
t - Request temp
c - Request config
t
>Requesting temp.
Raw temp = 0x1AE0
Temp = 26.88
Temp = 26.9
  >



The other aspect that I’ve left out of this demo as an exercise for the viewer is the fact we are blatantly ignoring negative readings. These are represented as twos complement numbers, about which there’s plenty of information on the web. If you come up with some cool routines to process negative numbers, send them in and we’ll include them in the library for everyone to use.

No comments: