Reading from a MCP3002 analog-to-digital converter


Created by: coderanger

Published Mar. 10, 2013

This tutorial covers the setup software and hardware to read an MCP3002 analog-to-digital converter from a Raspberry Pi running the latest Raspbian operating system.

An analog-to-digital converter (ADC) is an important component of many projects as it allows you to read an analog voltage signal and convert it to a value usable by your Python code. This is most commonly used to read sensors that return a range of values, anything from a volume knob (0-10) to a temperature sensor (0-100 degrees).

Here we will build the needed circuitry to interface with the chip and a simple input based on trimpot, a variable resistor with a knob. This is very similar to the circurity and software behind the volume knob on your sound system.

Related categories: Tutorial

Step 1: Install Python development tools

Open a terminal on the Raspberry Pi by double-clicking on the LXTerminal icon on the desktop.

Run the following commands to install some basic Python development tools:

sudo apt-get install python-dev python-pip
sudo pip install ipython

Step 2: Setup SPI interface

SPI stands for Serial Peripheral Interface. It is a very simple method of communicating with the  MCP3002 chip. Using this interface you can read the current value from the trimpot and convert it to a value you can use in your software.

Run the following commands:

sudo modprobe spi_bcm2708
sudo pip install spidev

This will activate the Linux kernel driver for SPI and install the Python library to communicate with it

Normally this will reset on reboot to make the pins available for GPIO again, if you would like to automatically load the SPI driver on startup run:

echo spi_bcm2708 | sudo tee -a /etc/modules

Step 3: Connect the ADC

Ensure the ribbon cable is connected to the Raspberry Pi with the notch facing towards the board. Connect the breakout headers in the middle of the breadboard so each row is on its own side. This is important because in a breadboard, each row on either side is electrically connected and you don't want to cross the two sides of the breakout.

Step 3.1: Installing the MCP3002 chip

The MCP3002 is a black chip with two rows of four pins, referred to as a DIP or dual inline package. As with the breakout, insert the chip in the center of the breadboard. There is a small notch on one end of the package, in the diagram this is facing towards the top of the board. The connections may look daunting so lets take them one at a time.

The first things to connect are the power and ground pins. While the rows in the middle of breadboard connect horizontally (and only on that half of the board) the two columns on the far left and far right are connected along their lengths. These are generally used for power supply and grounding, and are called busses. In our case both are coming from the Raspberry Pi, so first connect one of the 3.3V pins to the leftmost column and one of the GND (short for ground) to the rightmost column.

Then we can connect the power and ground for the MCP3002. In the diagram these are labelled VDD (power) and VSS (ground). the MCP3002 has two independent input channels, but we will only be using CH0 so you can also connect CH1 to ground if you like. This will make it more obvious if you are reading the wrong channel later on.

Step 3.2: Connecting communication wires

Next we need to connect the clock and communication pins. CLK is simple enough, this is the timing signal used to coordinate the data between the Raspberry Pi and MCP3002. The two data pins are called DIN/DOUT on MCP3002, and MOSI/MISO on the Raspberry Pi. The Pi names are short for "Master In Slave Out" and vice versa. This means we want to connect MOSI to DIN and MISO to DOUT.

Finally we need to connect the CS (short for Chip Select) pin. The Raspberry Pi can communicate with up to two devices on a shared SPI bus (shared clock and data connections), so the chip select signal is used to indicate which device the Raspberry Pi would like to talk to. We want to use SPI channel 0, so connect the CE0 pin on the breakout to the CS pin on the MCP3002.

All this leaves is the CH0 pin on the MCP3002, which we need to connect to some kind of analog signal.

Step 4: Build a voltage divider

As a small demonstration of the ADC's capabilities we will build a small volatge divider using a tunable 10k ohm trimpot (potentiometer). If you already have another analog signal you would like to sample you can skip this step and just use your existing signal in future steps. Be sure to use the 3.3V source as the input to the voltage divider, and not the 5V.

The trimpot is a square blue component with a turnable knob on the top. It has three leads on the bottom, the two on either side are connected to the fixed resistor, while the middle lead is connected to the part the knob controls (called the wiper). Connect one of the outside pins to the power bus on the left side of the breadboard. The middle pin will be your signal output. The other outside pin should be connected in series with a 330 Ohm resistor. This limits the maximum current draw through the Raspberry Pi's power supply even when you turn the knob down the zero, otherwise you risk damaging the Raspberry Pi.

Once completed you can verify things are working by using a multimeter to check the voltage on your signal output. Set the multimeter to the 2V setting and touch the black probe to a wire connected to the ground bus and the red probe to a wire connected to the signal pin on the trimpot. As you twist the dial on the trimpot you should see the voltage move from 0V to 3.3V.

Connect your signal output to the CH0 input on the MCP3002.

Step 5: Write Python Code

The following shows how to read from the MCP3002, more interesting applications are left to the reader.

from __future__ import division
import spidev

def bitstring(n):
    s = bin(n)[2:]
    return '0'*(8-len(s)) + s

def read(adc_channel=0, spi_channel=0):
    conn = spidev.SpiDev(0, spi_channel)
    conn.max_speed_hz = 1200000 # 1.2 MHz
    cmd = 128
    if adc_channel:
        cmd += 32
    reply_bytes = conn.xfer2([cmd, 0])
    reply_bitstring = ''.join(bitstring(n) for n in reply_bytes)
    reply = reply_bitstring[5:15]
    return int(reply, 2) / 2**10

if __name__ == '__main__':
    print read()

Using the provided voltage divider sensor you should see a number between 1.0 and 0.0. Slowly turn the trimpot knob and watch the number change. Can you find the halfway point?


comments powered by Disqus