MCP3008: Find out if this ADC is as good as it
claims. Do you need a 10 bit, 8 channel ADC with a high sample rate?
This could be the
right one. Find out its real sample rate here.
MCP3008: You saw the advert and it says this ADC has...
a total of 8 input channels,
a 200kHz sample rate...
... This is Over 20 times the Arduino Uno sample rate!
But why is your sample rate 10x lower? - Find out here.
The theoretical maximum sample rate for an "impossible" ideal 8-bit processor is 150ksps; is the datasheet lying?
It claims to have Differential Operation but sneakily puts in the words "pseudo differential".
Find out what "Pseudo Differential" means for this chip.
The MCP3008 is a 10bit Successive Approximation Register (SAR) ADC (the same as the Arduino ADC).
However unlike the Arduino ADC the claimed sample rate is 200ksps (@5V)
whereas the Arduino sample rate is
It has 8 inputs that can either be single ended or arranged as four input pairs in what is called pseudo-differential.
 Clock rate must be >10kHz
otherwise the sample cap. discharges before completion.
 Also has pseudo differential operation.
 Typical values of operating current are [email protected] and [email protected]
consumption depends heavily on the sample rate clock i.e. the SPI clock.
MCP3008 Block Diagram
PDIP and SOIC package pinout.
MCP3008 Connection list
This connection list shows you how to wire up the Arduino Uno to the
MCP3008. Simply connect MISO, MOSI, SCK, 5V and GND to the chip.
Additionally connect Arduino pin 10 to the CSn pin on the chip. Add a
10k potentiometer to CH0 for testing the input voltage.
Arduino Uno pin
13 - SCK
13 - SCK - White
12 - MISO
12 - MISO - Purple
11 - MOSI
11 - MOSI - Blue
10 - CS
10 - CSn - Yellow
9, 14 - GND - Black
16 - Vdd - Red
15 - Vdd - Red
10k pot left of wiper
10k pot wiper
1 - CH0
10k pot right of wiper
You can find library installation details are here.
Use the library manager, searching for MCP3008.
Don't install the library named Adafruit MCP3008 - it has a bug that won't allow it to compile.
Install the library named "MCP_ADC by Rob Tillaart"
MCP3008 Performance Test Sketch
The following simple program performs the bare minimum in order to
assess the maximum possible sample rate. All it does is initialise the
instance of the mcp1, set the SPI clock rate (for the default just
comment out both lines starting "mcp1.setSPIspeed").
Then it goes round the loop simply continuously reading analogue MCP3008 channel 0.
// MCP3008 initial speed test.
// Default settings used for capture of clock speed on oscilloscope.
// copyright John Main tronicsbench.com
MCP3008mcp1;// use HWSPI
mcp1.setSPIspeed(3600000);// Gets 2MHz clock - next lowest SPI in spec.
// mcp1.setSPIspeed(4000000); // Gets 4Mhz SPI clock; Outside MCP3008 spec.
Default Arduino Uno Hardware SPI
These two oscilloscope screenshots show the MCP3008 in action, using the hardware SPI in default mode.
Comment out the following lines (for a default SPI clock of 1MHz):
This first oscilloscope screen shot shows a 3 byte transaction
(required to get the data out of the MCP3008). It shows the clock in
blue (top trace) and MOSI in yellow (bottom trace).
You can see in the first one that the default clock rate is 1MHZ (the MCP3008 can go at 3.6MHz).
The second screen shot shows the repeat rate that the Arduino Uno is achieving which is ~23ksps.
Note: With a 1MHz SPI clock the sample rate is 23ksps.
Screenshot 1; Default SPI mode, CLK, MOSI
Screenshot 2; Default SPI mode, CLK, CSn
With this SPI rate (1MHz) the Arduino sample rate is modest at 23ksps. Note that is also without the Arduino doing anything else useful!
SPI at 2MHz
By uncommenting the line:
mcp1.setSPIspeed(3600000); // Gets 2MHz clock
and commenting out the next line as below:
// mcp1.setSPIspeed(4000000); // Gets 4MHz clock
The clock speed is set to 2MHz - which is the closest one that the hardware can achieve.
This is the problem with writing generic software - you really have
to understand the underlying hardware to see why allowing selection of
"desired" SPI clock speed only gets near the actual speed. However
the software chooses the next lowest available speed for the Arduino in
Here the repeat rate is 32kHz - the effective sample rate - again with no other useful operation.
Note: With a 2MHz SPI clock the sample rate is 32ksps.
SPI at 4MHz
Set 4Mhz by changing the following:
Comment out the line:
// mcp1.setSPIspeed(3600000); // Gets 2MHz clock
and uncomment the next line as below:
mcp1.setSPIspeed(4000000); // Gets 4MHz clock
Note: This is out of spec so should not be done (max speed should be
3.6Mhz). It is used here to see the effect on the Arduino Uno Sample
rate (not much!).
You can see the sample rate is still only 40ksps and that is
operating the MCP3008 out of spec, and again doing no other actions! The
Arduino Uno is going flat out and can't read the input fast enough.
Note: With a 4MHz SPI clock the sample rate is 40ksps but this is out of spec.
Theoretical Maximum sample rates
MCP3008 maximum 8-bit SPI rate
The claimed maximum MCP3008 sample rate is 200ksps. but if you do
some simple calculations when using the SPI module of the Arduino Uno
you get the following result:
For three 8 bit transactions using a 3.6Mhz clock:
sample rate = 1.0/ ((1/3.6e6)*8*3) = 150ksps.
Warning: The 150ksps sample rate is not acheivable in a real application.
(See the bit banged calculation for where the 200ksps figure comes from).
This is slightly unrealistic as the transactions are assumed back to
back (in practice this can't be done - the processor has to do some
other tasks or else it is useless) - it is also wrong as the max SPI
clock is 2MHz (see below for true Arduino sps rate). But this shows a
theoretical operation to figure out what is going on.
Either the data sheet is lying or something else is going on.
This figure reveals the problem (Figure 6-1 from the datasheet) :
The title of the figure is "SPI Communication with the MC3004/MCP3008
using 8-bit segments". This is an example of how to interface the
MCP3008 with an 8-bit SPI hardware module. It is not a specification
that must be followed - if you don't have 8-bit SPI module then bit
banging will use less bits.
The problem is the gap at the start (see DIN ?) - the
first 6 clocks are throwaway clocks to allow the data to align. A worse
problem is that the number of bits to communicate with the MCP3008 is 18
- it does not fit into a multiple of 8 so you always need 3 SPI
transactions to complete a transfer.
This is a problem with the payload size of the 8 bit SPI hardware module within the processor!
maximum 18 bit, bit banged rate
If you only transmit 18 bits at 3.6MHz then the sample rate is:
So in fact the data sheet is not lying - it is however misleading.
Warning: The 200ksps sample rate is not acheivable in a real application.
It is misleading in that the 200ksps figure assumes that the
processor is doing nothing else. The processor has to do something else
so this sample rate is a theoretical maximum! which can never be reached in practice!
This is also implied in the data sheet (Section 4.0 Device Operation):
"Conversion rates of 100 ksps are possible on the
This conversion rate acknowledges the processor time "activity" but
is not explicitly stated, and is not indicated anywhere else in the
datasheet! a bit naughty.
Is there a sample rate solution? - No
You can't change the SPI module's operation and running at 4MHz doesn't do much.
The only solution is a different processor, or use an FPGA that you program an SPI interface to 18 bits long!
One way round it is if there is a dedicated SPI module that can be
setup as an 18 bit generator - not sure that exists - you can do it in
an FPGA! The other way round it is to use a super fast processor with
interrupt generated SPI - so it can do some work within the bit period
of an SPI output at 3.6Mhz!
MCP3008 Arduino Uno maximum rate
You can only really use 2MHz SPI clock with the Uno (to remain within the MCP3008 specification) so your "real" sps is:
Uno sample rate = 1.0/ ((1/2e6)*8*3) = 83ksps[theoretical maximum]
In practice you can not achieve this as the processor must set up CSn
and there is a gap between SPI transactions (to set up the registers
and do other useful work) as you can see in the real world oscilloscope
screenshots. For the Arduino Uno the chip select signal frequency is ~32kHz - this is the maximum sample rate doing no other processing!
Understanding Pseudo Differential
Pseudo-differential and True-differential comparison:
True-differential operation uses an internal opamp to obtain the
difference between two ADC inputs which is then sampled by the ADC.
Pseudo-differential operation uses one of two methods:
Samples of each pin are made at different times then subtracted.
The sample capacitor is charged to Vin+ (for the track part) and
subsequently Vin- (for the hold part) - but not explicitly stated in
The MCP3008 uses the second method since, in application note AN1108, it
indicates that the Vin- pin must be kept to ±0.1LSB during the conversion for best performance of
the ADC (as is the case here). The MCP3008 allows only a ±100mV input range for the negative input in this mode.
The application note also indicates that this mode has little
effect on dynamic or common mode noise meaning this mode does not
eliminate noise (a very useful reason for using true-differential).
The main use for this pseudo differential operation for the MCP3008
seems to be to allow a slightly different ground to the one used by the
ADC to remove small dc offsets. This makes sense in removing ground
bounce - where at distant parts of the circuit the ground is at a
slightly different voltage than another ground.
You could use the pseudo differential mode to route two "sense" wires
so that the ground, and signal is sampled at the point of measurement
(end of the tracks) so that the local ADC ground is ignored. However the
mechanism of operation is not explained so it may not get
rid of dynamic noise (as the application note also suggests).
Warning: The exact
mechanism is not explicitly stated but application note AN1108 indicates
that this scheme uses a timed switch (Track and then Hold); meaning it
is impossible to remove dynamic noise as the T and H actions are
separated in time so the noise measured will be different between T
& H portions.
Fairly surprisingly the achievable sample rate using an Arduino Uno and an MCP3008 is Really Bad when compared to the maximum claimed.
It is about 2 times better than the internal ADC.
The spec of the MCP3008 200ksps but the Arduino Uno achieves 32ksps
at best when using a 2MHz SPI clock (doing no other work). This is the maximum
SPI clock that the Uno can generate that is within the 3.6MHz specification of the MCP3008. Note: the
default SPI clock is 1MHz, so set up the 2MHz clock as shown in the code above.
Uno Processing power problem
The real problem is that the Arduino Uno just does not have enough
processing power to really use the available 200ksps sample rate of the
MPC3008 - coupled with the 8-bit SPI hardware module problem.
The best you can achieve with the Uno is 32ksps (2MHz SPI clock).
However that is without the Uno doing any other processing and when you
do something else there is less time for sampling. In effect the sample
rate will be even lower.
True Uno sample rate
The true sample rate (when you do some processing - but not too much!) is probably 20ksps so it is an improvement over the built in ADC at 9.6ksps but it is probably not as much as you expected!
The MCP3008 does not have true differential operation and only allows
one of the differential inputs to move from ground by a maximum of
±100mV, so it is only useful in eliminating small d.c. offsets and may
not be effective in removing dynamic noise.
The MPC3008 does use a lot of current (over half a milliamp (max) at
5V) so it may not be that suited to battery operation. Note, however,
that the current consumed falls as the power supply is lowered and also falls with sample rate (Datasheet Fig2-32).
Useful to supplement Arduino Uno ADC
If you are looking to add additional ADC inputs to an Arduino Uno
then the MCP3008 will be a good choice as it has a comparable operation.
The sample rate you can achieve is far lower than the datasheet leads
you to believe, but still
better than the Arduino built-in ADC.