Sunday, 23 September 2012

Raspberry PI Digital to Analogue Conversion (DAC)

In this tutorial I will be detailing how to generate analogue voltages using a Raspberry Pi and an external Digital to Analogue Converter (DAC) to control the brightness of an LED.
Although the Raspberry Pi can interface with various low-level hardware using it's GPIO lines, SPI, I2C and serial UART interface, it does not have an DAC interface for generating analogue voltage levels. Instead the user must use an external DAC device controlled by one of the available low-level hardware interfaces, such as SPI and I2C.
I will be using the MCP4725 I2C DAC Breakout board as described here to control the brightness of the LED.


You will need the following components to complete this tutorial:
  • A Raspberry Pi with internet access, keyboard, power supply, etc.
  • An SD card with Raspbian “wheezy”.
  • A mini breadboard (example here).
  • Some Male to Female jump wires (example here).
  • A Breakout Board for MCP4725 I2C DAC (example here). You will need to solder on some break away headers onto the breakout board so you can mount it on your breadboard.
  • A 200 ohm resistor (example here).
  • An LED (example here).
(Please note that I have no affiliation with Proto-Pic other than being a regular customer.)

MCP4725 I2C DAC Breakout Board
The datasheet for the MCP4725 can be found on Microchip's website here. Suffice it to say that the DAC has a single analog output that can drive up to 25mAmps. This will be sufficient to power our LED.
To configure the voltage output that appears on the ANALOGUE pin, the user must send the appropriate '12 bit DAC Input Data' value to the DAC over the I2C bus. The user can also set this value into the device's EEPROM (permanent storage) so that a particular output voltage will be automatically set when the DAC is powered on, otherwise the DAC defaults to 0Volts output at power on.

The following gives the equation for input data value/code and output voltage, in our case Vdd will be 3.3volts:
Input Code and Output Voltage
Configuring the MCP4725 DAC is slightly different to the likes of the TMP102 I2C device as it does not have a register (data address) that you specify.
Instead, you simply write the configuration to the device without specifying a register number.
We will be setting the output voltage using the 'Fast Mode' configuration, which means when the DAC is power cycled our value will be lost.

This 'Fast Mode' I2C command takes the following structure:
1st Byte (Standard I2C Device Addressing with write) 2nd Byte 3rd Bye
0x60
0x0Y
Where Y is the most significant 4 bits of our output voltage setting.
0xZZ
Where ZZ is the lower byte of our output voltage setting.

Circuit
So, we are going to connect our I2C device to the appropriate pins on the Pi's GPIO header:
Raspberry Pi GPIO Header MCP4725 Breakout board Description
Pin1/3V3 Vcc This will provide power and Vref to the MCP4725 device.
Pin6/Ground GND  Device power rail ground.
Pin3/SDA SDA Data line for the Pi's I2C interface 0.
Pin5/SCL SCL Clock line for the Pi's I2C interface 0

We then need to connect the LED to the ANALOGUE pin on the breakout board and put the 200 ohm resistor in series between the LED and ground.

Enabling I2C on your Raspberry Pi
Please follow my instructions here to enable I2C on your Raspberry Pi.
Verify you can see the DAC on bus zero using the i2cdetect command:

pi@raspberrypi ~ $ i2cdetect -y 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: 60 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --           

Here we can see our device at address 0x60.

Controlling the LED Brightness

We will use the linux i2cset command to configure the DAC output voltage and therefore the brightness of the LED:

Full brightness (3.3volts, 0xFFF input code):
pi@raspberrypi ~ $ i2cset -y 0 0x60 0x0f 0xff b

Low Brightness (1.86volts, 0x900 input code):
pi@raspberrypi ~ $ i2cset -y 0 0x60 0x09 0x00 b

Note we are not really using i2cset as it was designed. Looking at the man page for i2cset, the command takes the following basic form:
i2cset -y i2cbus chip-address data-address [value] ...  [mode]
We are using the data-address (register) field as the 2nd byte in the command and our third byte is the first [value] in the command. A little bit confusing, but important to be aware of.

Conclusion
So, in this tutorial we have shown how to setup and control the brightness of an LED using the Raspberry Pi's I2C bus and an external I2C DAC.

Thursday, 20 September 2012

Raspberry Pi I2C Tutorial

In this tutorial I will detail how to interface to an I2C device using your Raspberry Pi. Specifically we will be reading the temperature from an I2C based TMP102 breakout board. You won't need any programming skills to do this, just the ability to connect up the simple circuit to your Pi and be able to use the command line. It will help to have some understanding on how I2C buses work.

Disclaimer: I take absolutely no responsibility if you blow up your Raspberry Pi or anything else while following this tutorial. 





You will need the following:

  • A Raspberry Pi with internet access, keyboard, power supply, etc.
  • An SD card with Raspbian “wheezy”.
  • A mini breadboard (example here).
  • Some Male to Female jump wires (example here).
  • An I2C based TMP102 digital sensor breakout board (example here). You will need to solder on some break away headers onto the breakout board so you can mount it on your breadboard.
