I'm trying to upgrade my Uno to have 12-bits of resolution, 1024 just isn't quite cutting it hey.
But I am having trouble getting the AD-Converter to work.
I've added a picture, to show how everything is connected. (Tried making it as clear as possible).'
The IC is a MCP3202.
Then I have my code, which I found on the web.
// MCP3202 2 channel ADC
// 3202 is different software-wise from 3204/3208
#define SELPIN 10
#define DATAOUT 11
#define DATAIN 12
#define SPICLOCK 13
/////////////////////////////////////////////////////////////////////////////
void setup(){
pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK, OUTPUT);
pinMode(SELPIN, OUTPUT);
digitalWrite(SELPIN, HIGH);
digitalWrite(DATAOUT, LOW);
digitalWrite(SPICLOCK, LOW);
Serial.begin(9600);
}
void loop(){
byte i;
int ain[2]; //creating a small array to save into
ain[0] = read_adc(SELPIN, 2); //calling the read function and saving in the array
ain[1] = read_adc(SELPIN, 1);
Serial.println(ain[0]); //printing the different array value
Serial.println(ain[1]);
Serial.print('\n'); //making it look pretty
delay(500);
}
int read_adc(byte cs, byte channel)
{
int adcvalue = 0;
//it gets a little fuzzy from here
byte commandbits = B11010000; //command bits - start, mode, chn, MSBF //preparing command bits
//allow channel selection
commandbits|=(channel<<5); //shifting the selected channel into the command bits.(probably?)
digitalWrite(cs, LOW); //Select adc
// setup bits to be written //
for (int i=7; i>=4; i--){
digitalWrite(DATAOUT,commandbits&1<<i);
//cycle clock
digitalWrite(SPICLOCK, HIGH);
digitalWrite(SPICLOCK, LOW);
}
digitalWrite(SPICLOCK, HIGH); //ignores 1 null bit
digitalWrite(SPICLOCK, LOW);
//read bits from adc
for (int i=11; i>=0; i--){
adcvalue+=digitalRead(DATAIN)<<i;
//cycle clock
digitalWrite(SPICLOCK, HIGH);
digitalWrite(SPICLOCK, LOW);
}
digitalWrite(cs, HIGH); //turn off device
return adcvalue;
}
This is what I've tried so far and when I open the Serial Monitor...
All I get is the Max value then zeros. And every now and again some random value.
If you were using real SPI you would be connected to D10-11-12-13 and the code would look more like this:
See figure 6-1 & 6-2
digitalWrite (SSpin, LOW);
SPI.transfer(0x01); // 1 is the start bit
upperDAC = SPI.transfer(Bxxx000000); // xxx are the configuration bits, lower 4 bits of upperDAC are D11-D8 from the chip
lowerDAC = SPI.transfer (0x00); // to data to ADC is ignored, lowerDAC contains the D87-D0 from the chip
digitalWrite (SSpin, HIGH;
dataDAC = (upperDAC<<8) + lowerDAC; // put the data together
So I took a good hard look at my code and realized some pretty important things.
First it is code for a DAC and I'm trying to achieve an ADC. (Facepalm.)
I've taken out the DATAOUT, DATAIN and SPICLOCK define in the beginning. (using SPI makes that redundant)
I've taken out the "upperDAC = transfer(goof)" out. and made the lowerDAC into dataDAC.
I am also no longer shifting it.
So after all these changes I loaded up my code and presto!!
Nothing works! now I'm no longer getting garbage, but super garbage!!
I really don't get this chip.
please help.
Here's my code for in case.
// MCP3202 2 channel ADC
// 3202 is different software-wise from 3204/3208 (which are identical)
#include <SPI.h>
#define SELPIN 10
/////////////////////////////////////////////////////////////////////////////
void setup(){
pinMode(SELPIN, OUTPUT);
SPI.begin();
// SPI.setClockDivider(16); // I don't really understand this line.
Serial.begin(9600);
}
void loop(){
byte i;
int ain[2];
ain[0] = read_adc(SELPIN, 2);
ain[1] = read_adc(SELPIN, 1);
Serial.println(ain[0]);
Serial.println(ain[1]);
Serial.print('\n');
delay(500);
}
int read_adc(byte cs, byte channel)
{
int upperADC = 0;
int lowerADC = 0;
int dataADC = 0;
// byte commandbits = B11000000; //command bits - start, mode, chn (3), dont care (3)
byte goof = B11000000; //command bits - start, mode, chn, MSBF
digitalWrite(cs, LOW); //Select adc
SPI.transfer(goof);
SPI.transfer(0x01); //1 is the start bit
dataADC = SPI.transfer(0x00); //receiving the ADC value.
//lowerADC = SPI.transfer(0x00);
digitalWrite(cs, HIGH);
//dataADC = (upperADC<<8) + lowerADC;
return dataADC;
}
See the Figure 6.1. and 6.2. of the datasheet - there is depicted exactly what needs to be done when operating it over SPI (3x8bit transfer)..
For example (not tested):
Thank you Pito for all the help, I really appreciate it.. It was really cool of you to write out a section of code for me. Helped to understand the chip better.. But I'm afraid I still can't get the little bugger to work...
Still no good. Just get some really odd values. But I can't even link it to something... Just random jibberish.
That link you put it... That's actually where I got my original code from.
Double check your wiring (MISO, MOSI, SCK, SS). You need a decoupling capacitor on 3202' Vdd (against gnd).
Connect adc inputs to ground (or Vcc) and print out adc_4h, adc_8l, and adc_value0 and 1.
PS: if you let the analog adc inputs float, you will read garbage..