샘플링 주파수를 어떻게 알 수 있습니까?


16

샘플링 속도 및 전송 속도 등에 대해 약간 혼란스러워지기 시작했습니다.이 Arduino 코드가 있습니다.

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

지연 인터럽트가 없기 때문에 샘플링 속도 / 주파수는 무엇입니까? Arduino ADC 속도를 기반으로합니까? 전송 속도를 높이면 샘플링 주파수 또는 직렬 포트를 통해 데이터를 전송하는 속도 만 증가합니까?

답변:


21

Arduino ADC 클럭 속도는 ..arduino-1.5.5 \ hardware \ arduino \ avr \ cores \ arduino \ wiring.c에 설정되어 있습니다.

관련 부분은 다음과 같습니다

#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

16MHz Arduino의 경우 ADC 클록은 16MHz / 128 = 125KHz로 설정됩니다. AVR의 각 변환에는 13 개의 ADC 클록이 필요하므로 125KHz / 13 = 9615Hz입니다.

가능한 최대 샘플링 속도이지만 애플리케이션의 실제 샘플링 속도는 연속적인 전환 호출 간격에 따라 다릅니다.
결과를 읽고 직렬 포트를 통해 전송하므로 전송 속도가 감소함에 따라 지연이 발생합니다. 전송 속도가 낮을수록 동일한 길이의 데이터를 전송하는 데 시간이 오래 걸리고 다음 ADC 변환을 호출하는 데 시간이 오래 걸립니다.

응용 프로그램의 실제 샘플링 속도는 디버거 또는 시뮬레이터를 사용하여 확인할 수 있지만 더 쉬운 해결책은 변환을 실행할 때마다 디지털 핀을 토글하고 디지털 핀이 토글되는 주파수를 측정하는 것입니다.


또한 타임 스탬프 사이의 시간은 ~ 1300에서 ~ 16400까지 증가합니다. 반드시 동일하게 유지해야합니까? 그것은 9600에, 115200에, 많은 시간이 지나면 약 1500으로 증가합니다.
user3284376

타임 스탬프 코드와 관련하여 @ user3284376, 나는 그것이 항상 작동 할 수 없다고 생각합니다 (잘못된 시간에 일부 인터럽트에 의해 바이어스 될 수 있음). Arduino에서 고정밀 타이밍을 얻는 방법에 대한 특정 질문을 게시하고 코드의 관련 부분을 거기에 넣는 것이 좋습니다.
jfpoilpret

7

또한 프로젝트의 샘플링 속도를 높이고 싶었습니다. ADCSRA 레지스터의 ADPS2, ADPS1, ADPS0 비트는 76923 s / s 또는 76.8 ks / s의 샘플링 속도를 얻도록 구성 할 수 있습니다. 그러나 무료 실행 모드에서 arduino의 ADC를 실행하고 있다는 것을 명심하십시오. 다음 줄이 저에게 효과적이었습니다.

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

이 주파수에서 일반적인 10 비트 결과는 신뢰할 수 없습니다. 샘플 속도를 높이면 결과의 정확도가 떨어집니다. 따라서이 프리 스칼라에서는 상위 8 비트가 신뢰할 수 있으므로 상위 8 비트 만 사용합니다. 이 페이지에서 자세한 내용을 볼 수 있습니다. 그는 UNO http://www.instructables.com/id/Girino-Fast-Arduino-Oscilloscope/를 사용하여 높은 샘플링 속도의 오실로스코프를 만들었습니다 .


3

각 루프는 9600bps 직렬 링크를 통해 8자를 인쇄합니다. 각 문자는 10 비트 (1 개 시작, 8 비트, 1 개 정지)를 사용합니다. 즉,이 루프는 ~ 120 회 / 초만 통과 할 수 있습니다.

analogRead()기능은 이론적으로 약 9600 배 / 초로 샘플링 할 수 있으며, 실제로는 약 8600 배 / 초입니다.

당신은 직렬 통신에 묶여있다.


