I am reading it with a Arduino Due using SPI protocol. I am pretty sure I am communicating with it just fine. The problem I am having is putting the 18 bits that I am reading into the proper order. I have tried flipping the bits and throwing away bits but it is not giving me the proper values.
I am using 3.3v to excite and I have a joystick(pot) going into the +IN and -IN is tied to ground. Proportionally I am getting the proper values but the bit values are either too high or too low.
Here is what comes out of my serial terminal.
// This is when the voltage across the pot is 3.3v
11 High
11111111 Mid
11111100 Low
111111111111111100
111111111111111100
ADC Result = 262140
// This is when the voltage across the pot is 1.57
1 High
11101101 Mid
0 Low
1111011010
11110110100000000
ADC Result = 126208
Here is the code I am running:
#include <SPI.h>
const int spiClockDivider = 42;
const int chipSelectPin = 4;
void setup()
{
Serial.begin(19200);
// start the SPI library:
SPI.begin(4);
// Set clock divider to 42
SPI.setClockDivider(chipSelectPin, spiClockDivider);
}
void loop()
{
//transfer 0x00 to the device on pin 4, store byte received in adcByteHigh, keep the chip selected
byte adcByteHigh = SPI.transfer(4, 0x00, SPI_CONTINUE);
//adcByteHigh &= 0b00000011; // Tried excluding some bits but not sure which ones
//transfer 0x00 to the device on pin 4, store byte received in adcByteMid, keep the chip selected
byte adcByteMid = SPI.transfer(4, 0x00, SPI_CONTINUE);
//transfer 0x00 to the device on pin 4, store byte received in adcByteLow, deselect the chip
byte adcByteLow = SPI.transfer(4, 0x00);
//adcByteHigh &= 0b11000000; // Tried excluding some bits but not sure which ones
//combine the three parts into one 18-bit number:
long ADCresult = ((adcByteHigh << 16) | (adcByteMid << 8) | adcByteLow );
// display the ADC value:
Serial.print(adcByteHigh, BIN);
Serial.println(" High");
Serial.print(adcByteMid, BIN);
Serial.println(" Mid");
Serial.print(adcByteLow, BIN);
Serial.println(" Low");
Serial.print(adcByteHigh, BIN);
Serial.print(adcByteMid, BIN);
Serial.println(adcByteLow, BIN);
Serial.println(ADCresult, BIN);
Serial.println("\tADC Result = " + String(ADCresult));
delay(500);
}
Please help me combine the bits in the proper order Thanks.
-Ryman
I think your results are only off by a factor of 4, so easy to fix
The way I understand the datasheet page 5 is that you do 3 times an 8 bit SPI transfer, like you do in your programm. Of the 24 bits you receive, the interesting ones are bits 7 to 22 (counting direction like in the datasheet assumed). So replacing the line in your code like this should do the job I guess:
so you get rid of bits 23 and 24 on the right side using (adcByteLow>>2), and you fill accordingly up to bit 16. About the bits 1 to 6 you don't care as long as they are always zero.. did you verify this?
to be secure, you might add something like this before:
adcByteHigh &= 0b00000011;
so you erase bits 1-6 and leave bits 7 and 8 unchanged of adcByteHigh
Let me know if it works! and thanks for posting the device name and datasheet link
That could not have been easier. I just changed that one line and then uncommented the other and it worked perfectly. Thank you very much. Now lets add 24 more of them...
I have another question about the same code except I added too it. I am trying to get a sense of the sampling rates that I can achieve so I made a "simulator" code with one ADC and polling it 24 times then writing it. This is working kind of but after the first read I get 3.30000 volts everytime ehich is not correct. I tried rezeroing all the channels but that doesn't work. Not sure what else to change. Am I filling up the memory with this method too, with a memory leak?
#include <SPI.h>
const int spiClockDivider = 42;
const int chipSelectPin = 4;
const int numChannels = 24;
long ADCresult[numChannels];
float ADCvolts[numChannels];
void setup()
{
Serial.begin(115200);
// start the SPI library:
SPI.begin(4);
// Set clock divider to 42
SPI.setClockDivider(chipSelectPin, spiClockDivider);
for (int makeChannel = 0; makeChannel < numChannels; makeChannel++)
{
ADCresult[makeChannel] = 0;
ADCvolts[makeChannel] = 0;
}
}
void loop()
{
unsigned int time = 0;
time = micros();
for (int readChannel = 0; readChannel <= numChannels; readChannel++)
{
//transfer 0x00 to the device on pin 4, store byte received in adcByteHigh, keep the chip selected
byte adcByteHigh = SPI.transfer(4, 0x00, SPI_CONTINUE);
adcByteHigh &= 0b00000011;
//transfer 0x00 to the device on pin 4, store byte received in adcByteMid, keep the chip selected
byte adcByteMid = SPI.transfer(4, 0x00, SPI_CONTINUE);
//transfer 0x00 to the device on pin 4, store byte received in adcByteLow, deselect the chip
byte adcByteLow = SPI.transfer(4, 0x00);
//combine the two parts into one 18-bit number:
ADCresult[readChannel] = ((adcByteHigh << 14) | (adcByteMid << 6) | (adcByteLow >> 2));
ADCvolts[readChannel] = 3.3 * ((float)ADCresult[readChannel]/65535);
//delayMicroseconds(10);
//delay(500);
}
time = micros() - time;
// display the ADC value:
//Serial.println(ADCresult, BIN);
//Serial.print("Vertical joystick Voltage = ");
for (int printChannel = 0; printChannel <= numChannels; printChannel++)
{
Serial.println(ADCvolts[printChannel], 6);
}
//Serial.println(" [Volts]");
Serial.println(time, DEC);
delay(1000);
}