1

I am having trouble configuring Arduino Due SPI to an AD7490 ADC.

Here is how I have the pins connected:

  • +3.3V > 7490 pin 22 Vin
  • +3.3V > 7490 Vref
  • DUE CS (8) > 7490 pin 20 SS - slave select)
  • DUE SCK > 7490 pin 16 (SCK - clock)
  • DUE MOSI > 7490 pin 19 (MOSI - data out)
  • Ground > 7490 pin 24 (all ground lines are tied together)
  • DUE MISO > 7490 pin 15

Below is my code, I feel like I am writing the correct bits into the register. The problem I think I'm having is getting the timing write. The code is a simple attempt to read a single channel.

#include <SPI.h>

// Set Constants
const int adcChipSelectPin = 8;      // set pin 8 as the chip select for the 
ADC:

// Start setup function:
void setup() {

pinMode (adcChipSelectPin, OUTPUT);
// set the ChipSelectPins high initially:
digitalWrite(adcChipSelectPin, HIGH);
// initialise SPI:
SPI.begin();
SPI.setBitOrder(MSBFIRST);         // Not strictly needed but just to be 
sure.
SPI.setDataMode(SPI_MODE0);        // Not strictly needed but just to be 
sure.
Serial.begin(9600);
//Clock Speed: Master clock/divider
//84Mhz/64 =  1.3 MHz
SPI.setClockDivider(SPI_CLOCK_DIV64);

} // End setup function.

// Start loop function:
void loop() {
float voltage[2];
for (int i = 0; i < 3; i++) {
voltage[i] = readAdc(0, 0);
}


}// End of loop function.

