Skąd mam znać częstotliwość próbkowania?


16

Zaczynam się trochę mylić co do częstotliwości próbkowania i prędkości transmisji itp. Mam ten kod 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;
        }
      }
    }
  }
}

Ponieważ nie ma przerwania opóźnienia, jaka jest częstotliwość próbkowania / częstotliwość? Czy jest oparty na prędkości Arduino ADC? Czy po zwiększeniu prędkości transmisji zwiększam częstotliwość próbkowania, czy tylko szybkość, z jaką wysyłam dane przez port szeregowy?

Odpowiedzi:


21

Częstotliwość zegara Arduino ADC ustawia się w ..arduino-1.5.5 \ hardware \ arduino \ avr \ cores \ arduino \ wiring.c

Oto odpowiednia część

#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

W przypadku Arduino 16 MHz zegar ADC jest ustawiony na 16 MHz / 128 = 125 KHz. Każda konwersja w AVR zajmuje 13 zegarów ADC, więc 125 KHz / 13 = 9615 Hz.

Jest to maksymalna możliwa częstotliwość próbkowania, ale rzeczywista częstotliwość próbkowania w aplikacji zależy od odstępu czasu między kolejnymi wywołaniami konwersji.
Ponieważ odczytujesz wynik i wysyłasz go przez port szeregowy, otrzymujesz opóźnienie, które zwiększa się wraz ze spadkiem prędkości transmisji. Im niższa prędkość transmisji, tym dłużej trwa przesłanie danych o tej samej długości i tym dłużej trwa wywołanie następnej konwersji ADC.

Rzeczywistą częstotliwość próbkowania w Twojej aplikacji można ustalić za pomocą debugera lub symulatora, ale łatwiejszym rozwiązaniem jest przełączanie pinów cyfrowych za każdym razem, gdy wykonujesz konwersję i mierzenie częstotliwości, z jaką przełącza się pin cyfrowy.


Ponadto czas między moimi znacznikami czasu wzrasta od ~ 1300 do ~ 16400, czy na pewno powinny pozostać takie same? To jest na 9600, na 115200, po długim czasie wzrosną tylko do około 1500.
— user3284376

@ user3284376 odnośnie twojego kodu znacznika czasu, myślę, że nie może on działać przez cały czas (może być tendencyjny przez niektóre przerwania w niewłaściwym czasie). Sugeruję, abyś zadał konkretne pytanie na temat tego, jak uzyskać bardzo precyzyjne taktowanie na Arduino i umieścić tam odpowiednią część kodu.
— jfpoilpret

7

Chciałem też uzyskać wysoką częstotliwość próbkowania dla projektu. okazuje się, że bity ADPS2, ADPS1, ADPS0 rejestru ADCSRA można skonfigurować tak, aby uzyskać częstotliwość próbkowania 76923 s / s lub 76,8 ks / s. Ale uwaga, że ​​uruchamiam ADC mojego arduino w trybie swobodnym, następujące linie działały dla mnie.

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

Przy tej częstotliwości zwykłe wyniki 10-bitowe nie są wiarygodne. Oznacza to, że zwiększenie częstotliwości próbkowania obniży dokładność wyników. Używam tylko górnych 8 bitów, ponieważ przy tym prescalar górne 8 bitów jest niezawodne. Możesz przejść do bardziej szczegółowych informacji na tej stronie, ten koleś kołysze! wykonał oscyloskop o wysokiej częstotliwości próbkowania za pomocą UNO http://www.instructables.com/id/Girino-Fast-Arduino-Oscilloscope/


3

W każdej pętli drukujesz 8 znaków przez łącze szeregowe 9600bps. Każdy znak wymaga 10 bitów (1 początek, 8 bitów dla znaku, 1 stop). Oznacza to, że możesz przejść przez tę pętlę tylko ~ 120 razy / sek.

analogRead()Funkcja próbki około 9600 razy / sek teoretycznie realistyczny jest około 8600 razy / sek.

Jesteś ograniczony przez komunikację szeregową.


Tak więc zwiększenie do 115200, daje 1440 razy na sekundę, czy to częstotliwość próbkowania?
— user3284376

