Data aquisition with arduino Due

Hello all - I am measuring tiny electrical signals in plants typically between 20mv and 160mv so +/-1v per analogue input. I have built an op amp to get the input inpedance right . My questions are what is the overall sampling rate for the arduino due and how many kb/s can I have per analogue input ? and can I stream in realtime into max msp or pure data (preferably max) ?

I've done some DAQ with the UNO but not the due. I expect you'll have MANY variables that you will have to consider if you really wanted to push speeds up (switching resolution, optimizing ISR's, DMA etc) and it can get complex fast. If you want to go this route i suggest you start to look at the ST SAM3X/A datsheet and see the ADC (the 1400 page one, actually you may want to read the ADC section regardless). I think the ADC runs at 1MHz, but i suspect this is actually NOT the parameter you are looking for, i think you want to know how quickly you can acquire a sample?

Here is a simple empirical test you can do with an o-scope and a sketch (note i didn't compile this).

While(1)
{
digitalWrite(13, HIGH)
analogRead(0)
digitalWrite(13, LOW)
delay(1);
}

Then on your o-scope measure the pulse width of the HIGH portion of the signal on pin 13, use vertical cursors or a pwh measure.... This will give you an idea of how quickly you could possibly read one single analog input in a polling manner. (the delay is there such that you'd have nice trigger on the scope). You can then add channels accordingly....keep in mind this does not include any other portion of your data acq system like writing to memory, serial port, ethernet etc, which will have a significant impact your throughput. I find its best to nail down what you actually need for your application, then code for that.

Hi,
I simply mean sample rate. Ie how often can each channel take a sample of the voltage per second taking niquist into account (or audio or whatever) . Normally with DAQs you just divide the overall sample speed of the board and divide that by the amount of channels.

PS - I am not a coder ( I can program max and pure data but not code) - so I was hoping to just copy and paste some code as my friends seem to have managed for most of their arduino projects- I can also use the sarcduino max patch....

I will try to do a test and post code and results.

Sorry it took a while to post back.
Here is some follow-up code and o-scope screenshots for the DUE vs UNO ADC sampling and test results.

ADC sampling results:
The DUE did 20 ADC (12bit) reads in about 766uSec. Approx 40uS/ch ~25KHz.
The UNO did 20 ADC (10bit) reads in about 2.25mSec. Approx 113uS/ch ~8.8KHz

Now, for giggles you'll see i added an optional single printf to the code. Here are the results with the single printf included:

The DUE did 20 ADC (12bit) reads + 1 printf (to the serial port emulated over the programming USB port) in about 5.1mS.
The UNO did 20 ADC (10bit) reads + 1 printf to the serial port in about 2.4mS.

Now this is probably an extreme case, but it illustrates how it is important to also analyze what you plan to do with a sample from the ADC once you've got it (send over serial, Ethernet, CAN, USB, write to memory, etc). This can be (and is often) the throughput bottleneck in your DAQ system. I suspect if had used the printf on one of the DUE native serial ports, the results would be much faster. The DUE USB programming port "emulates" a serial port on the system instead of acting like a "true" USB port I suspect there must be a ton of overhead there causing this delay....as such it actually served well to illustrate the point. There is probably more info on this latency if you dig or ask around this forum.

I hope this helps.

Here is the DUE code I used

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  analogReadResolution(12);
}

void loop() {
  int counts;
  // put your main code here, to run repeatedly: 
  
  //pull digital output high for measurement of "high time" on o-scope
  digitalWrite(13,HIGH);
  
  //read adc
  counts = analogRead(A0);
  counts = analogRead(A1);
  counts = analogRead(A2);
  counts = analogRead(A3);
  counts = analogRead(A4);
  counts = analogRead(A5);
  counts = analogRead(A6);
  counts = analogRead(A7);
  counts = analogRead(A8);
  counts = analogRead(A9);
  counts = analogRead(A10);
  counts = analogRead(A11);
  counts = analogRead(A0);
  counts = analogRead(A1);
  counts = analogRead(A2);
  counts = analogRead(A3);
  counts = analogRead(A4);
  counts = analogRead(A5);
  counts = analogRead(A6);
  counts = analogRead(A7);
  
#if false
    Serial.println(counts);   
#endif

  //pull pin down
  digitalWrite(13,LOW);
  
  //delay for scope trigger
  delay(10);
}

Here is the UNO code I used

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  //analogReadResolution(12);
}

void loop() {
  int counts;
  // put your main code here, to run repeatedly: 
  
  //pull digital output high for measurement of "high time" on o-scope
  digitalWrite(13,HIGH);
  
  //read adc
  counts = analogRead(0);
  counts = analogRead(1);
  counts = analogRead(2);
  counts = analogRead(3);
  counts = analogRead(4);
  counts = analogRead(0);
  counts = analogRead(1);
  counts = analogRead(2);
  counts = analogRead(3);
  counts = analogRead(4);
  counts = analogRead(0);
  counts = analogRead(1);
  counts = analogRead(2);
  counts = analogRead(3);
  counts = analogRead(4);
  counts = analogRead(0);
  counts = analogRead(1);
  counts = analogRead(2);
  counts = analogRead(3);
  counts = analogRead(4);
    
#if false
    Serial.println(counts);   
#endif

  //pull pin down
  digitalWrite(13,LOW);
  
  //delay for scope trigger
  delay(10);
}

scope images are here:




The Due's ADC takes 20 ADC clock cycles to take a 12-bit reading and you can set the clock rate up to 20MHz, so should be able to take a reading (from a single channel) every uS. However at that speed the impedance of the voltage source
has to be pretty low, I think about 10k.

That said I don't know how the Arduino's library implement the analogRead() function.


Rob

The DUE did 20 ADC (12bit) reads in about 766uSec. Approx 40uS/ch ~25KHz.
what about ADC with resolution 10 bit ?
thanks

I'll summarize what I learned from the blog below:
The running theory is that it is a bug in the core arduino code or for some unknown reason a decision to run the ADC slow. The STARTUP and SETTLING bits in the mode register are set, possibly erroneously to values that make the ADC channels run quite slow. One statement to directly change the STARTUP and SETTLING bits is below

REG_ADC_MR = (REG_ADC_MR & 0xFFF0FFFF) | 0x00020000;

Put that in your setup() function and it reduces the time to execute an analogRead from 40uS to about 4uS.

Here is the blog article:

Additionally this thread gave me a good idea of how to setup DMA but I didn't have time to figure out how to broaden it for multiple analog inputs and channels. I could easily enable the other channels but it wasn't clear how to configure DMA to support organizing the data from the other channels where you want it.

http://forum.arduino.cc/index.php?topic=137635.0

You should be able to acquire and transfer 1MS/s with the Due.
See this thread:
http://forum.arduino.cc/index.php?topic=137635.0

@eng_mac - i think i did this test with 10bits....and it didn't make a noticeable difference can't remember for sure i was finishing off some nice beer at the time. You can try it by changing the startup code where we set the ADC resolution.

@exedor - awesome!I do appreciate all of the responses on modifying the low-level code and getting the 1Ms/s bandwidth...of course i just saw that thread after i posted my test results in this thread. Initially was responding to AugustineL who "is not a coder" and posted a question on sample rates so this was a simple "dummy" high-level test on the arduino library "as provided"...as it was something i was looking to do at some point anyway. Daves blog post looks awesome thanks for sharing.