interfacing a 12 Bit SPI ADC

Hey, nice work on the code. What is the name of the gyro that you are trying to interface with the arduino? Could you include your code for the gyro as well? I'm having trouble interfacing the MLX 90609 rate gyro through SPI.

Thanks!!

I'm using the sparkfun analogue IMU, hence the ADC. The important thing with SPI is to read the datasheet carefully, nearly all SPI devices aren't 'standard'.

Hello Halabut,

I recently bought a Wiring Mini board and hooked up one of these mcp3208's to it .. using the same code you provided. It compiled with no errors and successfully uploaded to the wiring board. It doesn't seem to work though. All I see in the serial monitor of the Wiring IDE is either 0 or 4095 ... and the occasional random number every once in a while.

I'm using the same pin #'s ... 10,11,12,13

It works 100% on my arduino.

thanks,
Phil

I don't have any experience with wiring, but from the sounds of it this is a hardware problem. Check all your wires are in correctly and that the ADC has its ref voltage and power supplies connected and they're at the right levels. Other than that I can't think what it'd be.

Thank you. I checked it a few times over and then switched to a different set of pins with the same results. It is strange. Do you think it has something to do with timing? ... maybe the wiring board's timing is different from the Arduino.

Phil

Maybe the pin mapping is different between wiring an arduino. remember the pin #'s in the arduino world typically refer to the arduino board's pin numbers, not the microcontroller pin numbers.

