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?

użytkownik3284376
źródło

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.

alexan_e
źródło
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/

Salar Khan
źródło
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ą.

Cybergibbons
źródło
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.

użytkownik34028
źródło
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

ThermoRestart
źródło
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.

E_Sh
źródło
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