//Function to read the ADC, accepts the channel to be read.
float readAdc(int channel, int slave) {

float value;
if (slave == 0) {
noInterrupts(); // disable interupts to prepare to send address data to the 
ADC.
digitalWrite(adcChipSelectPin, LOW); // take the Chip Select pin low to 
select the ADC.


byte FirstByte = 0b10000011;    
byte SecondByte = 0b00110000;      

SPI.transfer(FirstByte);

byte response1 = SPI.transfer(SecondByte);
byte response2 = SPI.transfer(0x00);

digitalWrite(adcChipSelectPin, HIGH); // take the Chip Select pin high to 
de-select the ADC.
interrupts(); // Enable interupts.
Serial.println(response1);
Serial.println(response2);

}

The serial.prints output 255 consistently. In my experience this means the SPI is configured incorrectly.

Any pointers are appreciated.

12
  • I don't think the communication is like what you wrote here. It looks like it is sending the data with the next byte. Try with SPI.transfer(FirstByte); SPI.transfer(SecondByte); digitalWrite(adcChipSelectPin, HIGH); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); digitalWrite(adcChipSelectPin, LOW); byte response1 = SPI.transfer(0x00); byte response2 = SPI.transfer(0x00);. The five nops are for respecting the 50nm "t_quiet" time requested in the datasheet
    – frarugi87
    Commented Nov 9, 2018 at 15:25
  • (of course if this work you can avoid using the 0x00 writings and concatenate successive requests; for instance something like (using only one SPI.transfer instead of two, and some pseudo-code) SPI.transfer(read channel 0); CS high, nops, CS low; byte result_ch0 = SPI.transfer(read channel 1); CS high, ..[repeat as many times you need].. , CS low; byte result_chN = SPI.transfer(0x00);
    – frarugi87
    Commented Nov 9, 2018 at 15:31
  • I tried your suggestion and am still getting the same response as before unfortunately. I'm not sure what the issue could be at this point.
    – Flux
    Commented Nov 9, 2018 at 16:39
  • Did you try to measure the value of voltage on the MISO pin? is it 3.3V stable or it is lower? Can you try disconnecting it from the ADC and measure the voltage on the microcontroller MISO? Can you try to put a 10k resistor between MISO and GND?
    – frarugi87
    Commented Nov 9, 2018 at 16:51
  • The voltage on my MISO pin is only about .8V DC. When I disconnect from ADC I read a voltage of about .8V.
    – Flux
    Commented Nov 9, 2018 at 17:12

1 Answer 1

1

For anyone else who comes across the same problem, this worked for me:

// include the library code:
#include <SPI.h>

// Set Constants
const int adcChipSelectPin = 8;      // set pin 8 as the chip select for the ADC:

// Start setup function:
void setup() {
    pinMode (adcChipSelectPin, OUTPUT);

    // set the ChipSelectPins high initially:
    digitalWrite(adcChipSelectPin, HIGH);

    // initialise SPI:
    SPI.begin();
    SPI.setBitOrder(MSBFIRST);         // Not strictly needed but just to be sure.
    SPI.setDataMode(SPI_MODE0);        // Not strictly needed but just to be sure.
    Serial.begin(9600);

    //Clock Speed: Master clock/divider
    //84Mhz/64 =  1.3 MHz
    SPI.setClockDivider(SPI_CLOCK_DIV64);

    //Send dummy values over when ADC is turned on 
    //Hold Din High for 16 clock cycles twice 
    digitalWrite(adcChipSelectPin, LOW);
    SPI.transfer(0xFF);
    SPI.transfer(0xFF);
    digitalWrite(adcChipSelectPin, HIGH);

    digitalWrite(adcChipSelectPin, LOW);
    SPI.transfer(0xFF);
    SPI.transfer(0xFF);
    digitalWrite(adcChipSelectPin, HIGH);
    asm volatile("nop"); 
    asm volatile("nop"); 
    asm volatile("nop"); 
    asm volatile("nop"); 
    asm volatile("nop"); 
    //Send dummy values, next read should have correct values

    digitalWrite(adcChipSelectPin, LOW);
    byte FirstByte = 0x83;
    byte SecondByte = 0x50;
    byte response1 = SPI.transfer(FirstByte); 
    byte response2 = SPI.transfer(SecondByte); 

    digitalWrite(adcChipSelectPin, HIGH);

    asm volatile("nop"); 
    asm volatile("nop"); 
    asm volatile("nop"); 
    asm volatile("nop"); 
    asm volatile("nop"); 
    ///////////////////////////////////////////////////////////////////////////////////

    //50ns quiet time?
    asm volatile("nop"); 
    asm volatile("nop"); 
    asm volatile("nop"); 
    asm volatile("nop"); 
    asm volatile("nop"); 
} // End setup function.

// Start loop function:
void loop() {
    float voltage[2];
    for (int i = 1; i < 17; i++) {
        voltage[i] = readAdc(0, 1);
        //50ns quiet time? 
        asm volatile("nop"); 
        asm volatile("nop"); 
        asm volatile("nop"); 
        asm volatile("nop"); 
        asm volatile("nop"); 
    }
} // End of loop function.

//Function to read the ADC, accepts the channel to be read.
float readAdc(int channel, int slave) {
    float value;
    if (slave == 0) { 
        byte FirstByte = 0x83;
        byte SecondByte = 0x50;
        FirstByte |= channel << 2;

        noInterrupts(); // disable interupts to prepare to send address data to the ADC.

        digitalWrite(adcChipSelectPin, LOW); // take the Chip Select pin low to select the ADC.
        //Write = 1
        //SEQ = 0
        // ADD3-ADD0 = 0000
        //PM1 = PM0 = 1
        //Shadow = 0
        //WEAK/Tri = 1
        //Range = 0
        //Coding = 1
        //0b10000010 1010 0000
        //extra 4 zeros to fill

        //May need to wait 16 * (1/freq)
        //16 * (1/1.3MHz) 
        byte response1 = SPI.transfer(FirstByte); 
        byte response2 = SPI.transfer(SecondByte); 
        digitalWrite(adcChipSelectPin, HIGH);     

        interrupts(); // Enable interupts.

        //Serial.println(response1);
        Serial.println(response2);
        byte channel = (response1 >> 4);
        //byte value = (response1 << 4);
        //byte digitalValue = (response1 << 4) | response2; 
        //Serial.println(digitalValue);
        //Serial.println(channel);

        byte digitalValue = 0x00;
        float value = (float(digitalValue) * 3.3) / 4096.000; // The digital value is 
        converted to an analogue voltage using a VREF of 2.048V.
        //Serial.print(channel);
        //Serial.print("\t");
        //Serial.println(value);
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.