Bagaimana saya tahu frekuensi pengambilan sampel?

16

Saya mulai agak bingung tentang laju sampling dan baudrate dll. Saya punya kode Arduino ini:

#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;
        }
      }
    }
  }
}

Karena tidak ada penundaan interupsi, berapakah laju sampling / frekuensi? Apakah ini berdasarkan kecepatan ADC Arduino? Ketika saya meningkatkan baudrate apakah saya meningkatkan frekuensi pengambilan sampel atau hanya tingkat di mana saya mengirim data melalui port serial?

pengguna3284376
sumber

Jawaban:

21

Kecepatan clock Arduino ADC diatur dalam ..arduino-1.5.5 \ hardware \ arduino \ avr \ cores \ arduino \ wiring.c

Inilah bagian yang relevan

#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

Untuk Arduino 16 MHz, clock ADC diatur ke 16 MHz / 128 = 125 KHz. Setiap konversi dalam AVR membutuhkan 13 jam ADC sehingga 125 KHz / 13 = 9615 Hz.

Itu adalah laju pengambilan sampel maksimum yang mungkin, tetapi laju pengambilan sampel aktual dalam aplikasi Anda tergantung pada interval antara panggilan konversi berturut-turut.
Karena Anda membaca hasilnya dan mengirimkannya melalui port serial, Anda mendapatkan penundaan yang meningkat karena laju baud menurun. Semakin rendah baud rate, semakin lama waktu yang dibutuhkan untuk mengirim data yang sama dan semakin lama waktu untuk memanggil konversi ADC berikutnya.

Laju pengambilan sampel aktual dalam aplikasi Anda dapat ditentukan dengan menggunakan debugger atau simulator, tetapi solusi yang lebih mudah adalah dengan mengganti pin digital setiap kali Anda mengeksekusi konversi dan mengukur frekuensi di mana pin digital beralih.

alexan_e
sumber
Juga, waktu antara perangko waktu saya meningkat dari ~ 1300 sampai ~ 16400, tentunya mereka harus tetap sama? Yaitu di 9600, di 115200, mereka meningkat hanya menjadi sekitar 1500 setelah banyak waktu.
user3284376
@ user3284376 tentang kode cap waktu Anda, saya pikir itu tidak bisa berfungsi setiap saat (dapat dibiaskan oleh beberapa interupsi pada waktu yang salah). Saya sarankan Anda memposting pertanyaan spesifik tentang cara mendapatkan timing presisi tinggi di Arduino dan meletakkan bagian yang relevan dari kode Anda di sana.
jfpoilpret
7

Saya juga ingin mendapatkan sampling rate tinggi, untuk sebuah proyek. ternyata bit ADPS2, ADPS1, ADPS0 dari register ADCSRA dapat dikonfigurasi untuk mendapatkan laju sampling 76923 s / dtk atau 76,8 ks / dtk. Tetapi, berhati-hatilah bahwa saya menjalankan ADC arduino saya dalam mode berlari bebas, baris-baris berikut bekerja untuk saya.

#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)
}

Pada frekuensi ini, hasil 10-bit yang biasa tidak dapat diandalkan. Ini berarti bahwa meningkatkan laju sampel akan mengurangi ketepatan hasil. Jadi saya hanya menggunakan bit atas 8 karena pada prescalar ini bit atas 8 dapat diandalkan. Anda dapat melihat lebih detail di halaman ini, dude rocks! ia membuat sampel oscilloscpe tingkat tinggi menggunakan UNO http://www.instructables.com/id/Girino-Fast-Arduino-Oscilloscope/

Salar Khan
sumber
3

Setiap loop Anda mencetak 8 karakter melalui tautan serial 9600bps. Setiap karakter membutuhkan 10 bit (1 start, 8 bit untuk karakter, 1 stop). Itu berarti Anda hanya bisa melewati loop ini ~ 120 kali / detik.

The analogRead()Fungsi dapat mencicipi sekitar 9600 kali / detik dalam teori, realistis itu adalah tentang 8600 kali / detik.

Anda dibatasi oleh komunikasi serial.

