MCP3008 10 bit 8 channel Analog to Digital converter

In this example we are going to connect from Raspberry Pi to MCP3008 10 bit analog to digital converter.

This chip has 8 analog input channels.

(And at bottom there I tell of how to get it to work also on H3 based Orange Pi)

DISCLAIMER

We do not take any responsibility for possible errors in the guide or errors that you might do wiring it up. Incorrect wiring can result in damaged sensor or damaged Raspberry Pi.

Pieces we use in this guide:

For the test we will let potentiometer act as voltage divider to put values from zero to 3.3 V into one of the analog channels.

The MCP3008:

The MCP3008 has 8x 10 bit analog input channels.

There is also 1, 2 and 4 channel version of it that works the same. The name of the 1 channel chip is MCP3001, the name of the 2 channel version is MCP3002, the name of the 4 channel version is MCP3004. They all work the same except the MCP3001 has no digital in (which might change how the guide works) and MCP3002 works on single circuit as opposed to two circuits as all the other types do.

There are also MCP3201, MCP3202, MCP3204 and MCP3208 which are 1x 12 bit, 2x 12 bit 4x 12 bit  and 8x 12 bit analog input channel versions.

If you are working with other chip than the MCP3008 like I use in this guide then I have pin guide for the others here.

My chip looked like this .

You can also get  surface mount version of the MCP3008 and then it looks like this:

MCP3008 main specifications:

Pin number
Pin name
Description
1, 2, 3, 4, 5, 6, 7 , 8 Analog input channels. Analog voltage will be measured on those pins.
9 Digital ground Ground of the circuit that runs the MCP3008.
10 Chip select Turns the chip on and off, Low = on, high = off.
11 Digital in Used for getting data from SPI communication.
12 Digital out The chips sends data from this one in SPI communication.
13 Serial Clock Used to provide clock signal for SPI communication
14 Analog ground Ground which belongs to the analog circuit (or same ground if its the same circuit.
15 Reference voltage Voltage that belongs to the analog circuit.
16 VDD / VCC Voltage the drives the MCP3008 chip.

If you are not familiar with working with a breadboard or on how to place a cobbler on the breadboard then click here bellow

Breadboard

Wiring map

MCP308 Pin
Raspberry PI cobbler

Potentiometer
1 Middle pin
9 GND
10 SPI0-CE0 (Pin 24)
11 SPI0-MOSI (Pin 19)
12 SPI0-MISO (Pin 21)
13 SPI0-SCLK (Pin 23)
14 GND
15 3,3 V
16 3,3 V
GND Left pin
3,3 V Right pin
Raspberry Pi pin layout

If you need more information about the GPIO headers on Raspberry Pi or other boards then click bellow.

Raspberry Pi Pin guideOrange Pi One Pin guideOrange Pi Pin guide for most H3 modelsOrange Pi Zero 3 Pin  guideOrange Pi 5 Plus Pin guideRock 64 Pin guide

On the breadboard the circuit looks like this:


The Xojo code:

Remember to enable SPI in your Raspberry Pi configuration before running the code, else you will get exception.

The user interface was simple just a button to read the value. When the button is clicked it gives me voltage from 0 to 3.3 V and if I adjust the potentiometer then a different value will be read from the channel.

For the code I made a small driver class to make it reusable and easy to use in your projects.

The code for the button:

Sub Pressed() Handles Pressed
  try
    var device as new MCP3008()
    
    MessageBox(Format(device.Read(0, true) * 3.3 ,"#.00") + " V")
  catch ex as SPIException
    MessageBox(ex.Message)
  end try
End Sub

The drive class:

Protected Class MCP3008

Private mAdapter As SPI.Connection

Sub Constructor()
  #If TargetARM And TargetLinux Then
    mAdapter = SPI.Connection.Open(0, 8, 1350000, SPI.Modes.SPI_MODE_0, false)
  #else
    #Pragma unused adapterNo
    #Pragma unused deviceId
  #Endif
End Sub

Sub Constructor(bus as UInt8)
  #If TargetARM And TargetLinux Then
    mAdapter = SPI.Connection.Open(bus, 8, 1350000, SPI.Modes.SPI_MODE_0, false)
  #else
    #Pragma unused adapterNo
    #Pragma unused deviceId
  #Endif
End Sub

Function Read(channel as UInt8, modeSingle as Boolean) As Single
  if channel > 7 then
    Raise new InvalidArgumentException("Channel must be 7 or less as the chip only has 8 channels")
    return 0
  end if

  var mode as UInt8 = If(modeSingle, 1, 0)

  var ctrl as UInt8 = Bitwise.ShiftLeft(mode, 7) or Bitwise.ShiftLeft((channel and &b00000111),4)

  var txData(3) as UInt8

  txData(0) = &h01
  txData(1) = Bitwise.ShiftLeft(&h08 or channel,4)
  txData(2) = &h00 

  var rxData() as UInt8 = mAdapter.WriteAndRead(txData, true)

  var result as UInt16 = Bitwise.ShiftLeft((rxData(1) and &b00000011),8) or (rxData(2) and &b11111111)

  // We divide by 1023.0 since 1023 is highest number 10 bits can produce
  return result / 1023.0
End Function
	

Getting the code

You can find this example code at Example code for GPIO guides.

Running the code:

Remember to enable SPI in the Raspberry Pi configuration.

When the button is clicked it gives me voltage from 0 to 3.3 V and if I adjust the potentiometer then a different value will be read from the channel.


I got this also to work on H3 based Orange Pi running Armbian.

To get things to work on H3 based Orange Pi I had to: