Offline
Jr. Member
Karma: 0
Posts: 69
Arduino Rocks!
|
 |
« on: November 11, 2012, 08:52:56 am » |
How can I verify with an oscilloscope the sampling rate on an Arduino Uno rev3.? I want to generate a pulse every time a conversion is done. Here is my code: #include <avr/io.h> #include <avr/interrupt.h>
volatile uint16_t myMeasurement;
int main(void) { DDRC &= ~(1<<DDC0); // Pin A0 as Input DDRD |= (1<<PIND7);//Pin 6 as output ADCSRA |= 1<<ADPS2; // Prescaler=16, i.e. 1MHz ADMUX |= 1<<REFS0 | 1<<REFS1; //Internal 1.1V Ref used ADCSRA |= 1<<ADIE; // Enable the interrupt ADCSRA |= 1<<ADEN;// Enable the ADR sei();// Enable Interrupts (Global) ADCSRA |= 1<<ADSC;//start first conversion while(1){ //stay alive } }
// The interrupt method ISR(ADC_vect) { uint8_t lowPart = ADCL; myMeasurement = ADCH<<8 | lowPart; ADCSRA |= 1<<ADSC;//trigger new conversion PIND ^= 1<<PIND6;//Flip pin 6 on arduino }
This piece of code, generates a pulse of 29.41kHz on pin 6 - far from the expected 0.5MHz according to the prescaling division factor chosen. A prescaling factor of 4 yields a pulse of 75.8kHz while 2 yields 100kHz. Is there a way to output a pulse at the frequency of the sampling? Is there a way to make is go faster?
|
|
|
|
|
Logged
|
An Arduino development board costs €20~60. A pack of 20 Zener diodes to protect your board from almost certain damage costs less than €1...
|
|
|
|
UK
Offline
Edison Member
Karma: 45
Posts: 2240
What a host of balls she had seen: gaity, the brass buttons...
|
 |
« Reply #1 on: November 11, 2012, 09:01:25 am » |
I know next to nothing about the internals of the Atmel ADC, so I can't comment on your settings. One thing I can comment on though - are you taking into account the number of instructions taken to process the interrupt? // The interrupt method ISR(ADC_vect) { 154: 1f 92 push r1 156: 0f 92 push r0 158: 0f b6 in r0, 0x3f ; 63 15a: 0f 92 push r0 15c: 11 24 eor r1, r1 15e: 2f 93 push r18 160: 3f 93 push r19 162: 4f 93 push r20 164: 8f 93 push r24 166: 9f 93 push r25 168: ef 93 push r30 16a: ff 93 push r31 uint8_t lowPart = ADCL; 16c: 20 91 78 00 lds r18, 0x0078 myMeasurement = ADCH<<8 | lowPart; 170: 40 91 79 00 lds r20, 0x0079 174: 94 2f mov r25, r20 176: 80 e0 ldi r24, 0x00 ; 0 178: 30 e0 ldi r19, 0x00 ; 0 17a: 82 2b or r24, r18 17c: 93 2b or r25, r19 17e: 90 93 da 01 sts 0x01DA, r25 182: 80 93 d9 01 sts 0x01D9, r24 ADCSRA |= 1<<ADSC;//trigger new conversion 186: ea e7 ldi r30, 0x7A ; 122 188: f0 e0 ldi r31, 0x00 ; 0 18a: 80 81 ld r24, Z 18c: 80 64 ori r24, 0x40 ; 64 18e: 80 83 st Z, r24 PIND ^= 1<<PIND6;//Flip pin 6 on arduino 190: 89 b1 in r24, 0x09 ; 9 192: 90 e4 ldi r25, 0x40 ; 64 194: 89 27 eor r24, r25 196: 89 b9 out 0x09, r24 ; 9 } 198: ff 91 pop r31 19a: ef 91 pop r30 19c: 9f 91 pop r25 19e: 8f 91 pop r24 1a0: 4f 91 pop r20 1a2: 3f 91 pop r19 1a4: 2f 91 pop r18 1a6: 0f 90 pop r0 1a8: 0f be out 0x3f, r0 ; 63 1aa: 0f 90 pop r0 1ac: 1f 90 pop r1 1ae: 18 95 reti
That's 26 instructions from the point the interrupt routine is triggered to when the next ADC sample is started.
|
|
|
|
|
Logged
|
|
|
|
|
United Kingdom
Offline
Faraday Member
Karma: 131
Posts: 4685
|
 |
« Reply #2 on: November 11, 2012, 09:04:16 am » |
Looks like you are assuming that the ADC only takes one clock do to a conversion, whereas it actually takes more (around 12 AFAIR - check the datasheet).
|
|
|
|
|
Logged
|
Formal verification of safety-critical software, software development, and electronic design and prototyping. http://www.eschertech.com
|
|
|
|
Offline
Edison Member
Karma: 114
Posts: 2205
|
 |
« Reply #3 on: November 11, 2012, 09:09:45 am » |
[quote]This piece of code, generates a pulse of 29.41kHz on pin 6 - far from the expected 0.5MHz ... .5Mhz means 2u or 32 ticks at 16MIPS. Your isr latency will take 10 - 20 ticks and that doesn't leave much to execution. One way to check for latency is to eliminate all code other than the pin flipping statement and see if you gain speed. If you do, latency is the issue. Having said, 29.41khz sounds too low.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 0
Posts: 69
Arduino Rocks!
|
 |
« Reply #4 on: November 11, 2012, 09:09:52 am » |
One thing I can comment on though - are you taking into account the number of instructions taken to process the interrupt? ... That's 26 instructions from the point the interrupt routine is triggered to when the next ADC sample is started.
You mean, I should write my code in such a way that the occurring number of instructions is lower? Unless I go down to the assembly level, I don't think this is possible. But, I have the feeling that there must be a way...
|
|
|
|
|
Logged
|
An Arduino development board costs €20~60. A pack of 20 Zener diodes to protect your board from almost certain damage costs less than €1...
|
|
|
|
Austin, TX
Offline
Faraday Member
Karma: 41
Posts: 5175
CMiYC
|
 |
« Reply #5 on: November 11, 2012, 09:10:16 am » |
From the ATmega datasheet: A normal conversion takes 13 ADC clock cycles. A forum post that might interest you: http://arduino.cc/forum/index.php/topic,6549.0.html
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 0
Posts: 69
Arduino Rocks!
|
 |
« Reply #6 on: November 11, 2012, 09:11:51 am » |
Looks like you are assuming that the ADC only takes one clock do to a conversion, whereas it actually takes more (around 12 AFAIR - check the datasheet).
If this is the case, what is the prescaler all about? And what is the meaning of being able to sample every 1us (ie 1MHz) or less if it takes more just to get the result?
|
|
|
|
|
Logged
|
An Arduino development board costs €20~60. A pack of 20 Zener diodes to protect your board from almost certain damage costs less than €1...
|
|
|
|
UK
Offline
Edison Member
Karma: 45
Posts: 2240
What a host of balls she had seen: gaity, the brass buttons...
|
 |
« Reply #7 on: November 11, 2012, 09:14:03 am » |
One thing I can comment on though - are you taking into account the number of instructions taken to process the interrupt? ... That's 26 instructions from the point the interrupt routine is triggered to when the next ADC sample is started.
You mean, I should write my code in such a way that the occurring number of instructions is lower? Unless I go down to the assembly level, I don't think this is possible. But, I have the feeling that there must be a way... I don't know much about avr-gcc, but there might be attributes to the isr routine that control what gets stored in the stack and what doesn't - that could reduce the number of registers and such being saved and save some time. Also, don't forget that the output pin will be running at *half* the frequency of the sample rate. You switch on with one sample, and switch off with the next sample, so for 0.5MHz sample rate you should be getting 0.25MHz pin frequency.
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Edison Member
Karma: 45
Posts: 2240
What a host of balls she had seen: gaity, the brass buttons...
|
 |
« Reply #8 on: November 11, 2012, 09:18:08 am » |
The datasheet:  You have a maximum of 15ksps at full resolution, or 76.9ksps at "normal" resolution. How you're trying to get 0.5msps (500ksps) out of it I don't know. To get that kind of rate I use a dsPIC at 80MHz (40 MIPS) and DMA to do the actual sampling direct to memory.
|
|
|
|
« Last Edit: November 11, 2012, 09:19:53 am by majenko »
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 0
Posts: 69
Arduino Rocks!
|
 |
« Reply #9 on: November 11, 2012, 09:18:32 am » |
So the frequency I should expect is (at most):
f_sampling = f_cpu/prescaling f_pulse = f_sampling/(13*2)
Is that right?
|
|
|
|
|
Logged
|
An Arduino development board costs €20~60. A pack of 20 Zener diodes to protect your board from almost certain damage costs less than €1...
|
|
|
|
Offline
Edison Member
Karma: 114
Posts: 2205
|
 |
« Reply #10 on: November 11, 2012, 09:20:36 am » |
I think I understood your confusion now. The adc prescaler selects the adc clock (to be 1/16 in your case) but each conversion may take multiple (around 15) ticks of the adc clock to complete.
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Edison Member
Karma: 45
Posts: 2240
What a host of balls she had seen: gaity, the brass buttons...
|
 |
« Reply #11 on: November 11, 2012, 09:23:39 am » |
The ADC is a "successive approximation" type. Each tick of the ADC clock resolves the sampled voltage down to a higher resolution and accuracy. You can sample at a lower resolution, which requires less clock ticks to calculate that number of bits, and thus sample faster. You still can't get a sample at just one clock tick - for that you need a "flash" type ADC, and they cost big bucks. They're used in video systems and allow giga-samples-per-second.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 0
Posts: 69
Arduino Rocks!
|
 |
« Reply #12 on: November 11, 2012, 09:31:07 am » |
I think I understood your confusion now. The adc prescaler selects the adc clock (to be 1/16 in your case) but each conversion may take multiple (around 15) ticks of the adc clock to complete.
OK, I got it now... In the document "AVR120: Characterization and Calibration of the ADC on an AVR" it is stressed that: Since one conversion takes 13 ADC clock cycles, a maximum ADC clock of 1 MHz means approximately 77k samples per second. This limits the bandwidth in single-ended mode to 38.5 kHz, according to the Nyquist sampling theorem. But, the frequency I achieve is not 38.5kHz; it is 29.4kHz which means that either my conversion takes longer or that the directive PIND ^= 1<<PIND6; takes 4 cycles to execute. Does any of these hypotheses make sense?
|
|
|
|
|
Logged
|
An Arduino development board costs €20~60. A pack of 20 Zener diodes to protect your board from almost certain damage costs less than €1...
|
|
|
|
Offline
Edison Member
Karma: 114
Posts: 2205
|
 |
« Reply #13 on: November 11, 2012, 09:35:55 am » |
it is 29.4kHz Yes (I got 31khz) but that's for two samples (because you flip the pin for each sampling and two flips complete a period) -> sampling is done about close to 60khz. That's very close to the 77khz figure in the datasheet (without considering latency).
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 0
Posts: 69
Arduino Rocks!
|
 |
« Reply #14 on: November 11, 2012, 09:43:29 am » |
Yes (I got 31khz)
You mean, you tried my code and you got 31kHz? And I get 29.4kHz?! This is scandalous! I'll ask for my money back!  but that's for two samples (because you flip the pin for each sampling and two flips complete a period) -> sampling is done about close to 60khz. That's very close to the 77khz figure in the datasheet (without considering latency).
True. But, it's not that close to 77kHz. And I would like to fathom the reasons for this discrepancy. If I didn't have an oscilloscope for example, could I have predicted the actual sampling frequency at a good accuracy?
|
|
|
|
|
Logged
|
An Arduino development board costs €20~60. A pack of 20 Zener diodes to protect your board from almost certain damage costs less than €1...
|
|
|
|
|