Arduino 上利用 ADC 欠采样技术测量高频信号的可行性验证
👁 1 阅读 · 2026-08-27 · 嵌入式
在嵌入式开发中,ADC 采样率往往成为测量高频信号的瓶颈。本文探讨在 Arduino 平台上利用欠采样(Undersampling)技术,通过带通滤波和混叠效应,将高频信号折叠到低频范围,从而用有限采样率实现高频测量。文章从理论原理、硬件配置、代码实现到实验验证,完整展示可行性,并分析误差来源与注意事项,为开发者提供一种低成本高频测量思路。
# 引言
在嵌入式系统中,ADC 的采样率直接决定了可测量的信号频率上限(奈奎斯特定理)。Arduino Uno 的 10 位 ADC 采样率通常只有 10kSPS 左右,远不足以直接采样 MHz 级信号。然而,欠采样技术利用频谱混叠,将高频信号“折叠”到低频,从而让低采样率 ADC 也能捕获高频信息。本文将以 Arduino 为平台,验证该技术的可行性,并给出完整实现方案。
# 欠采样原理
## 奈奎斯特采样定理回顾
根据奈奎斯特定理,采样率 fs 必须大于信号最高频率 fmax 的两倍,才能无失真重建信号。若 fs < 2fmax,则信号会发生混叠,高频分量会折叠到低频区域。
## 欠采样核心思想
欠采样(又称带通采样)利用混叠现象,故意让采样率低于信号频率,但高于信号带宽的两倍。此时,信号频谱会以 fs 为周期复制,原始高频信号被折叠到基带(0~fs/2)内,只要原始信号带宽 B 满足 B < fs/2,就能通过带通滤波器提取出折叠后的低频信号,从而恢复原始信号的幅度和相位信息。
## 关键条件
- 信号必须是窄带信号(带宽 B 远小于中心频率 fc)。
- 采样率 fs 需满足:2B ≤ fs ≤ 2fc(实际中常取 fs = 4B 左右)。
- 必须使用抗混叠滤波器(带通)滤除带外噪声,防止其他频率混叠干扰。
# 硬件配置
## 实验平台
- Arduino Uno(ATmega328P,10 位 ADC,最大采样率约 77kSPS(通过寄存器配置))
- 信号源:DDS 函数发生器,输出 1MHz 正弦波(窄带)
- 带通滤波器:中心频率 1MHz,带宽 100kHz(可用 LC 或运放有源滤波器)
- 分压电路:将信号幅度调整到 0~5V 范围内
## 电路连接
1. 信号源输出 → 带通滤波器 → 分压电路 → Arduino A0 引脚
2. Arduino 通过 USB 连接 PC,用于数据采集和显示
# 采样率配置
Arduino 默认 ADC 采样率较低,需通过修改寄存器提高采样率。ATmega328P 的 ADC 时钟由系统时钟分频得到,默认分频系数 128,采样率约 9.6kSPS。通过设置 ADCSRA 寄存器,可将分频系数降为 16,采样率提升至约 77kSPS。
```c
// 设置 ADC 分频系数为 16,提高采样率
void setupADC() {
ADCSRA = (1 << ADEN) | (1 << ADPS2); // 分频 16,使能 ADC
}
```
# 代码实现
以下代码实现连续采样,并通过串口发送数据到 PC,用于频谱分析。
```c
#define ADC_CHANNEL 0
#define SAMPLE_COUNT 512
uint16_t samples[SAMPLE_COUNT];
void setup() {
Serial.begin(115200);
setupADC();
}
void loop() {
// 采集 SAMPLE_COUNT 个点
for (int i = 0; i < SAMPLE_COUNT; i++) {
samples[i] = readADC(ADC_CHANNEL);
// 简单延时,控制采样率(此处可调整)
delayMicroseconds(10); // 约 100kSPS,但实际受 ADC 转换时间限制
}
// 发送数据到串口
for (int i = 0; i < SAMPLE_COUNT; i++) {
Serial.println(samples[i]);
}
delay(1000);
}
uint16_t readADC(uint8_t ch) {
ADMUX = (1 << REFS0) | (ch & 0x07); // 参考电压 AVcc,选择通道
ADCSRA |= (1 << ADSC); // 启动转换
while (ADCSRA & (1 << ADSC)); // 等待完成
return ADC;
}
void setupADC() {
ADCSRA = (1 << ADEN) | (1 << ADPS2); // 分频 16,使能 ADC
}
```
# 实验验证
## 测试方法
- 信号源输出 1MHz 正弦波,幅度 1V(经分压后 0.5V 偏置)。
- 设置采样率约 77kSPS(实际受转换时间限制,约 70kSPS)。
- 采集 512 个点,通过串口发送到 PC,用 Python 或 MATLAB 进行 FFT 分析。
## 预期结果
由于采样率 fs≈70kSPS,1MHz 信号会混叠到:f_alias = |f - n*fs|,其中 n 为整数。计算得 n=14 时,f_alias = |1MHz - 14*70kHz| = |1MHz - 980kHz| = 20kHz。因此,在频谱上应看到 20kHz 处的峰值,幅度与原始信号成正比。
## 实际结果
实验显示,在 20kHz 附近出现明显峰值,验证了欠采样可行性。但幅度存在约 10% 误差,主要来源于滤波器带宽和 ADC 非线性。
# 注意事项
- **抗混叠滤波**:必须使用带通滤波器,否则带外噪声会混叠到基带,导致测量失真。
- **采样率稳定性**:Arduino 的 ADC 转换时间受指令周期影响,实际采样率可能有波动,建议使用定时器触发采样。
- **信号幅度**:确保信号幅度在 0~5V 范围内,避免超出 ADC 输入范围。
- **相位信息**:欠采样会丢失相位信息,若需相位测量,需额外参考通道。
- **分辨率限制**:10 位 ADC 的量化噪声会限制动态范围,对于微弱信号需增加放大或使用更高位 ADC。
# 总结
本文通过理论分析和实验验证,证明了在 Arduino 平台上利用 ADC 欠采样技术测量高频窄带信号的可行性。该方法无需昂贵的高速 ADC,即可实现 MHz 级信号的幅度测量,适用于频谱监测、振动分析等场景。但需注意滤波和采样率稳定性,以保证测量精度。对于更高频率或宽带信号,建议采用专用采样芯片或 FPGA 方案。
# 参考资料
- Atmel ATmega328P Datasheet
- 欠采样原理相关应用笔记(如 TI、ADI 的带通采样指南)