Pages: [1]   Go Down
Author Topic: Analog I/O Pins and ADC Sampling Frequency  (Read 7573 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

I am completely new to arduino programming.  I picked up the Arduino Due with the intention of sampling an analog signal (60Hz) at specific frequencies.  I am trying to sample from one of the analog pins at integer multiples of 60Hz, such as 3.84kHz,  6kHz or 21.6kHz.  I have found little documentation for the Due online.

The datasheet states that the clock governing the analog pins is set to the MCK (asuming the master clock, 84MHz) divided by a prescaler value.  The formula given is MCK / ((Prescaler value +1) * 2), with prescaler value ranging from 0 to 512.  If the max prescaler value is 512 does this mean that I must slow down the MCK to attain the desired sampling frequency?  If so, I cannot find anything in the data sheet that states how to alter the MCK.  How do I set the sampling frequency to a specific value?

I am also questioning the method I am using to detect how many samples a second I am recording.  I reading from an analog pin for 1 second (with various baud rates) and detecting how many values are sent to my computer through the microUSB port (using Putty).  Any advice or direction you can give me would be greatly apreciated. Thanks.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I also just received the Due and have found myself facing similar problems. Check out the following link:
http://www.djerickson.com/arduino/
Apparently it's the startup time that screws us up. Another way I went about fixing that is using:
adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST);
Where I simply multiplied the max frequency by 2 (less advised as its probably set at max for a reason). I hear what you're saying about the prescaler, but I have yet to find a way to edit it directly. In the above link he states that its set to its maximum value, so there's that too. Anyway best of luck with this mysterious chip  smiley-razz
« Last Edit: April 01, 2013, 09:42:47 am by BuckM » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello!

I am also interested in knowing more about this, I found some information about how to increase other Arduino boards sampling frequency, but there is very little about the DUE.

Jason504, thanks for this information, I was able to double the default ADC samplerate adding that to the setup() function ( but I would still need at least 100Khz ).

I bought the DUE because it had better processing capabilities, looking forward to see further developments in this part.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, here's some testings I made, I really don't know what I'm doing, but if someone assures me there's no danger of frying my board with this, I'll be happy... see my comments:

#define MAX_ADC_RESOLUTION 10 //changing resolution doesn't seem to affect sampling rate speed in this test

void setup() {
  
  //I tested this with a hall sensor, not sure if results will vary according to the sensor used, but please be gentle with me, I just started learning this 3 days ago, I'm just an amateur programmer. :-)
  
  Serial.begin(9600);

  //check adc.h in the /sam folder
  
  analogReadResolution(MAX_ADC_RESOLUTION); //
  
  //by default, I get around 25000 samples per second, readings around 570 ( 10bit ) with a hall sensor plugged in
  
  //adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX*2, 1); //~313000 samples per second, A/D readings kaput
  //adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX*2, 2); //~288 000 samples per second, A/D readings now have about 10% deviation
     adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX*2, 3); //~267000 samples per second, A/D readings OK, the best compromise I got
  //adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX*2, 4); //~220000 samples per second, A/D readings OK
  //adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX*2, ADC_STARTUP_NORM ); //~65000 samples per second,A/D readings OK
  //adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX*2, ADC_STARTUP_FAST ); //~47000 samples per second, from the name, I was tempted to think this would perform better. But I know nothing.

  edit: correction, I missed that 4 bit part from Dave's documentation. :-/
  
  pinMode(ADC0,INPUT);
}


void loop() {  
  
  int start = millis();
  int num_samples = 0;
  
  //just to evaluate any possible accurancy degradation while messing around with this
  int value = 0;
  int max_value = 0;
  int min_value = 2^MAX_ADC_RESOLUTION;
  
  //let's see how many samples we can read in 1 second
  while( millis() - start < 1000 )
  {
    value = analogRead(ADC0);
  
    if(value > max_value )
    max_value = value;
    
    if(value < min_value )
    min_value = value;
  
    num_samples++;
  }

  // print out the control results
  Serial.println("\nsamples read: ");
  Serial.print(num_samples);
  
  Serial.println("\nMax value: ");
  Serial.print( max_value );
  
  Serial.println("\nMin value: ");
  Serial.print( max_value );
 
  delay(1000);
}

Any thoughts?
« Last Edit: May 02, 2013, 12:51:39 am by username1982 » Logged

0
Offline Offline
Full Member
***
Karma: 2
Posts: 109
ArduiYES!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm a bit lost inbetween the arduino standard calls and what the DUE is or does,
but I learned that that MCK/2 and prescaler determine the speed of the ADC processing.
given that (clock) speed, taking a sample takes a few clock cycles.

but what determines the sampling timing is what the datasheet calls a trigger.
the trigger can be an external signal or e.g. a timer.

I have not yet gotten that to work yet, however.
If / when I do, I'll report. but I'm following the datasheet, not the arduino calls, so the code is extensive.
 

 
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am also interested in knowing how to increase the speed of digitalRead() and digitalWrite().

I know there's a library with faster calls for that operation, but I don't know if it supports the Arduino DUE.

The values I have currently are enough for a simple input / output measurement, but I am concerned with accuracy loss the more pins are used.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

no answer to the digital read/write question, but going back to OP:
the link that BuckM provided (http://www.djerickson.com/arduino/) is a real gem if you want fast ADC (analogRead). This djerikckson did a fantastic job in evaluating the ADC speed, resolution, accuracy etc of the Arduino DUE.
What is most interesting is that he hints at a possible programming mistake in the Arduino 1.5 codebase; a quote from the ADC speed section of djerickson's evaluation:
"This may be a bug. STARTUP is a four bit field so 12 (0xC) works, but 40 (0x28) won't work. And 12 sets the value to 768 which is why the ADC is so slow. So I suspect that the programmer confused the value with the hardware settings. "

I tried the hack and it works as claimed:
Code:
    REG_ADC_MR = (REG_ADC_MR & 0xFFF0FFFF) | 0x00020000;
this gives a 4usec analogRead, instead of the 39usec that the standard settings give you.

tip of the hat and big thanks to djerickson.com
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I saw this post also.  Does anyone know the proper protocol to bring this to the attention of the Due analogread code maintainers?  10x performance improvement in analogread seems like a big deal to me.
Logged

Forum Administrator
Milano, Italy
Offline Offline
Sr. Member
*****
Karma: 23
Posts: 292
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The electrical characteristics of the SAM3X datasheet specifies:

ADCClock - max 20Mhz
Conversion Time - 20 ADCClock

So the old prescaler is correct (ADC_FREQ_MAX == 20000000) while ADC_FREQ_MAX*2 is out of specification.
The conversion time was wrong, I've set it to 24 ADCClocks (that is "3", instead "2" is 16 and is under the minimum required).

https://github.com/arduino/Arduino/issues/1418
https://github.com/arduino/Arduino/commit/f03093332bd910a05af31838d06fa7f1c1e5040c

Thank you!
Logged

C.

Pages: [1]   Go Up
Jump to: