You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32 ADC2_GET_RAW采样速度提升及FM4替代可行性咨询

问题描述

我使用ESP32(WiFi Kit 32 V3)搭配两个间距1米的麦克风进行声速测量,期望实现至少35次/毫秒的采样率,但目前仅能达到25.34次/毫秒,相关代码如下。现咨询如何提升采样速度,以及更换为FM4 Starter Kit微控制器是否更合适?

#include <stdio.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <driver/adc.h>
#include <esp_system.h>

#define MEASUREMENTS 30000
int measurements1[MEASUREMENTS]; // 全局数组
int measurements2[MEASUREMENTS]; // 全局数组

class Stereomic {
  public:
    Stereomic(adc1_channel_t ad1, adc2_channel_t ad2) {
      adc1_config_width(ADC_WIDTH_BIT_12);
      adc1_config_channel_atten(ad1, ADC_ATTEN_DB_11); 
      adc2_config_channel_atten(ad2, ADC_ATTEN_DB_11); 
    }

    void runMeasurement() {
      unsigned long start_time = millis();

      for (int i = 0; i < MEASUREMENTS; ++i) {
        measurements1[i] = adc1_get_raw(ADC1_CHANNEL_6);
        adc2_get_raw(ADC2_CHANNEL_3,ADC_WIDTH_BIT_12, &measurements2[i]);
      }

      unsigned long end_time = millis();
      unsigned long elapsed_time_ms = end_time - start_time;
      Serial.printf("测量耗时: %lu 毫秒\n", elapsed_time_ms);
      Serial.printf("采样率: %f 次/毫秒。目标:35次/毫秒(当前最优25.34次/毫秒)\n", ((float)MEASUREMENTS / (float)elapsed_time_ms));
    }
};

void setup() {
  Serial.begin(115200);
  setCpuFrequencyMhz(240);
}

void loop() {
  if (Serial.available()) {
    Serial.println("开始");
    Serial.println("按下回车键开始测量...");
    Serial.read();

    Stereomic mic(ADC1_CHANNEL_6, ADC2_CHANNEL_3);
    mic.runMeasurement();
  }
  delay(10);
}
解决方案

一、提升ESP32采样速度的优化方案

当前代码采用单次手动调用ADC采样函数的方式,开销较大,可从以下几点优化:

  • 复用ADC配置,避免重复初始化
    目前每次创建Stereomic对象都会重新配置ADC,产生额外开销。将ADC配置代码移到setup()中,只初始化一次:

    void setup() {
      Serial.begin(115200);
      setCpuFrequencyMhz(240);
      // 提前配置ADC
      adc1_config_width(ADC_WIDTH_BIT_12);
      adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); 
      adc2_config_channel_atten(ADC2_CHANNEL_3, ADC_ATTEN_DB_11); 
    }
    

    同时修改Stereomic构造函数,移除重复的配置代码。

  • 使用ADC DMA连续采样模式
    ESP32的ADC1支持DMA驱动的连续采样,相比单次调用adc1_get_raw能大幅降低CPU开销。可配置ADC1扫描多个通道(若两个麦克风都接ADC1),或使用DMA双缓冲实现连续采样;优先使用ADC1,避免ADC2受WiFi/蓝牙占用的限制。

  • 关闭无关外设,释放总线带宽
    关闭未使用的WiFi、蓝牙模块,这些外设会占用系统总线和CPU资源,影响ADC采样效率。在setup()中添加:

    esp_wifi_stop();
    esp_bt_controller_disable();
    
  • 优化循环与内存访问

    • 展开循环体(比如每次处理2-4组采样),减少循环判断开销;
    • 确保采样数组在DRAM中(全局变量默认已满足),避免内存访问延迟;
    • 采样循环中仅保留核心采样操作,避免额外逻辑干扰。
  • 提升采样任务优先级
    创建高优先级FreeRTOS任务执行采样,避免被低优先级任务抢占:

    SemaphoreHandle_t samplingSemaphore;
    
    void samplingTask(void *pvParameters) {
      while(1) {
        if(xSemaphoreTake(samplingSemaphore, portMAX_DELAY) == pdTRUE) {
          // 执行采样逻辑
          Stereomic mic(ADC1_CHANNEL_6, ADC2_CHANNEL_3);
          mic.runMeasurement();
        }
      }
    }
    
    void setup() {
      // ... 其他配置
      samplingSemaphore = xSemaphoreCreateBinary();
      xTaskCreatePinnedToCore(samplingTask, "SamplingTask", 4096, NULL, 10, NULL, 0); // 绑定核心0,优先级10
    }
    
  • 调整ADC时钟
    参考ESP32规格书,适当提高ADC时钟(不超过硬件限制),通过修改寄存器或ESP-IDF配置调整,提升采样速率。

二、是否更换为FM4 Starter Kit?

FM4 Starter Kit(瑞萨FM4系列MCU)更适合你的场景,理由如下:

  • 采样率达标轻松:FM4系列ADC普遍支持1MSPS甚至更高采样率,远超35次/毫秒的需求;
  • 同步采样更精准:部分FM4型号支持多ADC通道同步采样,能保证两个麦克风的采样数据严格同步,这对声速测量的时间差计算至关重要——而ESP32的ADC1和ADC2无法实现真正的同步采样;
  • 采样开销更低:FM4的ADC硬件设计偏向高速模拟采集,CPU开销远低于ESP32的手动单次采样模式。

若项目对采样同步性和速率要求较高,更换FM4 Starter Kit是更优选择,但需注意其开发环境(瑞萨e2studio)与ESP32不同,需重新适配代码。

内容的提问来源于stack exchange,提问作者JB_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 08:10:19