Arduino UNO SPI Library + MCP3208 : request for suggestions

Hi everybody,
I am playing with a Microchip MCP3208 ADC SPI converter which is currently converting a 10K Pot input values to my Arduino UNO. MCP3208 is a 12bit resolution ADC, its SPI protocol needs some more bits in order to know how to answer to the Master, and I hadd to add quite a few more at the beginning in order to get those 12bits output at the end inside a few 8bits blocks to properly feed an SPI.transfer() function.

The logic analyzer shows me this:

The code generating that is:

#include <SPI.h>
#include "pins_arduino.h"

void setup (void) { }

void loop (void)
{
  byte a;
  byte b;
  byte c;
  digitalWrite(SS, HIGH);
  SPI.begin ();
  SPI.setDataMode(SPI_MODE1);
  digitalWrite(SS, LOW);    // SS is pin 10
  a = SPI.transfer(B00000110);
  b = SPI.transfer(B01000000);
  c = SPI.transfer(B00000000);
  digitalWrite(SS, HIGH);
  SPI.end();
}

I have a few questions someone may answer. Just out of curiosity. Everything works, I'd only like to know some more.

It's obvious there's no way to make spi.transfer() transfer more then 8bits at a time, and I assume there's no way to make those transfer more "tight" ... I mean, without generating those gaps between each 8bits pack, right? The mcp3208 doesn't complain, it still waits Clock signaling in order to answer back with anything at all. I'm just curious.

There's also that last gap at the end (the one where I wrote a green SPI.end()). Actually I assume It's related to digitalWrite(SS, HIGH) only. I wonder if that's a "feature" of SPI Library or just a "side effect". It's obviously not needed for the SPI to work.

Well, happy to read some hints about that.
Cheers :slight_smile:

Actually I have another question regarding the spi_clock_divider. As I read I can only force the UNO to clock the SPI at 8MHz. SPI.setClockDivider(SET_CLOCK_DIV2) makes it clock at 16MHz/2=8MHz which is still slower then the 10MHz minimum required by MCP3208 for reliable conversions.
I already noticed some quite offset values when running at default SET_CLOCK_DIV4, I will investigate more in that but I'd really like to hear something from the community about this issue :slight_smile:

The gap between the bytes is just the time needed for SPI.tranfer() to collect the resulting byte, return it to the calling program and be called again. The gap at the end is not from SPI.end() (you call that after you set CS high again) but from the call to digitalWrite(). That function is known for being relatively slow, that's why most time-critical Arduino applications use direct port manipulation commands instead of it.

pylon:
The gap at the end is not from SPI.end() (you call that after you set CS high again) but from the call to digitalWrite().

Right, SPI.end() in the timing_graph is just a typo.

So I assume I will live with all that waste if I don't want to rewrite the lib my own, right? Not that it disturbs anything as of now :slight_smile:

I have to correct myself about the clock issue. mcp3208 is not happy with clocks under 10KHz not 10MHz. My mistake, didn't read well the datasheet. So, SPI_CLOCK_DIV4 is already good enough :slight_smile:

In the meanwhile I managed to get more linear outputs adding a bypass capacitor to the circuit as suggested in the datasheet.

That really helped a lot but not solved a rather annoying issue in the upper voltage range. I'm feeding a +5v Vref to the ADC and I get a pretty linear output in the range 0.0-4.3V but after that the linearity is lost.


I assume it's because this chip is most probably a Chinese counterfeit.
Please, someone tell me if even the genuine Microchip MCP3208 do show that curve at "high" voltage (I doubt that).

12 bit A/D only goes to 4095 maximum output.

What voltage are you actually feeding into the device ?

michinyon:
12 bit A/D only goes to 4095 maximum output.

Well, I'm cool with that. Btw, the 4095 is confirmed, not the "zero" value, the lowest digital value I get is 3 (almost 0). But that's not an issue :slight_smile:

michinyon:
What voltage are you actually feeding into the device ?

I'm feeding it with 5V from Arduino itself. I have a cheap voltmeter, so my 4.90V reading maybe inaccurate but still pretty close to 5.0V. I consider that a minor issue. I'm more concerned with the non-linearity of the last part of the curve at values higher then 4.3V ... I supposed at first that the MCP3208 should output more linearly the whole range through.

I'm reading right now about a Unity Gain Amplifier, could that be related to this case? I'm still not very confident with all that low/high_impedance input stuff, I'm open to suggestions about that.

I totally nailed the linearity issue with a Unity Gain Amplifier :slight_smile:

This is what I get now:

I couldn't be more happy with the result :slight_smile:
Now I got full linearity on the whole analog input range! An LM358 in Unity Gain AMpli configuration did the trick on the input channel being fed to mcp3208. Well I still have to power the OpAmp with more then 5V ... which is a new issue I have to attack now, I'd really love to settle down on a single 5V power supply only :frowning: