ADC Sample Rate Comparison

Created 27/06/2016 | Measuring the sample rates for the ADC Pi Plus, ADC Pi Zero and ADC Differential Pi

The ADC Pi Plus, ADC Pi Zero and ADC Differential Pi from AB Electronics UK all use the MCP3424 analogue to digital converter from Microchip.  The MCP3424 has programmable bit rates from 12 bits to 18 bits and the number of samples that can be taken each second depends on the bit rate you have chosen.  According to the datasheet for the MCP3424 the data rates are as follows.

240 SPS (12 bits)
60 SPS (14 bits)
15 SPS (16 bits)
3.75 SPS (18 bits)

After getting several enquiries into the actual data rate available on the Raspberry Pi we decided to do some experiments and show you the results.  We decided to test the ADC Pi Plus on a Raspberry Pi 3 using the Python 2 programming language.  We provide our own Python library for the ADC Pi Plus which we used for the experiment. 

First we wrote a simple program that would initialise the ADC Pi Plus and take 1000 samples. The current time was recorded before and after the 1000 samples were taken and from that a total elapsed time and the number of samples per second was calculated.  We also recorded the voltage for each sample and calculated the average voltage at the end.  The program we used is shown below.

#!/usr/bin/python

from ABE_ADCPi import ADCPi
from ABE_helpers import ABEHelpers
import time

i2c_helper = ABEHelpers()
bus = i2c_helper.get_smbus()
adc = ADCPi(bus, 0x68, 0x69, 12)

adc.set_conversion_mode(1)

samples = 1000
value = []

start_time = time.time()

for x in range(0, samples):
    value.append(adc.read_voltage(1))

elapsed_time = time.time() - start_time    
samplerate = samples / elapsed_time
averagevalue = float(sum(value))/max(len(value),1)
print "%d samples in %.3f seconds" % (samples, elapsed_time)
print "%.3f samples per second" % samplerate
print "%.6fV average" % averagevalue

The MCP3242 supports two modes of operation, one-shot sampling and continuous sampling.  During one-shot sampling the ADC wakes up from a sleep state, takes a sample, sends the result to the Raspberry Pi and then goes back to sleep.  During continuous sampling mode the ADC takes samples continuously and returns the last sample when requested.   One-time sampling uses less energy than continuous sampling mode but at the cost of a slower sample rate as it takes time to wake up and go to sleep between each sample.

First we tested the ADC Pi Plus by reading 1000 samples from a single channel in continuous sampling mode.

Bit Rate

Samples Per Second

12

252.478

14

63.805

16

15.974

18

3.996

 

As the results above show the actual sample rate from the ADC Pi Plus is slightly higher than the manufacturers specifications.

Next we tested the ADC Pi Plus by reading 1000 samples from a single channel in one-shot sampling mode.  This was changed with the set_conversion_mode() function:

adc.set_conversion_mode(0)

Bit Rate

Samples Per Second

12

163.472

14

57.055

16

15.546

18

3.963

As the results above show there are significant delays when using one-shot mode on the 12 and 14 bit rates with only short delays on the 16 and 18 bit modes.  One-shot mode may be useful if you only need to take single samples at well-spaced intervals but if performance is more important than power usage then it may be better using continuous conversion mode.

When reading from several channels on the same MCP3424 ADC it takes a short amount of time for the ADC to change channel which can impact the sample rate.  To test this, we modified the Python program to read from two channels as shown below and then repeated the same tests above.

#!/usr/bin/python

from ABE_ADCPi import ADCPi
from ABE_helpers import ABEHelpers
import time

i2c_helper = ABEHelpers()
bus = i2c_helper.get_smbus()
adc = ADCPi(bus, 0x68, 0x69, 12)

adc.set_conversion_mode(1)

samples = 1000
value = []

start_time = time.time()

for x in range(0, samples):
    value.append(adc.read_voltage(1))
    value.append(adc.read_voltage(2))
    
elapsed_time = time.time() - start_time    
samplerate = (samples * 2) / elapsed_time
averagevalue = float(sum(value))/max(len(value),1)
print "%d samples in %.3f seconds" % (samples, elapsed_time)
print "%.3f samples per second" % samplerate
print "%.6fV average" % averagevalue

Reading 1000 samples from a two channels in continuous sampling mode.

Bit Rate

Samples Per Second

12

173.759

14

58.2

16

15.627

18

3.969

 

Reading two channels in continuous conversion mode is slightly faster than reading from one channel in one-shot mode.  This is probably because the time it takes to change channel is similar to the time it takes to wake and sleep in one-shot mode.

Reading 1000 samples from a two channels in one-shot sampling mode.

Bit Rate

Samples Per Second

12

163.209

14

57.023

16

15.546

18

3.961

 

In one-shot mode the sample rate for two channels is only fractionally slower than for one channel.  This shows that if you use one-shot mode there will be less of a performance penalty when reading from 2 or more channels.

Improving Performance When Reading Multiple Channels

As the ADC Pi Plus, ADC Pi Zero and ADC Differential Pi all contain two MCP3424 ADC chips you can read from.  As the MCP3424 only adds an additional delay when switching channels, it is possible to read a single channel from each chip without causing any additional delay. 

To demonstrate this, we will read from channels 1 and 5 on an ADC Pi Plus.  This will read from the first channel on chip U2 and the first channel from chip U3 in continuous conversion mode.  The Python code was modified to read from channels 1 and 5 as shown below and the total time to read 1000 samples from both channels was recorded for each bit rate.

#!/usr/bin/python

from ABE_ADCPi import ADCPi
from ABE_helpers import ABEHelpers
import time

i2c_helper = ABEHelpers()
bus = i2c_helper.get_smbus()
adc = ADCPi(bus, 0x68, 0x69, 12)

adc.set_conversion_mode(1)

samples = 1000
value = []

start_time = time.time()

for x in range(0, samples):
    value.append(adc.read_voltage(1))
    value.append(adc.read_voltage(5))
    
elapsed_time = time.time() - start_time    
samplerate = (samples * 2) / elapsed_time
averagevalue = float(sum(value))/max(len(value),1)
print "%d samples in %.3f seconds" % (samples, elapsed_time)
print "%.3f samples per second" % samplerate
print "%.6fV average" % averagevalue

Bit Rate

Samples Per Second

12

504.217

14

127.429

16

31.943

18

7.991

 

As you can see the time taken to read 1000 samples from two channels in independent chips is far faster than reading two channels from a single chip.  If your application requires more than one input, it may be beneficial to spread your inputs across the two MCP3424 chips to increase the sample rate.

All of these tests were performed on a Raspberry Pi 3 running Raspian Jessie using Python 2.  As Python is an interpreted language it is slower to use than a compiled language such as C.  When reading from an ADC Pi Plus this performance difference will be less noticeable as the main limiting factor is the time needed to wait for each sample.

If your application does other processing in between each ADC read, then you may see slower sample rates than we have listed above.  If you need to get the most performance out of your application, then we do have a C library for the ADC Pi Plus and ADC Differential Pi that should give a boost to your application speed but it will not make any noticeable difference to the sample rate from the ADC as that is limited by the internal circuitry in the MCP3424 chip.

Shop

Support

Click to contact us.
X

Have any Questions?

Send us any questions about this page or product and we will reply within 24 hours.

Submit your Message

X

Have any Questions?

Thank you for contacting us.

We will respond to your enquiry in the next 24 hours.

You can find answers to many questions and additional product support in our Knowledge Base and the Community Forum.