(Please note, I have no affiliation to Proto-Pic other than being a regular customer.)

TMP102 Breakout Board

The TMP102 breakout board I am using is this one from SparkFun. This device can measure a temperature range of -40°C to +125°C, with a resolution of 0.0625°C and an accuracy of 0.5°C.
The TMP102 has 4 registers that are accessible through the I2C bus:
  • Register 0 Temperature Register (Read Only)
  • Register 1 Configuration Register (Read/Write)
  • Register 2 TLOW Register (Read/Write)
  • Register 3 THIGH Register (Read/Write)

We are only interested in Register 0, for further info on the other registers, the datasheet for the TMP102 device can be found here. Two bytes can be read from register 0:
  • Byte 1: Full degrees
  • Byte 2: Fraction degrees


Circuit
So, we are going to connect our I2C device to the appropriate pins on the Pi's GPIO header:


Raspberry Pi GPIO Header TMP102 Breakout board Description
Pin1/3V3 V+ This will provide power to the TMP102 device.
Pin6/Ground GND and ADO Device power rail ground.
Pin3/SDA SDA Data line for the Pi's I2C interface 0.
Pin5/SCL SCL Clock line for the Pi's I2C interface 0


Note that AD0 in the TMP102 breakout board is used to define the least significant bit of the I2C address of the TMP102 device. If it is connected to ground, the address of the device is 0x48, if connected to 3v3 the address is 0x49. This allows up to two TMP102 devices to exist on the same I2C bus. In my case I have connected it to ground.


Enabling I2C and Installing I2C Tools
Assuming you have not enabled I2C on your Raspberry Pi before:


Enable I2C in modprobe:
Have a look at the /etc/modprobe.d/raspi-blacklist.conf file, comment out the two lines:
blacklist spi-bcm2708
blacklist i2c-bcm2708

Load the i2c kernel drivers:
sudo modprobe i2c-dev

Now check that the i2c devices have appeared in /dev:
ls -l /dev/i2c*
crw-rw---T 1 root i2c 89, 0 Sep 20 19:43 /dev/i2c-0
crw-rw---T 1 root i2c 89, 1 Sep 20 19:43 /dev/i2c-1


Install the i2c tool chain:
sudo apt-get install i2c-tools

Add your user to the i2c usergroup
This is so you don't need to use sudo to interact with the i2c device.
sudo usermod -aG i2c yourusername


Talking to the I2C device
We can now use the i2cdetect command to determine what devices are on the I2C bus
pi@raspberrypi ~ $ i2cdetect -y 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --

The '-y' option disables interactive mode for the command and the '0' is the I2C bus to scan. You can also run this command on the Pi's second I2C bus by specifying '1' instead.
We can see that it has found our TMP102 device at address 0x48.

To read the temperature from our temperature sensor, we use the i2cget command to read a single byte (Byte 1 - full degrees) from the temperature register (0x00) of the device.
pi@raspberrypi ~ $ i2cget -y 0 0x48 0x00 b
0x16

Converting this hexadecimal value to decimal, we get our temperature of 22°C.

If you want a more precision on the temperature, you can read both the full and fractional bytes from register 0 as follows:
pi@raspberrypi ~ $ i2cget -y 0 0x48 0x00 w
0xa015
This gives us byte 2 (0xa0) and byte 1 (0x15), but as a 16bit hexadecimal number and in the wrong order. To convert to °C, swap around the bytes, shift right by 4, convert to decimal and multiply by 0.0625.
E.g.
dec(0x15a0>>4) * 0.0625 = 21.625°C

Conclusion
So, we have been able to set up the circuit to interface with the TMP102 temperature sensor, enabled I2C on the Raspberry Pi, install the necessary I2C tools and queried the temperature from the sensor.
As a further exercise, the reader can experiment with reading and writing (using the i2cput command) to the other registers available in the TMP102.

Enabling I2C on a Raspberry Pi

Using an SD card with Raspbian “wheezy”...

Enable I2C in modprobe:
Have a look at the /etc/modprobe.d/raspi-blacklist.conf file, comment out the two lines:
blacklist spi-bcm2708
blacklist i2c-bcm2708

Load the i2c kernel drivers:
sudo modprobe i2c-dev

Now check that the i2c devices have appeared in /dev:
ls -l /dev/i2c*
crw-rw---T 1 root i2c 89, 0 Sep 20 19:43 /dev/i2c-0
crw-rw---T 1 root i2c 89, 1 Sep 20 19:43 /dev/i2c-1

Install the i2c tool chain:
sudo apt-get install i2c-tools

Add your user to the i2c usergroup
This is so you don't need to use sudo to interact with the i2c device.
sudo usermod -aG i2c yourusername

We can now use the i2cdetect command to determine what devices are on one of the  I2C buses
pi@raspberrypi ~ $ i2cdetect -y 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --
We can see that I have a device at address 0x48 on bus 0 (see my tutorial here for further info).