따라서 115200으로 증가하면 초당 1440 번이 샘플 속도입니까?
user3284376

그렇습니다. Serial은 상대방이 응답해야하므로 PC 응답에 의존한다는 점을 명심해야합니다. 이것은 결정적이지 않으므로 지터가 발생합니다.
Cybergibbons

Arduino의 말이 맞습니다. 모두 괜찮아 보이지만 Python의 경우 속도가 훨씬 느립니다. 컴퓨터의 성능을 향상시키기 위해 어떤 종류의 일을해야합니까?
user3284376

이를 PC의 직렬 성능 문제로 볼 필요는 없지만 데이터 전송에서 샘플링을 분리하는 방법은 무엇입니까?
Cybergibbons

1
@Cybergibbons-아니요, USB와 직렬이 분리 된 Uno에서 실행되므로 'S'문자를 발행하고 'F'를 발행하지 않는 PC에 의존하지 않습니다. 여기에 게시 된 스케치와 실행 플랫폼은 USB 직렬 컴패니언 마이크로에 직렬 데이터를 기꺼이 던지므로 USB의 다른 쪽 끝에있는 것이 있으면 맹목적으로 알 수 없습니다.
Chris Stratton

3

9600의 전송 속도로 직렬을 통해 11 비트를 전송하지만 샘플링을 위해 가능한 한 적은 지연 시간으로 배열에 저장 한 다음 완료되면 직렬 포트를 통해 전송하여 파이썬 스크립트로 읽습니다. matplotlib을 사용하여 FFT에 대해이 작업을 수행하고 있습니다. 0-5V 신호를 듣고 delay () 함수를 사용하지 않고 analogRead () 값을 해당 배열에 저장합니다. 순식간에 판독이 완료되면 직렬 데이터 덤프가 시작됩니다. 연결된 다른 Arduino의 tone ()을 사용하여 입력 주파수를 교정 할 때 정확도를 0.1Hz 이내로 높이려면 인덱스를 8915로 나눕니다. 적절한 인덱스 간격을 얻으려면 샘플링 주파수로 나눠야하기 때문에 내 추측으로는 Arduino 샘플링 주파수 (적어도 내 코드를 사용하는)는 8915Hz입니다.


1

샘플링 속도와 전송 속도의 차이에 대한 부분을 참조하면 측정 값이 다릅니다.

샘플 속도는 장치 (arduino)가 들어오는 아날로그 값의 디지털 표현을 재현 할 수있는 주파수입니다.

전송 속도는 통신 채널에서 정보가 전송되는 속도입니다. 마이크로 컨트롤러와 외부 세계 (컴퓨터) 간의 통신 속도를 설명합니다.

이 electronics_stack_exchange 링크를 추천합니다. /electronics/135056/sampling-rate-data-rate-and-bandwidth


0

8915Hz-125000/14 ~ = 8928.6에 매우 가깝습니다. 초기 변환은 인접한 변환간에 정확히 하나의 갭이 필요하다는 것입니다. 샘플링을위한 하나의 ADC 클럭과 변환 자체를위한 13 개의 ADC 클럭 Arduino의 완벽한 클럭 소스가 아닌 경우 작은 오류가 발생할 수 있습니다. 아직 확실하지 않습니다. 이 주제는 이제 샘플 데이터가 디지털 필터를 공급해야하므로 실제로 적용됩니다.


1
"샘플링 된 데이터가 디지털 필터를 공급해야하기 때문에이 주제는 이제 실제입니다."라고 말할 때 무슨 의미인지 잘 모르겠습니다. 비슷한 문제가 있습니까?
VE7JRO

각 변환은 ADC 클럭의 상승 에지에서 시작하며 코드 실행 에서 하나 이상의 ADC 클럭 사이클이 손실됩니다. 그렇습니다. 8928.6 Hz는 analogRead()자유 실행 모드에서 매우 일관된 9615.4 Hz에 비해 타이트한 루프 를 호출 하여 얻을 수있는 가장 빠른 속도 입니다.
Edgar Bonet
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.