SPI Assistance

Hi Friends,

I'm following along with a tutorial found here: sample code for LTC2440 24-bit ADC

The tutorial shows how to interface at 24 bit analog to digital converter (LTC2440) with an Arduino utilizing the SPI bus. It works great, but one piece of the puzzle is messing me up. In the code below, there's a delay(150) at line 65. I want to integrate some pushbuttons for a couple menu options, but that delay is creating a long response time when pressing the buttons. With the delay in there, the program stops scanning for 150ms, and during that delay, the processor doesn't see any buttons being pressed. I've scoured the datasheet, found here Mixed-signal and digital signal processing ICs | Analog Devices, but cannot find any reason to have the delay in the program. I tried removing it, but then the ADC stops working. Can anyone shed some insight as to what is happening? Does anyone know how to remove the delay and keep the ADC working?

Thanks for the help.

Here's the code:

    /*
      Interface between Arduino DM board and Linear Tech LTC2440 24-bit ADC
      Nov. 12 2010 John Beale

       LTC2440  <---------->  Arduino
       11: /CS <- to digital pin 10  (SS pin)
        7: MOSI <- to digital pin 11 (MOSI pin)
       12: MISO -> to digital pin 12 (MISO pin)
       13: SCLK <- to digital pin 13 (SCK pin)
       10: /EXT - ground
        1: GND - ground
        2: VDD3 - 5V supply

    */
#include <LiquidCrystal.h>

    #include <SPI.h>  // include the SPI library
LiquidCrystal lcd(3,4,5,6,7,8); 
int ledPin = 2;
#define GREENLITE 9
    // set I/O pins used in addition to clock, data in, data out
    const byte slaveSelectPin = 10;  // digital pin 10 for /CS
    const byte resetPin = 9;  // digital pin 9 for /RESET
    const int nsamples = 5;  // how many ADC readings to average together

    // SPI_CLOCK_DIV16 gives me a 1.0 MHz SPI clock, with 16 MHz crystal on Arduino

    void setup() {
     pinMode(ledPin, OUTPUT);
      pinMode(GREENLITE, OUTPUT);
        Serial.begin(9600);      // set up serial comm to PC at this baud rate
        lcd.begin(20, 4);
        pinMode (slaveSelectPin, OUTPUT);
        pinMode (resetPin, OUTPUT);
        digitalWrite(slaveSelectPin,HIGH);  // chip select is active low
        digitalWrite(resetPin,HIGH);  // reset is active low

        SPI.begin(); // initialize SPI, covering MOSI,MISO,SCK signals
        SPI.setBitOrder(MSBFIRST);  // data is clocked in MSB first
        SPI.setDataMode(SPI_MODE0);  // SCLK idle low (CPOL=0), MOSI read on rising edge (CPHI=0)
        SPI.setClockDivider(SPI_CLOCK_DIV16);  // system clock = 16 MHz, chip max = 1 MHz
       
        Serial.println("LTC2440 Test");
    }

    // =============================================================================
    // Main Loop:
    // acquire 'nsamples' readings, convert to units of volts, and send out on serial port

    void loop() {
analogWrite(ledPin, 125);
 analogWrite(GREENLITE, 0);//Turns Green LED ON
    int i;
    long secs;
    float mins;
    double volts;
    long in;         // incoming serial 32-bit word
    long sum = 0;

        for (i=0; i<nsamples; i++) {
          in = SpiRead();
          in &= 0x1FFFFFFF; // force high three bits to zero
          in = in>>5;   // truncate lowest 5 bits
          sum += in;
          delay(150);      // (msec). Total Looptime: +2 msec (overhead for comms)
        }

        // volts =  in * 2.5 / 8.388607;  // 0x7fffff = 8388607
        volts = sum * (0.2980232594);  // microvolts
        volts = volts / nsamples;

        mins = (float) millis() / 60000;   // elapsed time in minutes
        Serial.print(mins); 
        Serial.print(", ");
        Serial.println(sum);
lcd.setCursor(0,2);
lcd.print("AnalogIn:");
lcd.setCursor(9,2);
lcd.print(sum); 
    } // end main loop


    // =================================================================
    // SpiRead() -- read out 4 bytes from LTC2440 chip via SPI interface
    // =================================================================

    long SpiRead(void) {

      long result = 0;
      long b;
     
    //  long result2 = 0;// MOSI/SDI pin 7 HIGH => 7 Hz, best resolution

      digitalWrite(slaveSelectPin,LOW);   // take the SS pin low to select the chip
      delayMicroseconds(1);              // probably not needed, only need 25 nsec delay
     
      b = SPI.transfer(0xff);   // B3
      result = b<<8;
      b = SPI.transfer(0xff);   // B2
      result |= b;
      result = result<<8;
      b = SPI.transfer(0xff);   // B1
      result |= b;
      result = result<<8;
      b = SPI.transfer(0xff);   // B0
      result |= b;
     
      // take the SS pin high to de-select the chip:
      digitalWrite(slaveSelectPin,HIGH);
      return(result);
    }

