Як дізнатися частоту вибірки?


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? Коли я збільшую баудрат, я збільшую частоту вибірки або просто швидкість, з якою я надсилаю дані через послідовний порт?

Відповіді:


21

Тактова частота АЦП Arduino встановлена ​​в ..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

Для 16-МГц Arduino тактова частота АЦП встановлена ​​на 16 МГц / 128 = 125 КГц. Кожна конверсія в AVR займає 13 годин АЦП, так що 125 КГц / 13 = 9615 Гц.

Це максимально можлива швидкість вибірки, але фактична частота вибірки у вашій програмі залежить від інтервалу між послідовними викликами конверсій.
Оскільки ви читаєте результат і надсилаєте його через послідовний порт, ви отримуєте затримку, яка збільшується зі зменшенням швидкості передачі даних. Чим менша швидкість передачі даних, тим більше часу знадобиться для надсилання однакової довжини даних і тим довше буде потрібно для виклику наступного перетворення ADC.

Фактична частота дискретизації у вашій програмі може бути визначена за допомогою налагоджувача або тренажера, але простішим рішенням є перемикання цифрового штифта щоразу, коли ви здійснюєте перетворення та вимірюєте частоту, на яку цифровий штифт перемикається.


Також час між моїми часовими марками збільшується від ~ 1300 аж до ~ 16400, напевно вони повинні залишатися однаковими? Тобто на 9600, на 115200, вони збільшуються лише до приблизно 1500 після великої кількості часу.
користувач3284376

@ user3284376 щодо вашого коду штампів часу, я думаю, що він не може працювати завжди (може бути упереджений деякими перервами в неправильний час). Я б запропонував вам поставити конкретне питання про те, як отримати високу точність синхронізації на Arduino і поставити туди відповідну частину вашого коду.
jfpoilpret

7

Я також хотів отримати високий показник вибірки для проекту. виявляється, що біти ADPS2, ADPS1, ADPS0 регістра ADCSRA можуть бути налаштовані для отримання швидкості вибірки 76923 с / с або 76,8 кс / с. Але майте на увазі, що я запускаю АЦП ардуїно у вільному режимі, наступні рядки працювали для мене.

#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-бітові надійні. Ви можете детальніше ознайомитись на цій сторінці, цей чувак-скеля! він зробив осцилоскоп з високою швидкістю вибірки, використовуючи ООН http://www.instructables.com/id/Girino-Fast-Arduino-Oscilloscope/


3

Кожен цикл, який ви друкуєте, 8 символів через послідовне посилання 9600bps. Кожен символ бере 10 біт (1 старт, 8 біт для символу, 1 зупинка). Це означає, що ви можете пройти через цю петлю ~ 120 разів / сек.

analogRead()Функція може спробувати приблизно в 9600 разів / сек в теорії, реально вона становить близько 8600 раз / сек.

Вас обмежує серійний зв’язок.


Отже, збільшуючись до 115200, це дає 1440 разів / с, це швидкість вибірки?
користувач3284376

Дай або візьми, так. Потрібно мати на увазі, що Serial вимагає, щоб відповів інший кінець, тому ви залежні від відповіді ПК. Це не детерміновано, тому ви отримаєте тремтіння.
Кібергібони

Ви маєте рацію на ардуїнському кінці речей, все виглядає добре, але на Python все набагато повільніше, які речі мені потрібно зробити, щоб підвищити продуктивність на комп'ютерному кінці речей?
користувач3284376

На це не потрібно розцінюватись як проблему з серійною продуктивністю на ПК, але як змусити відібрати вибірку від надсилання даних.
Кібергібони

1
@Cybergibbons - ні, оскільки це працює на Uno, де USB і серійні роз'єднані, немає ніякої залежності від ПК, крім видачі символу "S" і не видачі "F". Ескіз, розміщений тут, і платформа, на якій він працює, будуть радісно передавати серійні дані на мікросхему USB-послідовного мікрофона, сліпо не звертаючи уваги, якщо те чи що-небудь на іншому кінці USB не відстає.
Кріс Страттон

3

Відправляю 11 біт за серійною передачею при швидкості 9600, але для вибірки я зберігаю його в масиві з якомога меншою затримкою, після цього, як тільки це буде зроблено, я надсилаю його через послідовний порт для читання за допомогою сценарію python. Я роблю це для FFT за допомогою matplotlib. Я слухаю сигнал 0-5V, потім, не використовуючи функції delay (), зберігаю в цьому масиві значення analogRead (). Через частку секунди відбувається зчитування, після чого починається скидання послідовних даних. Коли я калібрував вхідну частоту за допомогою тону () від іншого підключеного Arduino, я зрозумів, що мені доведеться розділити індекс на 8915, щоб отримати точність у межах .1 Гц. Оскільки для отримання належних індексних інтервалів слід поділити частоту вибірки, я здогадуюсь, що частота дискретизації Arduino (принаймні моя з моїм кодом) становить 8915 ГГц.


1

Посилаючись на частину про різницю між частотою вибірки та швидкістю передачі, вони є різними вимірами.

Частота вибірки - це частота, з якою пристрій (ардуїно) може відтворити цифрове представлення вхідних аналогових значень.

Швидкість боду - швидкість, з якою передається інформація в каналі зв'язку. Він описує швидкість зв'язку між мікроконтролером та зовнішнім світом (комп'ютером).

Я б рекомендував це посилання electronics_stack_exchange. /electronics/135056/sampling-rate-data-rate-and-bandwidth


0

8915 Гц - це дуже близько до 125000/14 ~ = 8928.6 Моя початкова здогадка, що потрібен рівно один проміжок між сусідніми перетвореннями. Один годинник АЦП для вибірки та 13 годин АЦП для самого перетворення. Невелика помилка може бути наслідком не ідеального тактового джерела Arduino. Я ще не впевнений. Ця тема зараз актуальна для мене, оскільки вибіркові дані повинні подавати цифровий фільтр.


1
Я не впевнений, що ви маєте на увазі, коли ви говорите "Ця тема зараз для мене актуальна, оскільки вибіркові дані повинні подавати цифровий фільтр". У вас є подібна проблема?
VE7JRO

Кожне перетворення починається з висхідного краю годинника АЦП, і принаймні один тактовий цикл АЦП втрачається виконуючим кодом. Так, так, 8928,6 Гц - це найшвидший виклик, зателефонувавши analogRead()в щільний цикл, порівняно з дуже стійким 9615,4 Гц у вільному режимі.
Едгар Бонет
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.