I have been using the MCP3302 as a 4-channel ADC with a project I've been working on. If I use the Playground example, I can get numbers but there are weird issues with dropping the LSB of the upper word (the 256 place) when the lower word is mostly ones. I would expect to see around 1000 but get something like 768.
I changed my code to do direct port manipulation instead of using digital.Write and it seems to work perfectly. I am using the standard pins for SPI (10-13.) This code will probably not work on the Mega since I'm running the ports directly, YMMV. It's a lot faster than the Playground code, too.
It's probably easier to do this in 0019 using the new SPI library but I haven't tried it yet. I'm also not sure if you can use more than one SPI device with the 0019 library. I imagine you can but it seems to indicated that 10 is SS and can't be changed...
The commented lines are from the Playground code, and have been replaced by high-octane bit toggling. Code follows:
// ADC Reading function
// modified from http://www.arduino.cc/playground/Code/MCP3208
// changed reading routine to request 13 bits instead of 12
// Changed all (slow) digitalWrite and digitalRead to (much faster)
// direct port manipulation
int read_adc(int channel, int oversample){
int adcvalue = 0;
int oversampleAvg = 0;
for (int i=oversample; i>0; i--){
byte commandbits = B11000000; //command bits - start, mode, chn (3), dont care (3)
//allow channel selection
commandbits|=((channel-1)<<3);
//Select adc
bitWrite(PORTB, 2, LOW); //pull CS low to enable
// setup bits to be written
for (int i=7; i>=3; i--){
bitWrite(PORTB, 3, (commandbits & 1 << i)); // shift command bits out PORTB 3, DATAOUT
//cycle clock
bitWrite(PORTB, 5, HIGH);
bitWrite(PORTB, 5, LOW);
}
//cycle clock twice, ignore two null bits
bitWrite(PORTB, 5, HIGH);
bitWrite(PORTB, 5, LOW);
bitWrite(PORTB, 5, HIGH);
bitWrite(PORTB, 5, LOW);
//read bits from adc
for (int i=12; i>=0; i--){
oversampleAvg += (bitRead(PINB, 4) << i);
//cycle clock
bitWrite(PORTB, 5, HIGH);
bitWrite(PORTB, 5, LOW);
}
bitWrite(PORTB, 2, HIGH);
adcvalue += oversampleAvg;
}
adcvalue /= oversample;
return adcvalue;
}
This defaults to single-ended mode, but if you want to use the ADC in differential you'd need to change the command word from B11000000 to B10000000. I think you can use this code as-is with the 3301, but it's only been tested with the 3302. I also added in the oversampling bits, this reads the ADC several times and returns the average. The 330X series should output 0-4095 in single-ended (12-bit) mode, just take care that oversampleAvg doesn't get too big for an int. With full-scale values, you could theoretically sample 8 times but that's it. I sample 4 times to reduce the jitter on the last couple of bits.
If you find a slick way to do this with the SPI library, post it here! This is just the best I could come up with.