Pages: [1]   Go Down
Author Topic: ADC - analogRead at high frequency (1 MHz) on Arduino DUE  (Read 1072 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 1
Posts: 62
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


There are some great posts about using Arduino Due (I have a Freaduino Due) to read an analogue signal at high frequency.

http://www.djerickson.com/arduino/
http://frenki.net/2013/10/fast-analogread-with-arduino-due/
http://forum.arduino.cc/index.php?topic=137635.5

But the situation changed a bit after ARDUINO 1.5.5 BETA 2013.11.28, when wrong initialization for ADC timings was changed.
This is discussed on:
https://github.com/arduino/Arduino/issues/1418

While before this change you could get an notorious decrease in the sampling time from some 38 us (micro seconds) to 1 us. After that I couldn´t get less than 1.5 us.

With this code I get 1 us again:

Code:

int x;                                           // read value

void setup()
{
  Serial.begin(57600);                           // initialize the serial port:
  REG_ADC_MR = 0x10380180;                       // change from 10380200 to 10380180, 1 is the PREESCALER and 8 means FREERUN
  ADC -> ADC_CHER = 0x80;                        // enable ADC on pin A0
}

void loop() {

  unsigned long t = micros();                    // init time an elapsed time, in micro seconds
  
  for(int i = 0; i < 1000; i++) {
    
    // instrucction to measure
    while((ADC->ADC_ISR & 0x80)==0);             // wait for conversion
    x = ADC->ADC_CDR[7];                         // read value A0
    
  }
  
  t = micros() - t - 2;                          // 2 us is nothing measured time
  
  Serial.print("Time (us) ");
  Serial.println( ( (double) t / 1000 ), 6 );
  
  delay(2000);
}



I´m getting a 1.00 us sample time, That is 1 MHz frequency!.

My small innovation from the links is that I changed the PRESCALAR, from 2 to 1.  This is in REG_ADC_MR = 0x10380180. I changed the third digit (right to left) from 2 to 1.
The change from 0 to 8 is to enable FREERUN, that means one sample after the other non stop.
___

Some comments:

Without any optimization I'm getting an analogRead(0); at 3.32 us (300 KHz)
enabling FREERUN (REG_ADC_MR = 0x10380280;) 1.92 us (520 KHz)
and changing resolution to 12 bits (shouldn´t be the opposite?) (analogReadResolution(12)) 1.80 us (555 KHz)

Then, from Stimmer post (I just coping and pasting his code, I am not sure to understand what he is doing)
ADC -> ADC_MR |= 0x80;                          // set free running mode on ADC;
ADC -> ADC_CHER = 0x80;                         // enable ADC on pin A0

while((ADC->ADC_ISR & 0x80)==0);                // wait for conversion
x = ADC->ADC_CDR[7];                            // read value
I´m getting 1.50 us (667 KHz)

I just check the speed. I didn´t check any measured values so far.
___

Adios from Buenos Aires
Happy coding
Marcelo




Logged

The Netherlands
Offline Offline
Full Member
***
Karma: 1
Posts: 139
MKDS hacker and Programmer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think you can only get 1MHz using dma.
Logged

Subscribe my youtube channel: http://www.youtube.com/user/MKDS3

Offline Offline
Jr. Member
**
Karma: 1
Posts: 62
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


No no. I´m getting 1 MHz with this.
I am only storing it in memory until the measure ends. It´s a big 24000 int array (I should try a short array).

I tested the light output of a compact fluorescent lamp. I will try to add some picture.



* Screen Shot 2014-03-11 at 21.28.16 .png (19.36 KB, 828x224 - viewed 50 times.)
Logged

0
Offline Offline
Shannon Member
****
Karma: 207
Posts: 12194
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think you can only get 1MHz using dma.

You can only get _reliable_ 1MHz sampling using DMA or disabling all (other) interrupt
handlers (which otherwise may cause lost samples by delaying the ADC code or ISR).

Its obviously going to be more powerful to use DMA which frees the CPU for other stuff.
Logged

[ I won't respond to messages, use the forum please ]

Offline Offline
Jr. Member
**
Karma: 1
Posts: 62
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ah. Now I understand what you are saying.
Thanks Gericom and thanks MarkT for pointing me that.

Honestly I don´t know how to implement DMA (direct memory access) right now. But I will try to learn (I love to investigate and learn).

In the meantime, will something like this be an acceptable solution?

Code:
noInterrupts();

(fast loop of analogRead)

interrupts():

Logged

The Netherlands
Offline Offline
Full Member
***
Karma: 1
Posts: 139
MKDS hacker and Programmer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here you can find the datasheet of the chip: www.atmel.com/Images/doc11057.pdf
Logged

Subscribe my youtube channel: http://www.youtube.com/user/MKDS3

Pages: [1]   Go Up
Jump to: