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 9.6ksps.

It has 8 inputs that can either be single ended or arranged as four input pairs in what is called pseudo-differential.

MCP3008 Datasheet

Download the MCP3008 datasheet here.

MCP3008 Details

MCP3008 Specifications

Parameter
MCP3008
Voltage Supply (Vdd)
2V7 ~ 5V5
Abs.Max VDD 7V
Measurement range 0V0 ~ Vref
Interface
SPI
SPI rate 3.4MHz(max) (5V)[1]
Resolution
10 bit
Sample Rate (@5V)
200ksps
Sample Rate (@2V7) 75ksps
Number of multiplexed inputs 8[2]
Active current
550uA(max@5V)[3][4]
Power down current (CSn = high)
5nA(typ) ~ 2uA(max)
Power down current (into Vref)
1nA(typ) ~ 3uA(max)
Offset error 
±1.5 LSB(max - typ N/A)
INL  
±0.5 LSB(typ) ~ ±1 LSB(max)
DNL 
±0.25 LSB(typ) ~ ±1 LSB(max)
Gain error
±1 LSB(max)
Operating temperature
-40°C ~ 85°C
            [1] Clock rate must be >10kHz otherwise the sample cap. discharges before completion.
            [2] Also has pseudo differential operation.
            [3] Typical values of operating current are 425uA@5V0 and 225@2V7.
            [4] Current consumption depends heavily on the sample rate clock i.e. the SPI clock.          

MCP3008 Block Diagram

mcp3008 block diagram

MCP3008 Pinout

MCp3008 pinout

        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
MCP3008 pin
13 - SCK
13 - SCK - White
12 - MISO
12 - MISO - Purple
11 - MOSI
11 - MOSI - Blue
10 - CS
10 - CSn - Yellow
GND
9, 14 - GND - Black
VCC
16 - Vdd - Red
VCC 15 - Vdd - Red
10k pot left of wiper
Vdd
10k pot wiper 1 - CH0
10k pot right of wiper GND

Software

Library Installation

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
//
#include "MCP_ADC.h"

MCP3008 mcp1; // use HWSPI

void setup() {
   mcp1.begin(10);

   mcp1.setSPIspeed(3600000); // Gets 2MHz clock - next lowest SPI in spec.
//   mcp1.setSPIspeed(4000000); // Gets 4Mhz SPI clock; Outside MCP3008 spec.
}

void loop() {
    uint16_t val = mcp1.analogRead(0);
}

[File:mcp3008-performance-test.cpp

Initial Testing

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):

//   mcp1.setSPIspeed(3600000); // Gets 2MHz clock
//   mcp1.setSPIspeed(4000000); // Gets 4MHz clock

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

MCP3008 Arduino Uno default SPI hardware mode clock and MOSI

Screenshot 2; Default SPI mode, CLK, CSn

MCP3008 Arduino Uno default SPI hardware mode clock and CSn showing Arduino Sample rate

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

Screenshot 3

MCP3008 Arduino Uno 2MHz SPI hardware mode clock and CSn showing Arduino Sample rate

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 use.

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!).

Screenshot 4

MCP3008 Arduino Uno 4MHz SPI hardware mode clock and CSn showing Arduino Sample rate

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) :

MCP3008 sample rate far lower than expected

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:

    bit-banged sample rate = 1.0/ ((1/3.6e6)*18) =  200ksps

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 MCP3004/3008"

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:
  1. Samples of each pin are made at different times then subtracted.
  2. The sample capacitor is charged to Vin+ (for the track part) and subsequently Vin- (for the hold part) - but not explicitly stated in the datasheet.

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.

Conclusions

Sample Rate

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!

Differential Operation

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.

MCP3008 Power

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.



Comments

Have your say about what you just read! Leave me a comment in the box below.

Don’t see the comments box? Log in to your Facebook account, give Facebook consent, then return to this page and refresh it.



Privacy Policy | Contact | About Me

Site Map | Terms of Use