Arduino was obviously inspired/based on/an offshoot of (not sure of the technical term, don't want to offend the tinket.it guys) the wiring board, so maybe the numbers match, I'm not sure.

That's a good possibility, but I don't think I would have seen anything on the serial monitor.

Phil

Timing shouldn't be a problem, the code is all bit-banged. It's very timing insensitive, and doesn't rely on any chip-specific features.

I'm pretty sure it is a pin mapping problem. I just checked out the schematic at:

It looks like Port 3 is where I need to be wiring the ADC to ... I was originally trying to use Port 1 on the Wiring Mini

Wiring Mini Board pins MCP3208 ADC Pins

24 -----> CS Chip Select Pin 10
25 -----> CLC Clock Pin 13
26 -----> Din MOSI Pin 11
27 -----> Dout MISO Pin 12

Looks like this should work. I'm out on the road with my job right now. I should be able to check this on Monday.

Phil

I've been messing around with it for the last couple hours on the correct pins ... still the same results. I have no idea what may be the problem.

Phil

I'm back to just using this on Arduino.

I'm trying to use the AGND pin. I tried putting about 2V on it, but it just shunts down to millivolts ... since it is an analog ground. Is AGND really meant for setting a lower limit? The spec sheet doesn't really mention too much about it.

Phil

I figured it out. I had to use a separate power source for the analog end of things. I connected the pot wiper (from analog source) to AGND pin.

In the end it brings the resolution down to only 11 bits instead of 12. I have my Vref set to 4.77V (from digital source) and AGND of 2.25V .... my ADC range is from 0 to 2047. Is there any way to make this range from 0 to 4095 ?

P.S. I didn't connect the Analog ground to the digital ground.

Phil

Hi halabut,
I am a newbie with arduino. I'm currently trying to implement ADC MCP3204. I tried to use your code and connect similarly but my adcvalue keeps reading either zero or 4095 (5V). I suspect it's the timing but the datasheet for both 3204 and 3208 have the exact same timing. Please help, thanks!

That's strange, especially given that they're the same datasheet. Looking at the code it should work fine (for the first four channels only obviously)
All I can advise is checking your connections against the datasheet, the pins are in the same order (except dgnd on the left). Many of my frustrating 'broken' circuits have been me forgetting to connect ground, so check everything twice. Other than that it might (and this is unlikely) be a dud chip.

Alec

Hi halabut,
Thank you very much for replying so early. I finally got it working with a little modification on your code. Instead of:

int adcvalue = 0;
byte commandbits = B11000000; //command bits - start, mode, chn (3), dont care (3)

//allow channel selection
commandbits|=((channel-1)<<3);

digitalWrite(SELPIN,LOW); //Select adc
// setup bits to be written
for (int i=7; i>=3; i--){
digitalWrite(DATAOUT,commandbits&1<<i);
//cycle clock
digitalWrite(SPICLOCK,HIGH);
digitalWrite(SPICLOCK,LOW);
}

I changed it to:

int adcvalue = 0;
byte commandbits = B110000 + channel; //command bits - start, mode, chn (3)

digitalWrite(SELPIN,LOW); //Select adc
// setup bits to be written
for (int i=4; i>=0; i--)
{
if ((commmandbits>>i)%2 == 1)
{ digitalWrite(DATAOUT,HIGH); }
else
{ digitalWrite(DATAOUT, LOW); }
//cycle clock
digitalWrite(SPICLOCK,HIGH);
digitalWrite(SPICLOCK,LOW);
}

I'm not sure why u had (channel-1) in your code but i got it working in the end using most of your code. Thank you very much. :slight_smile:

I found it was very nice to manually adjust the clock pin HIGH and LOW rather than having it running automatically in the background. Thus, timing is up to us to control rather than the arduino controller.

Part of my project is to also have a DAC12bit (TLV5616). I tried similar thing with your code but it does not work. I always get zero. Do you have any idea, please help me out. I already tried using the SPI library but didn't work. Thanks in advance. :slight_smile: :slight_smile: :slight_smile:

Here's my code so far for the DAC:

void writeDacSPI(byte voltValue)
{
byte commandbits = B11111111;
displayOnLCD(0,1, commandbits);
digitalWrite(dacFSPin, LOW); // turn on DAC
for (int i = 7; i >= 0; i--)
{
if ((commandbits>>i)%2 == 1)
{ digitalWrite(dataOutSPI, HIGH);}
else
{ digitalWrite(dataOutSPI, LOW); }
digitalWrite(clockSPI,HIGH);
digitalWrite(clockSPI,LOW);
}
for (int i = 7; i >= 0; i--)
{
if ((voltValue>>i)%2 == 1)
{ digitalWrite(dataOutSPI, HIGH);}
else
{ digitalWrite(dataOutSPI, LOW); }
digitalWrite(clockSPI,HIGH);
digitalWrite(clockSPI,LOW);
}
digitalWrite(clockSPI,HIGH);
digitalWrite(clockSPI,LOW);
digitalWrite(dacFSPin,HIGH); // turn off DAC device
}

The chan-1 makes it 1 based, rather than 0 based.

I think I know why you get 0 from the DAC: setting bit 13 to 1 will power down the chip! The data bits go x S P x d d d d d d d d d d d d
x = don't care
S = speed (1=fast)
P = power (1=off)
d = data bits (12)

Alec

Hi halabut,
U r right. I misunderstoood the spec sheet when it says "in power down mode, all amplifier are disabled". Thanks a lot :slight_smile:

This also works with the 13-bit MCP3302.

Change

  //read bits from adc
  for (int [glow]i=11[/glow]; i>=0; i--){
    adcvalue+=digitalRead(DATAIN)<<i;
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);
  }
  digitalWrite(SELPIN, HIGH); //turn off device
  return adcvalue;
}

to:

  //read bits from adc
  for (int [glow]i=12[/glow]; i>=0; i--){
    adcvalue+=digitalRead(DATAIN)<<i;
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);
  }
  digitalWrite(SELPIN, HIGH); //turn off device
  return adcvalue;
}

This allows reading in the extra bit that the 3302 provides. Thanks for the code, it works great for my application :slight_smile:

hello - maybe this thread is dead, but I just wanted to thank halabut for posting that code, works like a charm!

for those that can't get it to work, check your wiring - i had my Vref set to ground by mistake the first time and kept getting 4095