5

我刚刚将驻极体麦克风连接到 Arduino,我想在 1  kHz和 4 kHz 的范围内进行采样。

我知道这仅限于机器代码和ADC,所以我试图保持草图简单。

是否可以使用下面的草图在这些频率之间进行采样?

const int analogPin = 0;
int ledPin = 13;

void setup() {
    pinMode(ledPin, OUTPUT);
}

void loop() {
    int mn = 1024;
    int mx = 0;
    for (int i = 0; i < 5; ++i) {
        int val = analogRead(analogPin);
        mn = min(mn, val);
        mx = max(mx, val);
    }
    if (mx-mn >= 50) {
        digitalWrite(ledPin, HIGH);
    }
    else {
        digitalWrite(ledPin, LOW);
    }
}
4

3 回答 3

1

Arduino 是一个原型平台,由许多硬件板和一个软件抽象层组成。对于这样的问题,考虑底层硬件的功能很有用,因为它们提供了最终限制。我假设您使用的是 Arduino Uno/Nano,Due 的情况有所不同。

根据数据表,每个 ADC 读数(除了第一个)需要 13 个 ADC 时钟周期。ADC 时钟(不同于 MCU)时钟是通过将系统时钟除以某个因子(至少为 2)得出的。因此,在 16Mhz 板上,这相当于每秒 60 万个样本。到目前为止,一切都很好。然而,事情还没有结束,您仍然需要读取数据。如果你使用中断,即使你做一些非常简单的事情,经验表明你会损失大约 100 个时钟来中断处理。现在您的采样率降至 126K 样本/秒。但这是理论上的最大值。

数据表指出,要获得 ADC 的最大精度,需要 50kHz - 200kHz ADC 时钟。在 Arduino 代码 (in wiring.c) 中,选择了 128 的除法因子:

sbi(ADCSRA, ADPS2);
sbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);

这意味着每次转换需要 128*13 = 1764 个时钟,理论上每秒最多产生 10K 个样本。考虑到该readAnalog()函数所做的不仅仅是启动 ADC 转换并等待它完成,这比这要差一些,但应该不会差太多。这当然不涉及您的代码:您对结果进行的任何处理readAnalog()都会使捕获更多样本变得更加困难。但是,是的,要以 4Khz 捕获,您需要确保您的代码花费少于 1.5k 时钟周期/样本,这应该是可行的。请注意,如果您像在发布的代码中那样进行五次读取,如果您的代码执行的代码很少,则最大捕获速率将为 2kHz。


至于如何捕获数据,您需要处理这样一个事实,即没有放大的麦克风不会为您提供 0-5V 读数,如果您使用analogRead(). 事实上,麦克风输出电压从正向负摆动,但是,负电压不会被 ADC 拾取,并且仅显示为零,除非您给麦克风提供电压偏移。


我不确定您将最小幅度与最大幅度进行比较的代码应该做什么。您想将音频数字化吗?在这种情况下,您需要保存从 收集的所有幅度读数analogRead(),然后您可以在另一台计算机上对它们运行 FFT:Arduino 很可能不够快,无法对数据进行频率分析。

于 2013-04-11T06:03:46.280 回答
0

我听说过,或者更确切地说记得读过,ADC 每秒可以处理多达 10k 个样本,所以它应该可以达到 5 kHz。但是,我还没有尝试过,也没有链接来备份它。

试试看。

现在我知道一些 Arduino 库函数很慢,尤其是具有数百个周期开销的 DigitalRead/Write。其中大部分是健全性检查,允许人们只执行 DigitalRead/Write 而无需考虑设置所有内容。

但是,为了发挥最大性能,您可以考虑编写针对您的用例进行优化的自己的 AnalogRead。

至少有一些关于这个主题的链接:

于 2013-04-09T11:34:36.990 回答
0

我碰巧刚刚使用 Arduino Uno 和您的类似代码尝试过这个,我已经能够平均每秒采样 8000 次。那是 4 kHz 的奈奎斯特频率,所以你很好,但误差不大。

于 2018-11-06T21:35:48.463 回答