MCP3208 on RaspberryPi and Python


Reading analog signals from external sensors with MCP3008[1] is well known and wide-spread[2],[3]. I was also working with this chip on my first experiments with photoresistors, but figured out, that 10 bit resolution would not suffice my needs.


So I went on for the next higher ADC model, the MCP3208[4], which provides 8 channels at 12 bit. Naturally, I was hoping for a "plug-and-play" upgrade, having just to replace the chip and start measuring in ~0.0122 V steps (5V reference).
Well, there were a couple of things in the way....

Python SPI

I took the Python code from [2] and added code for a stepper motor control (more on that in another project).
The values looked garbled, and the reason is clear: the SPI interface messages must be adapted as discussed in [2], in depth in [5].
def ReadChannel(channel):
  adc = spi.xfer2([ 6 | (channel&4) >> 2, (channel&3)<<6, 0])
  data = ((adc[1]&15) << 8) + adc[2]
  return data

After fixing this, it still did not show the expected results, values were erratic, what else needs to be done? Would I have to add an amplifier, as mentioned in [5] and [6]?

Constant power source and capacitor

Equation 4.1 in [5], shows how the output value derives from input voltage and reference voltage. There is discussion about using 4095 vs. 4096, as mentioned in [2] . I use 4095, as this is the maximum output value read from the device:
value(out) = 4095 x V(sample)/V(reference)
While trying to establish the measurement setup, V(sample) is kept equal to V(reference), as I am using a simple voltage divider curcuit, with large resistance ~2MOhms to Ground vs. 5.1kOhms to channel 0 of the MCP3208.
[6] "Basic SAR ADC Operation" describes how an analog voltage is transformed into a digital value by means of a capacitive array. For 500kHz, the default SPI clock speed, it takes ~3µs to sample 12 bit . So if power oscillates within this time the values will not be stable. From figure 4 we take, that we should not run at much higher clock speeds, because the higher the sample resistance is, the more time it takes to charge the capacitors. Giving it too little time for charging and reading to fast would yield greater errors.
Attaching a power source unit at 5 V replacing RPi's GPIO 2 +5V out, yields much better results!
Monitoring RPi's GPIO 5V out with an oscilloscope revealed many jumps in voltage, mostly < 0.05 V. This would explain why driving the MCP3008 with RPi power suffices most needs.
Still, there were occasional single jumps of +- 5 counts, how about them? The countermeasure is a 0.1µF ceramic capacitor between VDD and Ground, also mentioned in [7].

MCP3208 wiring

After these modifications I read reproducible values, yielding smooth curves. More on this in another project! Photoresistor characteristics


  1. MCP3008 10-bit Analog-to-Digital Converter (ADC)
  2. Analogue Sensors On The Raspberry Pi Using An MCP3008
  3. Analog Inputs for Raspberry Pi Using the MCP3008
  4. MCP3208 12-bit Analog-to-Digital Converter (ADC)
  5. Microchip 3208 Datasheet(pdf)
  6. AN246 - Driving the Analog Inputs of a SAR A/D Converter (pdf)
  7. stackexchange forum - interfacing RaspberryPi with MCP3903
  8. online curcuit drawing tool: