Làm thế nào để tôi biết tần số lấy mẫu?


16

Tôi bắt đầu hơi bối rối về tốc độ lấy mẫu và tốc độ lấy mẫu, v.v. Tôi có mã Arduino này:

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

Vì không có gián đoạn trễ, tốc độ / tần số lấy mẫu là gì? Có phải nó dựa trên tốc độ Arduino ADC? Khi tôi tăng tốc độ baudrate tôi có tăng tần số lấy mẫu hay chỉ tốc độ tôi gửi dữ liệu qua cổng nối tiếp?

Câu trả lời:


21

Tốc độ xung nhịp của Arduino ADC được đặt ở ..arduino-1.5.5 \ phần cứng \ arduino \ avr \ cores \ arduino \ Wired.c

Đây là phần có liên quan

#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

Đối với Arduino 16 MHz, đồng hồ ADC được đặt thành 16 MHz / 128 = 125 KHz. Mỗi chuyển đổi trong AVR mất 13 đồng hồ ADC nên 125 KHz / 13 = 9615 Hz.

Đó là tốc độ lấy mẫu tối đa có thể, nhưng tốc độ lấy mẫu thực tế trong ứng dụng của bạn phụ thuộc vào khoảng thời gian giữa các cuộc gọi chuyển đổi liên tiếp.
Vì bạn đọc kết quả và gửi nó qua cổng nối tiếp, bạn sẽ nhận được độ trễ tăng khi tốc độ truyền giảm. Tốc độ truyền càng thấp thì càng mất nhiều thời gian để gửi cùng một chiều dài dữ liệu và sẽ mất nhiều thời gian hơn để gọi chuyển đổi ADC tiếp theo.

Tốc độ lấy mẫu thực tế trong ứng dụng của bạn có thể được xác định bằng việc sử dụng trình gỡ lỗi hoặc trình giả lập, nhưng một giải pháp dễ dàng hơn là chuyển mã pin kỹ thuật số mỗi khi bạn thực hiện chuyển đổi và đo tần số mà pin kỹ thuật số bật.


Ngoài ra, thời gian giữa các dấu thời gian của tôi tăng từ ~ 1300 lên đến ~ 16400, chắc chắn chúng có nên giữ nguyên không? Đó là ở mức 9600, lúc 115200, chúng chỉ tăng lên khoảng 1500 sau rất nhiều thời gian.
dùng3284376

@ user3284376 liên quan đến mã tem thời gian của bạn, tôi nghĩ rằng nó không thể hoạt động mọi lúc (có thể bị sai lệch bởi một số ngắt không đúng lúc). Tôi khuyên bạn nên đăng một câu hỏi cụ thể về cách lấy thời gian chính xác cao trên Arduino và đặt phần có liên quan của mã của bạn vào đó.
jfpoilpret

7

Tôi cũng muốn có được tỷ lệ lấy mẫu cao, cho một dự án. hóa ra các bit ADPS2, ADPS1, ADPS0 của thanh ghi ADCSRA có thể được cấu hình để có tốc độ lấy mẫu là 76923 s / s hoặc 76,8 ks / s. Nhưng, hãy cẩn thận khi tôi đang chạy ADC của arduino ở chế độ chạy miễn phí, các dòng sau hoạt động với tôi.

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

Ở tần số này, kết quả 10 bit thông thường không đáng tin cậy. Nó có nghĩa là tăng tỷ lệ mẫu sẽ làm giảm độ chính xác của kết quả. Vì vậy, tôi chỉ sử dụng 8 bit trên bởi vì tại thời điểm này, 8 bit trên là đáng tin cậy. Bạn có thể đi vào chi tiết hơn trên trang này, anh chàng đá này! ông đã tạo ra một bộ dao động tốc độ mẫu cao bằng cách sử dụng UNO http://www.instructables.com/id/Girino-Fast-Arduino-Oscillcop/


3

Mỗi vòng lặp bạn đang in 8 ký tự qua liên kết nối tiếp 9600bps. Mỗi ký tự mất 10 bit (1 bắt đầu, 8 bit cho ký tự, 1 dừng). Điều đó có nghĩa là bạn chỉ có thể đi qua vòng lặp này ~ 120 lần / giây.

Về analogRead()mặt lý thuyết, hàm có thể lấy mẫu với tốc độ khoảng 9600 lần / giây, thực tế là khoảng 8600 lần / giây.

Bạn đang bị ràng buộc bởi các giao tiếp nối tiếp.


Vì vậy, tăng lên 115200, cho 1440 lần / giây, đó có phải là tốc độ mẫu không?
dùng3284376

Cho hay nhận, vâng. Bạn cần lưu ý rằng Nối tiếp yêu cầu đầu kia phản hồi, vì vậy bạn phụ thuộc vào PC phản hồi. Điều này không mang tính quyết định nên bạn sẽ bị giật.
Cyberg Ribbon

Bạn nói đúng về kết thúc Arduino, mọi thứ đều ổn, nhưng trên Python mọi thứ chậm hơn rất nhiều, tôi cần phải làm gì để tăng hiệu suất trên đầu máy tính?
dùng3284376

Bạn không cần phải xem đây là một vấn đề với hiệu suất nối tiếp trên PC, nhưng làm thế nào để bạn lấy mẫu được tách rời khỏi việc gửi dữ liệu.
Cyberg Ribbon

1
@Cyberg Ribbon - không, vì điều này đang chạy trên Uno nơi USB và nối tiếp được tách rời, không có sự phụ thuộc vào PC ngoài việc phát hành ký tự 'S' và không phát hành ký tự 'F'. Bản phác thảo được đăng ở đây và nền tảng mà nó chạy sẽ vui vẻ ném dữ liệu nối tiếp vào micro đồng hành nối tiếp USB, không biết gì nếu điều đó hoặc bất cứ điều gì ở đầu kia của USB đang theo kịp.
Chris Stratton

3

Gửi 11 bit qua nối tiếp ở tốc độ 9600, nhưng để lấy mẫu, tôi lưu trữ nó trong một mảng với độ trễ càng ít càng tốt, sau đó khi nó được thực hiện, tôi gửi nó qua cổng nối tiếp để được đọc bởi tập lệnh python. Tôi đang làm điều này cho một FFT bằng matplotlib. Tôi nghe tín hiệu 0-5V, sau đó không sử dụng hàm delay (), tôi lưu các giá trị analogRead () vào mảng đó. Trong tích tắc, việc đọc được thực hiện, sau đó kết xuất dữ liệu nối tiếp bắt đầu. Khi tôi hiệu chỉnh tần số đầu vào bằng cách sử dụng âm () từ một Arduino được kết nối khác, tôi nhận ra rằng tôi phải chia chỉ số cho 8915 để có được độ chính xác trong khoảng .1 Hz. Bởi vì người ta sẽ phải chia cho tần số lấy mẫu để có được các khoảng chỉ số thích hợp, nên tôi đoán là tần số lấy mẫu Arduino (ít nhất là của tôi với mã của tôi) là 8915Hz.


1

Đề cập đến phần về sự khác biệt giữa tốc độ mẫu và tốc độ truyền, chúng là các phép đo khác nhau.

Tỷ lệ mẫu là tần số mà thiết bị (arduino) có thể tạo lại biểu diễn kỹ thuật số của các giá trị tương tự đến.

Tốc độ Baud là tốc độ truyền thông tin trong kênh truyền thông. Nó mô tả tốc độ giao tiếp giữa vi điều khiển và thế giới bên ngoài (máy tính).

Tôi muốn giới thiệu liên kết Electronics_stack_exchange này. /electronics/135056/sampling-rate-data-rate-and-bandband


0

8915Hz - nó rất gần với 125000/14 ~ = 8928.6 Dự đoán ban đầu của tôi rằng cần có chính xác một khoảng cách giữa các chuyển đổi liền kề Một đồng hồ ADC để lấy mẫu và 13 đồng hồ ADC để tự chuyển đổi. Lỗi nhỏ có thể là do nguồn Arduino không hoàn hảo. Tôi chưa chắc chắn. Chủ đề này là thực tế đối với tôi bây giờ vì dữ liệu được lấy mẫu phải cung cấp bộ lọc kỹ thuật số.


1
Tôi không chắc ý của bạn là gì khi bạn nói "Chủ đề này thực tế đối với tôi bây giờ vì dữ liệu được lấy mẫu phải cung cấp bộ lọc kỹ thuật số." Bạn đang có một vấn đề tương tự?
VE7JRO

Mỗi chuyển đổi bắt đầu trên một cạnh tăng của đồng hồ ADC và ít nhất một chu kỳ đồng hồ ADC bị mất mã thực thi. Vì vậy, có, 8928,6 Hz là tốc độ nhanh nhất bạn có thể nhận được bằng cách gọi analogRead()trong một vòng lặp chặt chẽ, so với 9615,4 Hz rất nhất quán trong chế độ chạy tự do.
Edgar Bonet
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.