Örnekleme sıklığını nasıl bilebilirim?


16

Ben örnekleme oranları ve baudrates vb hakkında biraz karışmaya başlıyorum. Bu Arduino kodu var:

#include <eHealth.h>

extern volatile unsigned long timer0_overflow_count;
float fanalog0;
int analog0;
unsigned long time;


byte serialByte;
void setup() {
  Serial.begin(9600);
}

void loop() { 
  while (Serial.available()>0){  
    serialByte=Serial.read();
    if (serialByte=='S'){        
      while(1){
        fanalog0=eHealth.getECG();  
        // Use the timer0 => 1 tick every 4 us
        time=(timer0_overflow_count << 8) + TCNT0;        
        // Microseconds conversion.
        time=(time*4);   
        //Print in a file for simulation
        //Serial.print(time);
        //Serial.print(" ");
        Serial.print(fanalog0,5);
        Serial.print("\n");

        if (Serial.available()>0){
          serialByte=Serial.read();
          if (serialByte=='F')  break;
        }
      }
    }
  }
}

Gecikme kesintisi olmadığından, örnekleme oranı / frekansı nedir? Arduino ADC hızına mı dayanıyor? Baud hızını artırdığımda örnekleme frekansını mı yoksa sadece seri port üzerinden veri gönderme hızımı mı artırıyorum?

Yanıtlar:


21

Arduino ADC saat hızı ..arduino-1.5.5 \ hardware \ arduino \ avr \ cores \ arduino \ wiring.c olarak ayarlanmıştır.

İşte ilgili bölüm

#if defined(ADCSRA)
    // Set A/D prescale factor to 128
    // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
    // XXX: this will not work properly for other clock speeds, and
    // this code should use F_CPU to determine the prescale factor.
    sbi(ADCSRA, ADPS2);
    sbi(ADCSRA, ADPS1);
    sbi(ADCSRA, ADPS0);

    // Enable A/D conversions
    sbi(ADCSRA, ADEN);
#endif

16 MHz Arduino için ADC saati 16 MHz / 128 = 125 KHz olarak ayarlanmıştır. AVR'deki her dönüşüm 13 ADC saati alır, böylece 125 KHz / 13 = 9615 Hz.

Bu, mümkün olan maksimum örnekleme oranıdır, ancak uygulamanızdaki gerçek örnekleme oranı, birbirini izleyen dönüşüm aramaları arasındaki aralığa bağlıdır.
Sonucu okuduğunuzdan ve seri bağlantı noktasından gönderdiğinizden, baud hızı azaldıkça artan bir gecikme yaşarsınız. Baud hızı ne kadar düşük olursa, aynı uzunluktaki veriyi göndermek o kadar uzun sürer ve bir sonraki ADC dönüşümünü çağırmak o kadar uzun sürer.

Uygulamanızdaki gerçek örnekleme oranı, bir hata ayıklayıcı veya bir simülatör kullanılarak belirlenebilir, ancak her dönüşüm gerçekleştirdiğinizde ve dijital pimin geçiş yaptığı frekansı ölçtüğünüzde dijital bir pimi değiştirmek daha kolay bir çözümdür.


Ayrıca, zaman damgalarım arasındaki süre ~ 1300'den ~ 16400'e kadar artar, elbette aynı kalmalılar mı? Yani 9600'de, 115200'de, çok zaman sonra sadece 1500'e yükseliyorlar.
user3284376

@ user3284376 zaman damgası kodunuzla ilgili olarak, her zaman çalışamayacağını düşünüyorum (yanlış zamanda bazı kesintiler tarafından önyargılı olabilir). Arduino'da yüksek hassasiyetli zamanlamanın nasıl alınacağı ve kodunuzun ilgili kısmını oraya nasıl koyacağınız hakkında belirli bir soru göndermenizi öneririm.
jfpoilpret

7

Ayrıca bir proje için yüksek bir örnekleme oranı almak istedim. ADCSRA kaydının ADPS2, ADPS1, ADPS0 bitlerinin 76923 s / s veya 76.8 ks / s örnekleme hızı alacak şekilde yapılandırılabileceği ortaya çıkıyor. Ancak, arduino'nun ADC'sini serbest çalışma modunda çalıştırdığımı unutmayın, aşağıdaki satırlar benim için çalıştı.

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

void setup() {
// Set the Prescaler to 16 (16000KHz/16 = 1MHz)
// WARNING: Above 200KHz 10-bit results are not reliable.
//ADCSRA |= B00000100;
sbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
cbi(ADCSRA, ADPS0);

// Set ADIE in ADCSRA (0x7A) to enable the ADC interrupt.
// Without this, the internal interrupt will not trigger.
//ADCSRA |= B00001000;
sbi(ADCSRA,ADIE)
}

