0

I have a two channel 24bit ADC(LTC2402- http://cds.linear.com/docs/en/datasheet/24012f.pdf) that I am communicating with via Arduino Leonardo(Leonardo because it was free!). If I attempt to do multiple reads the SPI becomes very slow while if I do a single read the time to send is what is expected. I have have integrated with python and timed the different transactions. A single read takes around 170ms( this is for both channels and the datasheet of the ADC indicates about 65ms per conversion(table 3 arduino as external sck etc.)) BUT if I do 5 reads the time taken is about 1.5s(expected about 0.65s) 10 reads take about 3s and 20 about 6.5s. Doing no ADC conversions and just serial comm to python is less than 2ms.

The relevant python code is as follows:

def getdata(ser,code):#ser is the arduino that has been connected, code is for writting to arduino
    ser.write(code)
    ch0=float(ser.readline().decode()[:-2])
    ch1=float(ser.readline().decode()[:-2])
    return ch0,ch1

code='1'
code=code.encode()

a=datetime.datetime.now()  
ch0,ch1=getdata(ser,code)
b=datetime.datetime.now()
print(b-a)

The arduino code is as follows. The code has been simplified to just the necessary byte reads from the ADC, all other code has been removed to ensure the delays are coming from the SPI.transfer(0x00). The full code retrieves 4 bytes per channel and converts this to voltage and returns these values.

#include <SPI.h>


const int ltcs = 3; //active low ADC enable

float ch0=0.0;
float ch1=0.0;
byte b0; 

void setup() {
SPI.begin();
SPI.beginTransaction(SPISettings(200000, MSBFIRST, SPI_MODE0));

Serial.begin(9600); // set the baud rate

pinMode(ltcs, OUTPUT);
digitalWrite(ltcs, LOW);
}

void loop() {
if(Serial.available()){

   int data = Serial.read() - '0';
   if(data>0){

   getdata2(ch0,ch1);
    //getdata2(ch0,ch1); //run multiple getdata2 to test multiple conversions
   //getdata2(ch0,ch1);
    //getdata2(ch0,ch1);
   //getdata2(ch0,ch1);

    Serial.println(0.2);
    Serial.println(0.4);


  }
  }
  }

 void getdata2(float &ch0, float &ch1) {
   ch0 = 0.0;
   ch1 = 0.0;

   for (int i = 0; i < 2; i++) { //Do twice to retrieve both Channels   
     while (digitalRead(MISO) == HIGH) {
     }

       b0 = SPI.transfer(0x00);
       b0 = SPI.transfer(0x00);
       b0 = SPI.transfer(0x00);
       b0 = SPI.transfer(0x00);
   }
   }

Can anyone help me? I have tried different SPISettings with no change. Interestingly I also find that the Baud rate does not change either.

Thanks for the help if any

  • Why are you reading from MISO? Why are you ignoring b0? You don't seem to be changing ch except to set it to zero. I don't see what getdata2 achieves except to slow things down. – Nick Gammon May 4 '17 at 21:05
  • The time isn't increasing exponentially. 5 reads take 1.5s, 10 reads take 3s and 20 reads takes 6s. That's a linear increase. – Nick Gammon May 4 '17 at 21:10
  • @NickGammon - Hi, MISO is just to see when data is ready. I'm only ignoring b0 for the example code. The actual code reads byte by byte and reconstructs to the 24bit which is then translated to voltage. In the actual code ch is the translated voltage as a float. So in short getdata2 is the function that recieves 4 bytes from the ADC and translates to voltage. I may have been a little dramatic by saying the time increases exponentially but it does double after a few reads. Hope that clears it up – Nick Law May 4 '17 at 21:39
  • @NickGammon- The Code I included here was to ensure that no other code was causing delays. This is the bare minimum needed to receive data from the ADC – Nick Law May 4 '17 at 21:40
  • I can only see one call to getdata2 call in the above code. Can you please show the actual code that is slow? – Nick Gammon May 4 '17 at 23:13
1

I found the error. Unfortunately I was so busy blaming the code and assuming it was my lack of arduino knowledge that I forgot to check the hardware specs. I thought I was using the maximum external oscillator frequency(f_EOSC) of 300KHz, but in fact was using the 50Hz internal oscillator frequency with an external f_sck from the arduino. This means that the conversions where in fact running at expected times. The thing that threw me off was that the first reading was much faster than the rest. This was most likely because at first read I only had to wait for one channel conversion as the other was already done before I request the data and so the first readings wait time is only as long as a single channels conversion. I would need to implement a 300KHz external clk if I want faster conversion speeds. Thanks for the help for those who tried:)

0

You probably want to take a look at the datasheet and work on one routine that returns adc results from a channel selected by the user. The typical process is to read the register until EOC is asserted (_EOC is low).

and you would go from there.

  • @dannyf- Can you please elaborate? I have the ADC correctly returning values so I am unsure what you're referring to. It's literally just the timing. – Nick Law May 5 '17 at 11:29
  • @dannyf- Nevermind. I solved it. I was actually already doing what you suggested. The /EOC is implement on the SDO/MISO channel just before data conversion. Thanks though. – Nick Law May 5 '17 at 13:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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