Daj lub weź, tak. Należy pamiętać, że szeregowy wymaga, aby drugi koniec reagował, więc jesteś zależny od reakcji komputera. To nie jest deterministyczne, więc będziesz się denerwować.
— Cybergibbons,

Masz rację po stronie Arduino, wszystko wygląda dobrze, ale w Pythonie rzeczy są znacznie wolniejsze, jakie rzeczy musiałbym zrobić, aby zwiększyć wydajność na komputerze?
— user3284376,

Nie musisz postrzegać tego jako problemu z wydajnością szeregową na PC, ale w jaki sposób można oddzielić próbkowanie od wysyłania danych.
— Cybergibbons

1
@Cybergibbons - nie, ponieważ działa na Uno, na którym USB i szeregowy są oddzielone, nie ma zależności od komputera poza wydaniem znaku „S” i nie wydaniem znaku „F”. Zamieszczony tutaj szkic i platforma, na której działa, z radością wyrzucą dane szeregowe na USB-serial micro-towarzysz towarzyszący, ślepo nieświadomy, czy to, czy coś na drugim końcu USB dotrzymuje kroku.
— Chris Stratton

3

Wysyłam 11 bitów przez port szeregowy z szybkością 9600, ale dla próbkowania przechowuję go w tablicy z możliwie najmniejszym opóźnieniem, a następnie, gdy to zrobione, wysyłam przez port szeregowy do odczytu przez skrypt python. Robię to dla FFT przy użyciu matplotlib. Słucham sygnału 0-5 V, a następnie bez użycia funkcji delay () przechowuję wartości analogRead () w tej tablicy. W ułamku sekundy odczyt jest zakończony, a następnie rozpoczyna się zrzut danych szeregowych. Kiedy skalibrowałem częstotliwość wejściową za pomocą tonu () z innego podłączonego Arduino, zdałem sobie sprawę, że muszę podzielić indeks przez 8915, aby uzyskać dokładność z dokładnością do 1 Hz. Ponieważ należałoby podzielić przez częstotliwość próbkowania, aby uzyskać odpowiednie interwały indeksu, domyślam się, że częstotliwość próbkowania Arduino (przynajmniej moja z moim kodem) wynosi 8915 Hz.


1

Odnosząc się do części dotyczącej różnicy między częstotliwością próbkowania a szybkością transmisji, są to różne pomiary.

Częstotliwość próbkowania to częstotliwość, z jaką urządzenie (arduino) może odtworzyć cyfrową reprezentację przychodzących wartości analogowych.

Szybkość transmisji to szybkość, z jaką informacje są przesyłane w kanale komunikacyjnym. Opisuje szybkość komunikacji między mikrokontrolerem a światem zewnętrznym (komputerem).

Poleciłbym ten link electronic_stack_exchange. /electronics/135056/sampling-rate-data-rate-and-bandwidth


0

8915Hz - jest to bardzo blisko 125000/14 ~ = 8928.6 Moje początkowe przypuszczenie, że dokładnie jedna przerwa jest wymagana między sąsiednimi konwersjami Jeden zegar ADC do próbkowania i 13 zegarów ADC do samej konwersji. Mały błąd może wynikać z niedoskonałego źródła zegara Arduino. Nie jestem jeszcze pewien. Ten temat jest teraz dla mnie aktualny, ponieważ próbkowane dane muszą zasilać filtr cyfrowy.


1
Nie jestem pewien, co masz na myśli mówiąc „Ten temat jest teraz dla mnie aktualny, ponieważ próbkowane dane muszą zasilać filtr cyfrowy”. Czy masz podobny problem?
— VE7JRO

Każda konwersja rozpoczyna się od zbocza narastającego zegara ADC i co najmniej jeden cykl zegara ADC traci kod wykonawczy. Tak więc, 8928.6 Hz jest najszybszym, jaki można uzyskać, dzwoniąc analogRead()w ciasnej pętli, w porównaniu do bardzo spójnego 9615.4 Hz w trybie swobodnym.
— Edgar Bonet
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.