MCP3008 8-Channel 10-Bit A/D Converter

The Raspberry Pi has no built in analog to digital converters (ADC), which can limit the types of sensors it can interface to directly; digital only. A simple and inexpensive option for adding several channels of analog inputs is with Micochip’s MCP3008. It features a SPI serial interface, can operate between 2.7-5.5 VDC, has 10 bit resolution, and can run in a single-ended or differential input configuration. A datasheet is included at the end of this article.


Connecting the Hardware:

Four pins are required for SPI communications, data in, data out, clock and chip select (CS). A great interactive Raspberry Pi Pinout is posted at Gadgetoid. Here are the connections needed:

1-8 CH0-CH7 NA Analog input
9 DGND 6, 9, 14, 20 or 25 Ground USE ONE PIN ONLY!
10 CS 24 (GPIO 8) CE0 or 26 (GPIO 7) CE1 SPI Channel Select USE ONE PIN ONLY!
11 DIN 19 (GPIO 10) MOSI Data out from Pi to MCP3008
12 DOUT 21 (GPIO 9) MISO Data into Pi from MCP3008 SEE NOTE #1!
13 CLK 23 (GPIO 11) SCKL Clock
14 AGND NA Common ground for analog input SEE NOTE #2
15 VREF NA Reference voltage for analog input SEE NOTE #2
16 VDD 1 or 17 (3.3V) Operating voltage SEE NOTE #1!

NOTE #1:  If the supply voltage for the MCP3008 is greater than 3.3VDC, the digital output line on the SPI interface can exceed the Raspberry Pi’s input voltage limit of 3.3V!

NOTE #2: The reference input (VREF) determines the analog input voltage range and is used to calculate the digital output code.

The formula to convert analog to digital is: 1024 (10 bit) * analog voltage in (VIN) / reference voltage (VREF).
Example: 2.5VDC analog in @ 5VDC VREF = (1024*2.5)/5 = 512.
Example: 2.5VDC analog in @ 3.3VDC VREF = (1024*2.5)/3.3 = 775.

Putting it together:


Enabling Device Drivers Under Raspbian “wheezy”:

On some Raspberry Pi software distributions, SPI and I2C kernel modules are explicitly set not to be loaded (blacklisted). We will need to edit the ‘/etc/modprobe.d/raspi-blacklist.conf’ file to remove these restrictions. Place a comment (#)  at the front of the lines containing spi-bcm2708 and i2c-bcm2708. A reboot is needed.

sudo nano /etc/modprobe.d/raspi-blacklist.conf

#blacklist spi and i2c by default (many users don’t need them)
#blacklist spi-bcm2708
#blacklist i2c-bcm2708

sudo reboot

Setting Up the Software:

This program requires Wiring Pi: GPIO Interface library for the Raspberry Pi to make it easier for setting up and using the Pi SPI interface. After you have installed WiringPi. you can test it with the following command.

gpio -v && gpio readall

Once WiringPi is successfully installed, copy the following source code into a file named mcp3008.c and compile.

mkdir source
cd source
nano readMcp3008.c

Double click the source code to get the full listing. Copy and paste into nano and save.

gcc -Wall -o readMcp3008 readMcp3008.c -lwiringPi

And now we can test the program. On my setup I have the first channel attached to 3.3VDC. The second channel is tied to a LED on my prototype board. The rest of the channels were left floating.


Usage: readMcp3008 all|channel[1-8] [-l] [-ce1] [-d]
-l = load SPI driver, default: do not load SPI drivers, drivers already loaded
-ce1 = spi channel 1, default: 0
-d = differential channel input, default: single-ended

External Resources:

Wiring Pi: GPIO Interface library for the Raspberry Pi


MCP3008 Datasheet

Shaun Bennett has written 6 articles

12 thoughts on “MCP3008 8-Channel 10-Bit A/D Converter

    1. David says:

      My guess: you hit the same problem I did… your input impedance is too high for the MCP3008 to charge the “sample&hold” capacitor properly during one clock cycle. (e.g. with the supplied LDR and a 10k voltage divider.)

      Solutions: (a) add a relevantly sized capacitor.
      (b)give the chip longer to do the sample: (wiringPiSPISetup call) I found that all went much better at an SPI clock frequency of 500kHz rather than 1MHz.

  1. craig says:

    Thanks, very helpful. was a bit confused for a while as running the “gpio load spi” command would return “unable to load/unload modules as this Pi has the device tree enabled” . In the end, I just tried the program code anyway, and once I got the reference voltage right it was fine, even with the odd error message when using the command. Thanks!!

  2. Zach says:

    It is great to have code for an ADC in C, instead of python. I have started to learn C from “C In Easy Steps” . Your program “readMcp3008.c” worked well and will advance my understanding.
    Do you have C code to CONTINUOUSLY record analog input? I would be grateful for some help here too. Thank you very much!!!

  3. Les. Hayward says:

    Just completed your example. It works very well. The only additional thing I needed to do was use raspi-config to enable the SPI interface.
    This has been most helpful, as I am constructing a logger for downhole magnetometer logging and this interface will save a great deal of work!

  4. Martini says:

    Thank you so much for the code!
    I’m trying to get as close as possible to the 200ksps sample speed of the MCP3008 (1 channel, 5.0V). I’m trying to sample 40kHz on the raspberry pi 4, so I should at least sample above 80ksps. Sadly I’m only getting just shy of 40ksps using python.

    What was sample speed you achieved using this code?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">