Cybergibbons
sumber
Jadi meningkat menjadi 115200, menghasilkan 1440 kali / detik, apakah itu laju sampel?
user3284376
Memberi atau menerima, ya. Anda harus ingat bahwa Serial mensyaratkan bahwa ujung yang lain merespons, sehingga Anda bergantung pada PC yang merespons. Ini bukan deterministik sehingga Anda akan mendapatkan jitter.
Cybergibbons
Anda benar di ujung hal Arduino, semuanya tampak baik-baik saja, tetapi pada Python hal-hal jauh lebih lambat, hal-hal seperti apa yang harus saya lakukan untuk meningkatkan kinerja di ujung komputer?
user3284376
Anda tidak perlu melihat ini sebagai masalah dengan kinerja serial pada PC, tetapi bagaimana Anda mendapatkan sampel untuk dipisahkan dari pengiriman data.
Cybergibbons
1
@Cybergibbons - tidak, karena ini berjalan pada Uno di mana USB dan serial dipisahkan, tidak ada ketergantungan pada PC selain mengeluarkan karakter 'S' dan tidak mengeluarkan 'F'. Sketsa yang diposting di sini dan platform yang menjalankannya akan dengan senang hati melemparkan data serial ke micro-serial pendamping USB, secara membabi buta lupa jika itu atau apa pun yang ada di ujung USB lainnya mengikuti.
Chris Stratton
3

Mengirim 11 bit melalui serial dengan baud 9600, tetapi untuk pengambilan sampel, saya menyimpannya dalam array dengan penundaan sesedikit mungkin, kemudian setelah selesai, saya mengirimkannya melalui port serial untuk dibaca oleh skrip python. Saya melakukan ini untuk FFT menggunakan matplotlib. Saya mendengarkan sinyal 0-5V, lalu tanpa menggunakan fungsi delay (), saya menyimpan nilai analogRead () ke dalam array itu. Dalam sepersekian detik pembacaan selesai, maka dump data serial dimulai. Ketika saya mengkalibrasi frekuensi input menggunakan nada () dari Arduino lain yang terhubung, saya menyadari bahwa saya harus membagi indeks dengan 8915 untuk mendapatkan akurasi dalam 0,1 Hz. Karena kita harus membagi dengan frekuensi sampling untuk mendapatkan interval indeks yang tepat, tebakan saya adalah frekuensi sampling Arduino (setidaknya milik saya dengan kode saya) adalah 8915Hz.

pengguna34028
sumber
1

Mengacu pada bagian tentang perbedaan antara laju sampel dan laju baud, mereka adalah pengukuran yang berbeda.

Sample Rate adalah frekuensi di mana perangkat (arduino) dapat membuat ulang representasi digital dari nilai analog yang masuk.

Baud Rate adalah tingkat di mana informasi ditransfer dalam saluran komunikasi. Ini menggambarkan tingkat komunikasi antara mikrokontroler dan dunia luar (komputer).

Saya akan merekomendasikan tautan electronics_stack_exchange ini. /electronics/135056/sampling-rate-data-rate-and-bandwidth

ThermoRestart
sumber
0

8915Hz - sangat dekat dengan 125000/14 ~ = 8928.6 Tebakan awal saya bahwa tepat satu celah diperlukan antara konversi yang berdekatan Satu jam ADC untuk pengambilan sampel dan 13 jam ADC untuk konversi itu sendiri. Kesalahan kecil bisa jadi akibat dari sumber clock Arduino yang tidak sempurna. Saya belum yakin. Topik ini aktual bagi saya sekarang karena data sampel harus mengumpankan filter digital.

E_Sh
sumber
1
Saya tidak yakin apa yang Anda maksud ketika Anda mengatakan "Topik ini aktual untuk saya sekarang karena data sampel harus memberi makan filter digital.". Apakah Anda mengalami masalah yang sama?
VE7JRO
Setiap konversi dimulai pada tepi naik dari jam ADC, dan setidaknya satu siklus clock ADC hilang kode eksekusi. Jadi ya, 8928,6 Hz adalah yang tercepat yang bisa Anda dapatkan dengan menelepon analogRead()dalam loop ketat, vs 9615,4 Hz yang sangat konsisten dalam mode bebas-lari.
Edgar Bonet