Look for the "blink without delay" example in the IDE (file, Examples, Digital). It shows how to use millis() to time the execution of your program. Using that technique you can scan for pushbuttons while the "delay" takes place.

I'll check it out. Thanks!

Rewrite it some, I'd go with this. May need a little tweak for the flow.

/*
Interface between Arduino DM board and Linear Tech LTC2440 24-bit ADC
Nov. 12 2010 John Beale

LTC2440 <----------> Arduino
11: /CS <- to digital pin 10 (SS pin)
7: MOSI <- to digital pin 11 (MOSI pin)
12: MISO -> to digital pin 12 (MISO pin)
13: SCLK <- to digital pin 13 (SCK pin)
10: /EXT - ground
1: GND - ground
2: VDD3 - 5V supply

*/
#include <LiquidCrystal.h>

#include <SPI.h> // include the SPI library
LiquidCrystal lcd(3,4,5,6,7,8); 
int ledPin = 2;
#define GREENLITE 9
// set I/O pins used in addition to clock, data in, data out
const byte slaveSelectPin = 10; // digital pin 10 for /CS
const byte resetPin = 9; // digital pin 9 for /RESET
const int nsamples = 5; // how many ADC readings to average together

// SPI_CLOCK_DIV16 gives me a 1.0 MHz SPI clock, with 16 MHz crystal on Arduino

int i;
long secs;
float mins;
double volts;
long in; // incoming serial 32-bit word
long sum = 0;

void setup() {
pinMode(ledPin, OUTPUT);
pinMode(GREENLITE, OUTPUT);
Serial.begin(9600); // set up serial comm to PC at this baud rate
lcd.begin(20, 4);
pinMode (slaveSelectPin, OUTPUT);
pinMode (resetPin, OUTPUT);
digitalWrite(slaveSelectPin,HIGH); // chip select is active low
digitalWrite(resetPin,HIGH); // reset is active low

SPI.begin(); // initialize SPI, covering MOSI,MISO,SCK signals
// DEFAULT STATES:
// SPI.setBitOrder(MSBFIRST); // data is clocked in MSB first  
// SPI.setDataMode(SPI_MODE0); // SCLK idle low (CPOL=0), MOSI read on rising edge (CPHI=0)

SPI.setClockDivider(SPI_CLOCK_DIV16); // system clock = 16 MHz, chip max = 1 MHz

Serial.println("LTC2440 Test");
}

// =============================================================================
// Main Loop:
// acquire 'nsamples' readings, convert to units of volts, and send out on serial port

void loop() {
analogWrite(ledPin, 125);
analogWrite(GREENLITE, 0);//Turns Green LED ON

currentTime = millis();
if ( (currentTime - nextTime) >= 150){ // time for next sample

if (i <= 6){  // take a sample
i = i+1; // update for next pass

// long result2 = 0;// MOSI/SDI pin 7 HIGH => 7 Hz, best resolution
// =================================================================
// SpiRead() -- read out 4 bytes from LTC2440 chip via SPI interface
// =================================================================
digitalWrite(slaveSelectPin,LOW); // take the SS pin low to select the chip
delayMicroseconds(1); // probably not needed, only need 25 nsec delay

b = SPI.transfer(0xff); // B3
result = b<<8;
b = SPI.transfer(0xff); // B2
result |= b;
result = result<<8;
b = SPI.transfer(0xff); // B1
result |= b;
result = result<<8;
b = SPI.transfer(0xff); // B0
result |= b;
// take the SS pin high to de-select the chip:
digitalWrite(slaveSelectPin,HIGH);

in = result;  // or replace "in" with "result" in the next 3 lines
in &= 0x1FFFFFFF; // force high three bits to zero
in = in>>5; // truncate lowest 5 bits
sum += in;
}
else {
averageFlag =1;  // do the volts math
i=0; // reset sample count
}
if (averageFlag == 1){  // perform an average
averaageFlag = 0; // clear for next time
// volts = in * 2.5 / 8.388607; // 0x7fffff = 8388607
volts = sum * (0.2980232594); // microvolts
volts = volts / nsamples;

} // what do with volts answer?
mins = (float) millis() / 60000; // elapsed time in minutes
Serial.print(mins); 
Serial.print(", ");
Serial.println(sum);
lcd.setCursor(0,2);
lcd.print("AnalogIn:");
lcd.setCursor(9,2);
lcd.print(sum); 

} // end main loop

Also:

void loop() {
analogWrite(ledPin, 125);
analogWrite(GREENLITE, 0);//Turns Green LED ON

Does the light ever get turned off? If not, move the analogWrites to the end of void setup. Otherwise its just a time waster in void loop.

Will do. Thanks for the help.