Raspberry Pi Analog to Digital Conversion Experiments and Howto

The Raspberry Pi is a great little educational computer, but all models of the Raspberry Pi miss a critical ingredient for electronics experiments – an Analog to Digital converter.

SPIMux / Analog Data Acquisition @ http://Mikronauts.com

(Raspberry Pi Model B running with the Data Acquisition board – click on the image for a larger version)

I am constantly working on upgrading my lab, and one of my needs is to measure many channels of analog signals, with reasonably high precision.

I decided to take the time to document a custom Raspberry Pi based data acquisition system that I built to monitor up to 64 analog inputs (currently 24 are available) at two different voltage ranges.

As the project needs at least three (and up to eight) SPI devices, it incorporates an SPI demultiplexer circuit to generate eight chip selects from /CE1.


There are three issues that affect the precision, and number of channels, for this project:

1) Conversion Error

In the past, I just used Microchip’s excellent MCP3008 (eight channel, 10 bit ADC) and MCP3208 (eight channel, 12 bit ADC) which needs an analog voltage reference.

Using the 5V power supply as the analog voltage reference is the simplest choice, but the analog to digital conversion results will be relative to the fluctuating 5V power supply – which is effected by everything happening with the Pi, with 5% error being commonplace.

The simplest way to get more accurate results is NOT to use the systems 5V supply as Aref, but instead use an voltage reference such as a 2.5V Vref will allow measuring 0-2.5V analog inputs much more precisely.

Unfortunately, the most common range I need to measure is approximately 0-5V and often it would be nice to be able to measure more than 5V at times.

The simplest solution is to add a voltage divider on every analog input – for example, using two 10k precision resistors would allow accurately measuring 0-5V using a 2.5V voltage reference.

2) Number of Channels

As I mentioned earlier, I want to be able to measure many channels of analog data, so the eight channels present on an MCP3208 are not sufficient for my purposes.

Using both chip selects available from the GPIO header would allow for 16 analog inputs – but I need more than that!

There are two simple ways of solving this issue:

2.1) Add Analog Multiplexers

It is fairly easy to expand the number of channels using inexpensive analog multiplexers such as the 74HC4051 – just add an analog multiplexer in front of each ADC channel, and feed the output of the analog multiplexer to the divider.

Unfortunately, this increases the amount of wiring, and the multiplexer will add its own minute (but very real) error to the analog signal being measured.

The advantage of this approach is that these multiplexers are a lot less expensive than the analog to digital converters, you will need fewer voltage dividers, and by using three I/O’s as the multiplexer address, eight multiplexers and a single MCP3208 can support 64 channels of input.

The disadvantage for this approach is the internal resistance of the analog multiplexer needs to be taken into account with non-1:2 voltage dividers.

2.2) Create more chip selects and use more MCP3208’s

This is the more expensive, and slightly more accurate approach – but wait, the Raspberry Pi only has one SPI port, with only two chip select!

Fortunately it is very easy to generate additional chip selects using  a 74HC138N 1:8 decoder, three I/O bits, and one of the existing chip selects.

I chose this approach in the past – and will do so again – due to the greater flexibility, as there is nothing that says that the eight devices have to be identical!

3) Input Voltage Range

The most common voltage ranges I need to accurately monitor these days is 0-3.3V and 0-5V however it would be nice to be able to monitor at least 0-6V in order to measure 5V power supplies and signals when they exceed 5V.

Instead of using a common 2.5V voltage reference, I decided to use a readily available 4.096V voltage reference.

A 4.096Vref means that the 12 bit conversion result from an MCP3208 is in mV so to get the voltage just divide by 1000. Makes the math easy :)

It also allows measuring up to 8.192V (in 2mV steps) by using a simple 1:2 voltage divider, and 16.384V (in 4mV steps) with a 1:4 divider.

The Schematic

Raspberry Pi SPI Multiplexer @ http://Mikronauts.com

(click on the image for a larger version)

As you can see, the circuit is quite simple.

The voltage reference circuit is taken from the LM4040AIZ-4.1 data sheet, using a 909R resistor, voltage reference diode, and  100nF ceramic and 33uF electrolytic capacitors for filtering before being fed to the Aref pins of the MCP3208 analog to digital converters.

The 74HC138N 3:8 demultiplexer is used to create eight chip selects from the Raspberry Pi’s /CE1. Note the pull up resistor at the 74hc138 that ensures that none of the ADC’s can be selected until /CE1 is low.

As I need to measure a lot of voltages between 0 and 4.096V, one of the analog to digital converters does not have any voltage dividers, and as such,so reading that ADC returns the voltage in mV directly. I may add a second such ADC later.

The two other ADC’s shown have voltage dividers, which I configured for 0-8.912V with a 2mV resolution.

I used 10k 1% resistors for the ADC voltage dividers as I had a lot of them in stock.

I simply measured enough resistors and binned them to better than 0.1% – I only had to measure about 50 resistors before I found 16 9.966K for one ADC, and 16 9.994K resistors for the other. The voltage divider for MISO is 2k4 coming from the MCP3208’s and 4k7 to ground. I used MCP3208’s instead of MCP3008’s shown, and the LM4040AIZ-4.1 voltage reference instead of the shown zener diode.

A less expensive version of this data acquisition system can be built by using MCP3008 10 bit ADC’s and using a 3.3V zener diode for the voltage reference.

I will likely add another ADC section later, with a 1:4 divider allowing me to measure 0-16.384V with a 4mV resolution.

The measurements should usually be accurate to +/- 1LSB (+-1mV / +-2mV / +-4mV for the ranges discussed above) however the error may be roughly doubled in outlying cases.

I used a 26 pin stacking GPIO connector with a Raspberry Pi Model B and my EZasPie 300 large prototyping board in order to have enough space for 3-5 ADC’s.

The board should work as-is with any Raspberry Pi with a 26 pin or 40 pin GPIO connector.

Updated April 7, 2015: Fixed two errors on the schematic – thanks Thomas!

Article Index:

  1. Introduction, Problems: Conversion Error, Number of Channels, Input Voltage Range, Schematic
  2. Software Support, Sample Code, Results, Conclusion

Pages: 1 2

If you liked this article, please help us grow! "Like" us and let your friends know with the Twitter and Facebook buttons at the top left - We appreciate your support!