Go Down

Topic: accessing adc at faster rate (Read 3326 times) previous topic - next topic

prasad

I want to take consecutive samples of voltage waveform @ 50 Hz.
What is the shortest period possible between two consecutive adc accesses using Arduino ?
Thanks.
--prasad

AWOL

Quote
What is the shortest period possible between two consecutive adc accesses using Arduino ?

Using vanilla Arduino, I think around 100 to 110 microseconds.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

CrossRoads

See section 23 of the atmega datasheet:

"By default, the successive approximation circuitry requires an input clock frequency between 50
kHz and 200 kHz to get maximum resolution. If a lower resolution than 10 bits is needed, the
input clock frequency to the ADC can be higher than 200 kHz to get a higher sample rate.
The ADC module contains a prescaler, which generates an acceptable ADC clock frequency
from any CPU frequency above 100 kHz. The prescaling is set by the ADPS bits in ADCSRA.
The prescaler starts counting from the moment the ADC is switched on by setting the ADEN bit
in ADCSRA. The prescaler keeps running for as long as the ADEN bit is set, and is continuously
reset when ADEN is low.
When initiating a single ended conversion by setting the ADSC bit in ADCSRA, the conversion
starts at the following rising edge of the ADC clock cycle.
A normal conversion takes 13 ADC clock cycles. The first conversion after the ADC is switched
on (ADEN in ADCSRA is set) takes 25 ADC clock cycles in order to initialize the analog circuitry.
When the bandgap reference voltage is used as input to the ADC, it will take a certain time for
the voltage to stabilize. If not stabilized, the first value read after the first conversion may be
wrong."

So should be much faster than 100us, more like 1-10uS.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

AWOL

#3
May 09, 2011, 02:21 pm Last Edit: May 09, 2011, 02:26 pm by AWOL Reason: 1
Quote
So should be much faster than 100us, more like 1-10uS

That's quite a bit faster than the quoted absolute maximum of 76.9 kSPS (13us), or the 15 kSPS (66us) at ten bit resolution. (23.1 Features)

Quote
A normal conversion takes 13 ADC clock cycles.

On the Arduino, the ADC is clocked at 125kHz, so 13 cycles is 104us.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

CrossRoads

Ah. I was thinking 13 clock cycles referred to the 16MHz clock.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

CrossRoads

Still, plenty fast enough for 50 Hz. I think I misread OP and had 50 KHz on the brain.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

JimEli

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1208715493/11

Igor R

#7
Aug 10, 2011, 11:28 pm Last Edit: Aug 11, 2011, 12:01 am by Igor R Reason: 1
Hi,

I´ve just tinkering today with this... http://arduino.cc/forum/index.php/topic,68855.msg510474.html#msg510474 (Reply 23).  I´m sorry, it´s in spanish, but the code is C and a graph easy to understand....  :D
It´s a 50 Hz signal (from a trafo connected to a 230V power supply plug).

It´s the first test to be sure that eveything was working as expected. I´m just working on it.
I also need a fastest serial routines to try to plot in real time...

This example achieve 35.6 kHz!! t_sample=28 us!!
Code: [Select]

#define mysize 600

unsigned long tStart;
unsigned long tEnd;
byte mydata[mysize];

void setup()
{
 Serial.begin(115200);
 
 //Prescaler
 //ADPS2 - ADPS1 - ADPS0 - Division Factor
 //0        - 0       - 0        ->2
 //0        - 0       - 1        ->2
 //0        - 1       - 0        ->4
 //0        - 1       - 1        ->8
 //1        - 0       - 0        ->16
 //1        - 0       - 1        ->32
 //1        - 1       - 0        ->64
 //1        - 1       - 1        ->128
 //Configure to Prescaler=32
 bitWrite(ADCSRA,ADPS2,1);
 bitWrite(ADCSRA,ADPS1,0);
 bitWrite(ADCSRA,ADPS0,1);
 
 //Input A5
 ADMUX=(1<<ADLAR)|(0<<REFS1)|(1<<REFS0)|(0<<MUX3)|(1<<MUX2)|(0<<MUX1)|(1<<MUX0);
}


void loop()
{

 tStart=micros();
 for (int i=0; i<mysize;i++)
 {
    mydata[i]=analogReadFast();
 }
 tEnd=micros();
 
 Serial.println("NEW ACQUISITION");
 Serial.print("tStart=");
 Serial.println(tStart);
 Serial.print("tEnd=");
 Serial.println(tEnd);
 Serial.print("nPoints=");
 Serial.println(mysize);
 
 for (int i=0; i<mysize;i++)
 {
   Serial.println(mydata[i],DEC);
 }
 
}

int analogReadFast()
{
ADCSRA|=(1<<ADSC);
// ADSC is cleared when the conversion finishes
while (bit_is_set(ADCSRA, ADSC));
       return ADCH;
}





;)

Igor R

#8
Aug 12, 2011, 12:55 am Last Edit: Aug 12, 2011, 01:01 am by Igor R Reason: 1
I've been working a little more on this.
Now with the help of a small python script, I'm plotting in "real time" into KST with a frecuency of 11.7 kHz (85.02 us)!!! The ADC is in 8 bits mode.

The example is the signal acquired from a trafo connected to the AC:


PYTHON:

Code: [Select]

#! /usr/bin/env python

import serial


ser = serial.Serial('/dev/ttyUSB0', 115200);
while 1:
   n=ser.read();
   n=ord(n);
   print n;


ARDUINO:

Code: [Select]

#define mysize 1200

unsigned long tStart;
unsigned long tEnd;
byte mydata[mysize];

void setup()
{
 Serial.begin(115200);
 
 //Prescaler
 //ADPS2 - ADPS1 - ADPS0 - Division Factor
 //0        - 0       - 0        ->2
 //0        - 0       - 1        ->2
 //0        - 1       - 0        ->4
 //0        - 1       - 1        ->8
 //1        - 0       - 0        ->16
 //1        - 0       - 1        ->32
 //1        - 1       - 0        ->64
 //1        - 1       - 1        ->128
 //Configure to Prescaler=32
 bitWrite(ADCSRA,ADPS2,1);
 bitWrite(ADCSRA,ADPS1,0);
 bitWrite(ADCSRA,ADPS0,1);
 
 //Entrada A5
 ADMUX=(1<<ADLAR)|(0<<REFS1)|(1<<REFS0)|(0<<MUX3)|(1<<MUX2)|(0<<MUX1)|(1<<MUX0);
}


void loop()
{

 tStart=micros();
 
 //for (int i=0;i<mysize;i++)
 //frec=11761.938367443
 for (;;)
 {
   while (!(UCSR0A & (1 << UDRE0)));
   UDR0 = analogReadFast();
 }
 tEnd=micros();
 
 Serial.println("NEW ACQUISITION");
 Serial.print("tStart=");
 Serial.println(tStart);
 Serial.print("tEnd=");
 Serial.println(tEnd);
 Serial.print("nPoints=");
 Serial.println(mysize);  
}

int analogReadFast()
{
ADCSRA|=(1<<ADSC);
// ADSC is cleared when the conversion finishes
while (bit_is_set(ADCSRA, ADSC));
       return ADCH;
}


Original post (in Spanish) => http://arduino.cc/forum/index.php/topic,68855.30.html


;)

Go Up