Как узнать частоту дискретизации?

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

user3284376
источник

Ответы:

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

Для Arduino 16 МГц тактовая частота АЦП установлена ​​на 16 МГц / 128 = 125 КГц. Каждое преобразование в AVR занимает 13 тактовых импульсов АЦП, поэтому 125 кГц / 13 = 9615 Гц.

Это максимально возможная частота выборки, но фактическая частота выборки в вашем приложении зависит от интервала между последовательными вызовами преобразования.
Поскольку вы читаете результат и отправляете его через последовательный порт, вы получаете задержку, которая увеличивается с уменьшением скорости передачи. Чем ниже скорость передачи, тем больше времени потребуется для отправки данных той же длины и тем больше времени потребуется для вызова следующего преобразования АЦП.

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

alexan_e
источник
Кроме того, время между моими отметками времени увеличивается с ~ 1300 до ~ 16400, неужели они должны оставаться неизменными? То есть в 9600, в 115200 они увеличиваются только до 1500 через много времени.
user3284376
@ user3284376 относительно вашего кода метки времени, я думаю, что он не может работать постоянно (может быть смещен некоторыми прерываниями в неправильное время). Я бы посоветовал вам опубликовать конкретный вопрос о том, как получить высокую точность синхронизации на Arduino и поместить туда соответствующую часть вашего кода.
jfpoilpret
7

Я также хотел получить высокую частоту дискретизации для проекта. Оказывается, биты ADPS2, ADPS1, ADPS0 регистра ADCSRA могут быть сконфигурированы для получения частоты дискретизации 76923 с / с или 76,8 кс / с. Но, помните, что я запускаю АЦП моего Arduino в режиме свободного запуска, следующие строки работали для меня.

#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

В каждом цикле вы печатаете 8 символов по последовательной линии связи 9600 бит / с. Каждый символ занимает 10 бит (1 старт, 8 бит для символа, 1 стоп). Это означает, что вы можете пройти только этот цикл ~ 120 раз / сек.

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

Вы ограничены последовательной связью.

Cybergibbons
источник
Таким образом, увеличение до 115200, дает 1440 раз / сек, это частота дискретизации?
user3284376
Дай или возьми, да. Вы должны иметь в виду, что Serial требует, чтобы другой конец отвечал, поэтому вы зависите от ПК. Это не является детерминированным, поэтому вы получите дрожание.
Cybergibbons
Вы правы в конце Arduino, все выглядит нормально, но в Python все гораздо медленнее, что мне нужно сделать, чтобы повысить производительность компьютера?
user3284376
Вам не нужно смотреть на это как на проблему с последовательной производительностью на ПК, а на то, как вы можете отделить выборку от отправки данных.
Cybergibbons
1
@Cybergibbons - нет, так как он работает на Uno, где USB и последовательный порт не связаны, нет никакой зависимости от ПК, кроме выдачи символа «S» и отказа от символа «F». Эскиз, размещенный здесь, и платформа, на которой он работает, с радостью выбросят последовательные данные на USB-серийный компьютер-компаньон, слепо не замечая, что это или что-то на другом конце USB идет в ногу.
Крис Страттон,
3

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

user34028
источник
1

Обращаясь к части о разнице между частотой дискретизации и скоростью передачи, они представляют собой разные измерения.

Частота дискретизации - это частота, с которой устройство (arduino) может воссоздавать цифровое представление входящих аналоговых значений.

Скорость передачи - это скорость, с которой информация передается по каналу связи. Он описывает скорость связи между микроконтроллером и внешним миром (компьютером).

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

ThermoRestart
источник
0

8915 Гц - это очень близко к 125000/14 ~ = 8928,6. По моему первоначальному предположению, между соседними преобразованиями требуется ровно один разрыв: один тактовый сигнал АЦП для выборки и 13 тактовых импульсов АЦП для самого преобразования. Небольшая ошибка может быть следствием неидеального тактового источника Arduino. Я пока не уверен. Эта тема актуальна для меня сейчас, так как выборочные данные должны питать цифровой фильтр.

E_Sh
источник
1
Я не уверен, что вы имеете в виду, когда говорите: «Эта тема актуальна для меня сейчас, поскольку выборочные данные должны поступать в цифровой фильтр». У вас есть похожая проблема?
VE7JRO
Каждое преобразование начинается с нарастающего фронта тактового сигнала АЦП, и по крайней мере один тактовый цикл АЦП теряется при выполнении кода. Так что да, 8928,6 Гц - это самая быстрая скорость, которую вы можете получить, analogRead()используя узкий цикл, по сравнению с очень стабильными 9615,4 Гц в режиме свободного хода.
Эдгар Бонет