SPI interface for analog to digital converter MCP3202

this is my first post here; I couldn't tack my question on to an old related thread http://arduino.cc/forum/index.php/topic,18827.0.html because it was read-only.

I am trying to use an analog to digital converter, the MCP3202, to read voltages from a thermistor, the TMP36, and print the resulting digital conversion to the serial monitor.

I consulted and used the sketch on the playground for the MCP3208 (though it supposedly should work for the 3202 just fine):
http://www.arduino.cc/playground/Code/MCP3208

When bypass the ADC to check things (and run the thermistor straight to the arduino's 10bit analog read), I get values around 154 (out of 1024 for 10bit) which translates nicely to ~78 deg F right where I sit. This is good.

When I run the thermistor through the ADC to the arduino, per the plan, I get values around 2600 (out of 4096 for 12 bit resolution). The value should be closer to 616 to agree with the last paragraph.

Also strangely, Ch1 gives the same values of 2600 (moves in concert with Ch0), but I have that connected straight to 5V.

I checked the pin connections to the ADC, consulting the datasheet; I have 5V going to the Vref, 0V going to the Vss, the out from the arduino going to the Din of the ADC, and the IN for the arduino going to the Dout of the ADC. I have the thermistor connected to channel 0, and channel 1 connected to 5V as mentioned above. And the clock connected of course.

So far as I can tell, I did not deviate from the example sketch (link provided above) for any of the ADC interface. Others reported luck with this code, so I'm baffled.

questions:

  1. anyone know what I'm doing wrong?
  2. aux: why does the loop in read_adc() that collects the bits from the ADC run from 11 to 1 (only 11 bits) instead of 11 to 0?
  3. aux: is it necessary to include the DEC mode when printing the value to serial?

much thanks for this great resource,
matt

here is my sketch:

/*	Filename: Matt01_TemperatureLoggerD.pde
	Language: Arduino
	Created: 3/6/11
	Purpose: 
		1. basic serial output of data to be handled by a processing sketch		
		2. add a handshake algorithm so that arduino only sends data when it is requested
		by the processing sketch
		3. add an ADC to serve as middleman between the sensor (thermistor) and the arduino,
		in order to gain increased resolution 
*/

//We are using a TMP36 thermistor. 
//Resolution is 10mV/deg C
//500mV offset to make negative temperatures an option

//The thermistor is connected to an MCP3202 analog to digital converter
//The ADC is 12 bits, so it will take the voltage 0-5V from the thermistor and convert
//it to a value 0-4096, expressed as 12 bits of data that we must program the arduino to 
//manually read in each individual bit and reassemble it into an integer for us
 
//PIN assignments for the ADC interface
//the chip select pin is pulled low to initiate communication (each time)
//the dataout pin of the arduino goes to the ADC's Din; it is used to configure the mode
//the datain pin of the arduino receives the 12 bits representing the digital conversion
//the clock chip is used to time the sending/receiving of each bit on the datain port
#define SELPIN 10 	//Selection Pin (CS/SHDN)
#define DATAOUT 11	//Data in  (Din)
#define DATAIN 12	//Data out (Dout)
#define SPICLOCK 13	//Clock (CLK)
int readvalue;
						
//the setup function runs once at the beginning
void setup(){
	//set pin modes
	pinMode(SELPIN, OUTPUT);
	pinMode(DATAOUT, OUTPUT);
	pinMode(DATAIN, INPUT);
	pinMode(SPICLOCK, OUTPUT);
	
	//disable device to start with
	digitalWrite(SELPIN,HIGH);
	digitalWrite(DATAOUT,LOW);
	digitalWrite(SPICLOCK,LOW);
	
	Serial.begin(9600);		//Start the serial connection for communication with the computer
}



//the loop function loops continuosly
void loop(){
	//wait to do anything until there is a byte available to be read in the serial buffer,
	//which was sent by processing
	//this makes the arduino wait until it receives a message from processing before doing 
	//another iteration of this loop
	if(Serial.available() > 0){
		
		//first, clear the serial buffer
		//this is accomplished by reading it into a variable
		//also, for some reason I don't understand, this has to be done a second time
		//at the end of the loop in order for the arduino not to send two sets of data
		//each time
		Serial.read();
		
		//read from the ADC and print to the serial port, separated by commas and ending
		//with a linefeed (ASCII value of 10)
		//This is the general code for two sensors; in this case we only have one but
		//we'll leave the code 
		readvalue = read_adc(1);
		Serial.print(readvalue,DEC);		
		Serial.print(",");
		readvalue = read_adc(2);
		Serial.println(readvalue,DEC);
		
		//might have to give the adc some time to clear (true?  if so, what's the min?)
		delay(250);
		
		//must read from the serial buffer again for some reason to clear it, in order
		//to not output two readings for every character sent by the processing sketch
		//(i.e. this is an adjustment for proper hand-shaking)		
		Serial.read();		
	}	
}

//read_adc() communicates with the ADC--sets it up and collects the data from it, returns it
//it will be a number 0-4095 (12 bit resolution)
//feed read_adc() an argument of 1 or 2 to tell it which channel to read
int read_adc(int channel){
    int adcvalue = 0;				//a variable to hold the digital value given by the ADC
    byte commandbits = B11000000; //command bits - start, mode, chn (3), dont care (3)

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

    digitalWrite(SELPIN,LOW); //turn on adc
	// setup bits to be written
  
	//send the command setup to the chip:
	//first bit is a start message
	//second bit tells it to use single-ended mode (rather than differential)
	//third bit tells it what channel to look at
	for (int i=7; i>=3; i--){
	    digitalWrite(DATAOUT,commandbits&1<<i);
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);
    }

	//cycle clock up and down twice to ignore 2 null bits
  	digitalWrite(SPICLOCK,HIGH);   
  	digitalWrite(SPICLOCK,LOW);
  	digitalWrite(SPICLOCK,HIGH);
  	digitalWrite(SPICLOCK,LOW);

  	//now read bits from adc
  	//??why does it only read in 11 bits instead of 12? should this be "=" instead of ">="?
  	for (int i=11; i>=0; i--){
    adcvalue+=digitalRead(DATAIN)<<i;
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);
    
  }
  digitalWrite(SELPIN, HIGH); //turn off device
  return adcvalue;
}

I would put a print in the for loop to see exactly how many times it is iterated.

But also I've been caught with this sort of thing in the past by shifting stuff at the wrong time.

I can't see anything wrong with your code but try

adcvalue <<= 1;
adcvalue != digitalRead(DATAIN);

inside the loop.


Rob

I fell into the same trap. The MCP3204 and MCP3208 are identical. I've been told the new MCP3201 is identical to the 3204/8.

The MCP3202, however, is different. I don't remember the details, but I do remember it biting me in the butt.

Here is some working code that talks to an MCP3202:

http://www.eng.uah.edu/~jdw/avr/ttpv.pde

http://www.eng.uah.edu/~jdw/avr/radioshield_rocket_tracker.pde

-j

that fixed it! much thanks, really appreciate it

Could you update the entire code?
I'm trying to read a voltage value from a Buck converter with the ADC I don't know how to do it. Could you help me, please?
Thanks!!!!

albale96:
Could you update the entire code?
I'm trying to read a voltage value from a Buck converter with the ADC I don't know how to do it. Could you help me, please?
Thanks!!!!

see example code here: