LTC2400 ADC apply on Arduino Due

Hello,

I am currently design a pressure sensor system and want to add this LTC2400 ADC into the system to have a better reading.
I have read through the LTC2400 tutorial on line, and tried on Arduino Uno. It works perfectly, now I want to apply it onto Arduino Due.
http://interface.khm.de/index.php/lab/experiments/connect-a-ltc2400-high-precision-24-bit-analog-to-digital-converter/

The code doesn't seem working for Arduino Due, following errors shown. And I am also confused about those SCK, SDO and CS connections with Arduino Due board.Which pins should I connect those into, and how to clarify them in the program. Appreciate any little help.

ADC_Uno_ino.ino: In function 'void setup()':
ADC_Uno_ino:26: error: 'PORTB' was not declared in this scope
ADC_Uno_ino:26: error: '_SFR_BYTE' was not declared in this scope
ADC_Uno_ino:26: error: '_BV' was not declared in this scope
ADC_Uno_ino:27: error: 'DDRB' was not declared in this scope
ADC_Uno_ino:34: error: 'SPCR' was not declared in this scope
ADC_Uno_ino:34: error: 'MSTR' was not declared in this scope
ADC_Uno_ino:35: error: 'SPR0' was not declared in this scope
ADC_Uno_ino:36: error: 'SPR1' was not declared in this scope
ADC_Uno_ino:37: error: 'SPE' was not declared in this scope
ADC_Uno_ino.ino: In function 'void loop()':
ADC_Uno_ino:54: error: 'PORTB' was not declared in this scope
ADC_Uno_ino:54: error: '_SFR_BYTE' was not declared in this scope
ADC_Uno_ino:54: error: '_BV' was not declared in this scope
ADC_Uno_ino:56: error: 'PINB' was not declared in this scope
ADC_Uno_ino:56: error: 'PORTB4' was not declared in this scope
ADC_Uno_ino.ino: In function 'byte SPI_read()':
ADC_Uno_ino:97: error: 'SPDR' was not declared in this scope
ADC_Uno_ino:98: error: 'SPSR' was not declared in this scope
ADC_Uno_ino:98: error: 'SPIF' was not declared in this scope

That sketch is written for an ATmega based Arduino. On a Due you cannot use the direct port manipulation commands of the ATmega platform, so you have to rewrite the sketch to use digitalWrite() instead of the port manipulations and the SPI library instead of the register manipulations in the sketch.

Appreciate your reply.
So, to use digitalWirte to set low or high for SCK and use digitalRead to read data from SDO? I am very new to Arduino, this gona be difficult for me to rewrite without similar examples.
And also I am not sure about how to connect those pins on ADC to SPI on Due since usually they are MISO, MOSI, SCK when using SPI. Do you have any thoughts on that?

Regards,
Danny

cbi(PORTB,LTC_SCK);      // LTC2400 SCK low

gets

digitalWrite(SCKL, LOW);
sbi (DDRB,LTC_CS);       // LTC2400 CS HIGH

(the comment is wrong!) gets

pinMode(SS, OUTPUT);
cbi (DDRB,LTC_MISO);
sbi (DDRB,LTC_SCK);

gets

pinMode(MISO, INPUT);
pinMode(SCKL, OUTPUT);

but all that stuff is not necessary, it's all in

SPI.begin();

The relevant parts replaced could look like this (not tested, just a quick hack, I don't have the hardware):

#include <SPI.h>

void setup() {

 pinMode(SS, OUTPUT);
 digitalWrite(SS, HIGH);
 SPI.begin();

 Serial.begin(57600);
 Serial.println("LTC2400 ADC Test");

}
float volt;
float v_ref=3.0;          // Reference Voltage, 5.0 Volt for LT1021 or 3.0 for LP2950-3

long int ltw = 0;         // ADC Data ling int
int cnt;                  // counter
byte b0;                  //
byte sig;                 // sign bit flag
char st1[20];             // float voltage text

/********************************************************************/
void loop() {

 digitalWrite(SS, LOW);
 delayMicroseconds(1);
 if (digitalRead(MISO) == LOW) {   // ADC Converter ready ?
   ltw=0;
   sig=0;

   b0 = SPI_read();             // read 4 bytes adc raw data with SPI
   if ((b0 & 0x20) ==0) sig=1;  // is input negative ?
   b0 &=0x1F;                   // discard bit 25..31
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;

   delayMicroseconds(1);

   digitalWrite(SS, HIGH);      // LTC2400 CS HIGH
   delay(200);

   if (sig) ltw |= 0xf0000000;    // if input negative insert sign bit
   ltw=ltw/16;                    // scale result down , last 4 bits have no information
   volt = ltw * v_ref / 16777216; // max scale

   Serial.print(cnt++);
   Serial.print(";  ");
   printFloat(volt,6);           // print voltage as floating number
   Serial.println("  ");

 }
 digitalWrite(SS, HIGH); // LTC2400 CS hi
 delay(20);

}
/********************************************************************/
byte SPI_read()
{
 return SPI.transfer(0x00);
}
/********************************************************************/

This assumes that the chip is connected to SPI with the standard pins (SDO -> MISO, SCK -> SCKL, CS -> SS).

It works! Thank you so much!
I only added one line to clarify which pin SS connect to.
const int SS = 4;
It is reading out the Vout from my pressure sensor now!

However, since both my SD card module (to log data) and this ADC need to use SPI on Due. I only know one SPI which is located in the middle of the board. Is ICSP another SPI or is there any solution so that I can use both these devices?

Regards,
Danny

I realise that Due could communicate with more than one device through SPI. Each device could have its own SS which are pin 4, 10 and 52 for Due. But my question is I will need both these devices work (ADC do the converting and SD storage do the logging data) for the most of time. When I enable both of them, they will share SPI. Will it be alright?

Regards,
Danny

Below is my code, I tried to enable both ADC and SD card module but couldn't get it work.
When they are separate, they both work fine.
Could anyone check it for me to see what did I write wrong or it's not the right way to use SPI for two device?

/*
#include <SPI.h>
#include <SD.h>
#include <LiquidCrystal.h>


const int SDCS = 4;
const int ADCCS = 10;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


void setup()
{
    pinMode(ADCCS, OUTPUT);
    digitalWrite(ADCCS, HIGH);
    SPI.begin();
    lcd.begin(16, 2);
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  Serial.print("Initializing SD card...");
  
  // see if the card is present and can be initialized:
  if (!SD.begin(SDCS)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
}

float volt;
float v_ref=5.0;          // Reference Voltage, 5.0 Volt for LT1021 or 3.0 for LP2950-3

long int ltw = 0;         // ADC Data ling int
int cnt;                  // counter
byte b0;                  //
byte sig;                 // sign bit flag
char st1[20];             // float voltage text

void loop()
{
  digitalWrite(ADCCS, LOW);
  delayMicroseconds(1);
   if (digitalRead(MISO) == LOW) {   // ADC Converter ready ?
   ltw=0;
   sig=0;

   b0 = SPI_read();             // read 4 bytes adc raw data with SPI
   if ((b0 & 0x20) ==0) sig=1;  // is input negative ?
   b0 &=0x1F;                   // discard bit 25..31
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;

   delayMicroseconds(1);

   digitalWrite(ADCCS, HIGH);      // LTC2400 CS HIGH
   delay(200);

   if (sig) ltw |= 0xf0000000;    // if input negative insert sign bit
   ltw=ltw/16;                    // scale result down , last 4 bits have no information
   volt = ltw * v_ref / 16777216; // max scale

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(volt);
    lcd.print(volt);
    
    // print to the serial port too:
    Serial.print(cnt++);
    Serial.print(";  ");
    Serial.print(volt,6);         
    dataFile.close();
    lcd.clear();
  }  

  // if the file isn't open, pop up an error:
    else {
    Serial.println("error opening datalog.txt");
  } 
  } 
   digitalWrite(ADCCS, HIGH); // LTC2400 CS hi
   delay(20);
}

byte SPI_read()
{
 return SPI.transfer(0x00);
}

Could anyone check it for me to see what did I write wrong or it's not the right way to use SPI for two device?

What does happen then? Theoretically it should work like that. You just have to ensure that only one chip select is in LOW state at the same time.

The output is error opening datalog.txt, I am not quite sure about the reason.
But I was trying to set both low for the most of time. SD is low all the time, ADC is low when it's doing work.
I will need them both low to work at the same time. Is that possible?

Danny

But I was trying to set both low for the most of time. SD is low all the time, ADC is low when it's doing work.
I will need them both low to work at the same time. Is that possible?

A chip select signal is LOW active which means that the chip is activated on LOW and deactivated on HIGH. So you have to try to let the chip select lines be HIGH as often as possible.
Only one of them must be low at any given time because else you're sending commands to multiple devices which may even result in short circuits on the MISO line.

Thank you very much for your reply. It is working now.
I enable them alternatively within a loop. And it worked!
Below is my code, maybe someone else will be interested in someday.

/*
 Pressure sensor system
 
 This system shows how to log data from a analog sensor and log 
 data into an SD card using the SD library.Also use an external 
 24 bit ADC
 	 
 created  20 June 2013
 by Danny	 
 */

#include <SPI.h>
#include <SD.h>
#include <LiquidCrystal.h>


const int SDCS = 4;
const int ADCCS = 10;
double pressureValue = 0;
LiquidCrystal lcd(12, 11, 6, 5, 3, 2);


void setup()
{
    pinMode(ADCCS, OUTPUT);
    pinMode(SDCS, OUTPUT);
    digitalWrite(ADCCS, HIGH);
    digitalWrite(SDCS, HIGH);
    SPI.begin();
    lcd.begin(16, 2);
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(SDCS)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
}

float volt;
float v_ref=5.0;          // Reference Voltage, 5.0 Volt for LT1021 or 3.0 for LP2950-3

long int ltw = 0;         // ADC Data ling int
int cnt;                  // counter
byte b0;                  //
byte sig;                 // sign bit flag
char st1[20];             // float voltage text

void loop()
{
  digitalWrite(ADCCS, LOW);
  delayMicroseconds(1);
  lcd.print("Pressure Diff:");
  lcd.setCursor(10, 1);
  lcd.print("kPa");
  lcd.setCursor(0, 1);
   if (digitalRead(MISO) == LOW) {   // ADC Converter ready ?
   ltw=0;
   sig=0;

   b0 = SPI_read();             // read 4 bytes adc raw data with SPI
   if ((b0 & 0x20) ==0) sig=1;  // is input negative ?
   b0 &=0x1F;                   // discard bit 25..31
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;

   delayMicroseconds(1);

   digitalWrite(ADCCS, HIGH);      // LTC2400 CS HIGH
   delay(2);
   
   if (sig) ltw |= 0xf0000000;    // if input negative insert sign bit
   ltw=ltw/16;                    // scale result down , last 4 bits have no information
   volt = ltw * v_ref / 16777216; // max scale
   pressureValue=(volt-0.2)/0.01845;
   }
   
   digitalWrite(ADCCS, HIGH);    
   digitalWrite(SDCS, LOW);
   
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(pressureValue);
    lcd.print(pressureValue);
    
    // print to the serial port too:
    Serial.print(cnt++);
    Serial.print(";  ");
    Serial.print(volt,6);           // print voltage as floating number
    Serial.print("; ");
    Serial.print(pressureValue);  
    Serial.println("  ");    

    dataFile.close();
    delay(200);
    lcd.clear();
  }  
    else {
    Serial.println("error opening datalog.txt");
  } 
    digitalWrite(SDCS, HIGH);
}

byte SPI_read()
{
 return SPI.transfer(0x00);
}

Thanks again,
Danny

Nice to see other work with the LTC2400. It is in my opinion a very good and cheap simple to use precision ADC.

And there are some resources to use. If anyone is interested, I have a thread with some links to things done before
about making a precision DVM of an LTC2400 and an Arduino in another forum.

It can be found by searching "Easy DIY 5.5 Digit DVM + Volt Ref./Cal. (LTC2400+LTC6655 / SPI uC / Arduino)"
from any web search engine.