Bu frekansta normal 10 bitlik sonuçlar güvenilir değildir. Bu, örnekleme hızını arttırmanın sonuçların kesinliğini azaltacağı anlamına gelir. Bu yüzden sadece üst 8 biti kullanıyorum çünkü bu prescalar üst 8 bit güvenilir. Bu sayfada daha fazla ayrıntıya girebilirsiniz, bu ahbap kayalar! UNO kullanarak yüksek örnekleme oranlı bir osiloskop yaptı http://www.instructables.com/id/Girino-Fast-Arduino-Oscilloscope/


3

Her döngü 9600bps seri bağlantı üzerinden 8 karakter yazdırıyor. Her karakter 10 bit alır (1 başlangıç, karakter için 8 bit, 1 durdurma). Bu, yalnızca bu döngüden ~ 120 kez / saniye geçebileceğiniz anlamına gelir.

analogRead()İşlev gerçekçi bu 8600 kere / sn ile ilgilidir, teorik olarak yaklaşık 9600 kat / sn örnek olabilir.

Seri iletişim sizi kısıtlıyor.


Yani 115200'e çıkarak, 1440 kez / saniye verir, örnekleme hızı bu mu?
user3284376

Ver ya da al, evet. Serial'in diğer ucun yanıt vermesini gerektirdiğini, böylece bilgisayarın yanıt vermesine bağlı olduğunuzu aklınızda bulundurmanız gerekir. Bu deterministik değildir, bu yüzden sinirleneceksiniz.
Cybergibbons

İşlerin Arduino ucundasınız, her şey yolunda görünüyor, ancak Python'da çok daha yavaş, şeylerin bilgisayar ucundaki performansı artırmak için ne tür şeyler yapmam gerekir?
user3284376

Buna, PC'deki seri performansla ilgili bir sorun olarak bakmamanız gerekir, ancak örneklemenin veri gönderilmesinden nasıl ayrıldığını nasıl elde edersiniz?
Cybergibbons

1
@Cybergibbons - hayır, bu USB ve dizinin ayrıldığı bir Uno'da çalıştığı için, PC'ye 'S' karakterini vermenin ve 'F' karakterini vermenin ötesinde bir bağımlılık yok. Burada yayınlanan çizim ve üzerinde çalıştığı platform, USB seri arkadaşı mikroda seri verileri mutlu bir şekilde atacak, USB'nin diğer ucundaki herhangi bir şeyin veya herhangi bir şeyin devam edip etmediği gözü kapalı.
Chris Stratton

3

9600 baud'luk seri üzerinden 11 bit gönderme, ancak örnekleme için, mümkün olduğunca az gecikmeyle bir dizide saklarım, sonra bir kez bittiğinde, bir python betiği tarafından okunması için seri port üzerinden gönderirim. Bunu matplotlib kullanarak bir FFT için yapıyorum. Bir 0-5V sinyali dinliyorum, sonra delay () işlevini kullanmadan, analogRead () değerlerini bu diziye depolarım. Bir saniyede okuma yapılır, daha sonra seri veri dökümü başlar. Başka bir bağlı Arduino'dan tone () kullanarak giriş frekansını kalibre ettiğimde, .1 Hz aralığında doğruluk elde etmek için indeksi 8915'e bölmem gerektiğini fark ettim. Uygun indeks aralıklarını elde etmek için örnekleme sıklığına bölünmesi gerekeceğinden, tahminim Arduino örnekleme frekansı (en azından kodumla benimki) 8915Hz'dir.


1

Örnekleme hızı ve baud hızı arasındaki farkla ilgili bölüme bakıldığında, bunlar farklı ölçümlerdir.

Örnekleme Hızı, cihazın (arduino) gelen analog değerlerin dijital temsilini yeniden oluşturabilme sıklığıdır.

Baud Hızı, bir iletişim kanalında bilginin aktarılma hızıdır. Mikrodenetleyici ile dış dünya (bilgisayar) arasındaki iletişim oranını tanımlar.

Bu electronics_stack_exchange bağlantısını öneriyorum. /electronics/135056/sampling-rate-data-rate-and-bandwidth


0

8915Hz - 125000/14 ~ = 8928.6'ya çok yakın. İlk tahminim, bitişik dönüşümler arasında tam olarak bir boşluk olması gerekiyor Örnekleme için bir ADC saati ve dönüşümün kendisi için 13 ADC saati. Küçük hata Arduino'nun mükemmel saat kaynağının etkisi olmayabilir. Henüz emin değilim. Örneklenen veriler dijital filtreyi beslemesi gerektiğinden bu konu benim için geçerli.


1
"Örneklenen veriler dijital filtreyi beslemesi gerektiğinden bu konu benim için gerçek" dediğinde ne demek istediğinden emin değilim. Benzer bir sorun mu yaşıyorsunuz?
VE7JRO

Her dönüşüm ADC saatinin yükselen kenarında başlar ve en az bir ADC saat döngüsü yürütme kodunu kaybeder. Yani evet, 8928.6 Hz, analogRead()serbest çalışma modunda çok tutarlı bir 9615.4 Hz ile sıkı bir döngüde arayabileceğiniz en hızlısıdır.
Edgar Bonet
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.