ESP32音频输入-MAX4466,MAX9814,SPH0645LM4H,INMP441(翻译)
有几种方法可以将模拟音频数据输入到ESP32中。
- 直接从内置的模数转换器(ADC)读取
- 这对于一次性读取很有用,但不适用于高采样率。
- 使用I2S通过DMA读取内置ADC
- 适用于模拟麦克风,例如MAX4466和MAX9814
- 使用I2S直接从I2S兼容外设读取
- 对于SPH0645LM4H,INPM441,ICS43432和ICS43434等麦克风有用
直接从ADC读取
ESP32上有两个内置ADC,ADC1和ADC2。
ADC1具有8个通道:
渠道 | 通用输入输出 | 渠道 | 通用输入输出 |
---|---|---|---|
ADC1_CHANNEL_0 | GPIO36 | ADC1_CHANNEL_4 | GPIO32 |
ADC1_CHANNEL_1 | GPIO37 | ADC1_CHANNEL_5 | GPIO33 |
ADC1_CHANNEL_2 | GPIO38 | ADC1_CHANNEL_6 | GPIO34 |
ADC1_CHANNEL_3 | GPIO39 | ADC1_CHANNEL_7 | GPIO35 |
ADC2有10个通道:
渠道 | 通用输入输出 | 渠道 | 通用输入输出 |
---|---|---|---|
ADC2_CHANNEL_0 | GPIO4 | ADC2_CHANNEL_5 | GPIO12 |
ADC2_CHANNEL_1 | GPIO0 | ADC2_CHANNEL_6 | GPIO14 |
ADC2_CHANNEL_2 | GPIO2 | ADC2_CHANNEL_7 | GPIO27 |
ADC2_CHANNEL_3 | GPIO15 | ADC2_CHANNEL_8 | GPIO25 |
ADC2_CHANNEL_4 | GPIO13 | ADC2_CHANNEL_9 | GPIO26 |
尽管有一些限制-WiFi子系统也使用ADC2,并且某些引脚还用于控制启动行为的捆绑引脚。这意味着在项目中坚持使用ADC1是最安全的。
从ADC读取非常简单-您可以使用Arduino函数或直接使用Espressif函数:
// read using Arduino
int sample = analogRead(35) // read using Espressif
int sample = adc1_get_raw(ADC1_CHANNEL_7);
ESP32 ADC非常不准确,如果您想获得准确的读数,可以使用校准设置。现在,这些操作大多在工厂完成,因此您的ESP32应该已经具有一些校准设置。也可以手动校准ADC。
要读取校准值,请使用以下代码,它将为您提供以毫伏为单位的值。这两个调用adc1_config_width
和adc1_config_channel_atten
是至关重要的,因为校准特性需要匹配ADC配置。
// calibration values for the adc
#define DEFAULT_VREF 1100
esp_adc_cal_characteristics_t *adc_chars; //Range 0-4096
adc1_config_width(ADC_WIDTH_BIT_12); // full voltage range
adc1_config_channel_atten(ADC1_CHANNEL_7, ADC_ATTEN_DB_11); // get the ADC characteristics
esp_adc_cal_characterize(
ADC_UNIT_1,
ADC_ATTEN_DB_11,
ADC_WIDTH_BIT_12,
DEFAULT_VREF,
adc_chars); // read a sample from the ADC
int sample = adc1_get_raw(ADC1_CHANNEL_7); // get the calibrated value
int milliVolts = esp_adc_cal_raw_to_voltage(sample, adc_chars);
使用I2S和DMA的高速ADC采样
直接使用ADC可以进行低频和一次性采样。为了采样高质量的音频数据,您将需要以16-40KHz的频率采样。您可以使用计时器来执行此操作,但这并不是ESP32的CPU资源的最佳用途。
更好的方法是使用内置的I2S外设将ADC的样本直接读取到内存中。
这是使用I2S读取内置ADC的基本设置。
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
.sample_rate = 40000,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S_LSB,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 2,
.dma_buf_len = 1024,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0}; //install and start i2s driver
i2s_driver_install(I2S_NUM_0, &i2s_config, 4, &i2s_queue); //init ADC pad
i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_7); // enable the ADC
i2s_adc_enable(I2S_NUM_0); // start a task to read samples from I2S
TaskHandle_t readerTaskHandle;
xTaskCreatePinnedToCore(readerTask, "Reader Task", 8192, this, 1, &readerTaskHandle, 0);
然后,您可以使用以下任务从ADC读取样本:
void readerTask(void *param)
{
I2SSampler *sampler = (I2SSampler *)param;
while (true)
{
// wait for some data to arrive on the queue
i2s_event_t evt;
if (xQueueReceive(sampler->i2s_queue, &evt, portMAX_DELAY) == pdPASS)
{
if (evt.type == I2S_EVENT_RX_DONE)
{
size_t bytesRead = 0;
do
{
// try and fill up our audio buffer
size_t bytesToRead = (ADC_SAMPLES_COUNT - sampler->audioBufferPos) * 2;
void *bufferPosition = (void *)(sampler->currentAudioBuffer + sampler->audioBufferPos);
// read from i2s
i2s_read(I2S_NUM_0, bufferPosition, bytesToRead, &bytesRead, 10 / portTICK_PERIOD_MS);
sampler->audioBufferPos += bytesRead / 2;
if (sampler->audioBufferPos == ADC_SAMPLES_COUNT)
{
// do something with the sample - e.g. notify another task to do some processing
}
} while (bytesRead > 0);
}
}
}
}
阅读完样本后,您可以执行所需的任何处理,I2S外设将在后台继续将样本从ADC读取到DMA缓冲区中。
MA4466的接线非常简单,只需将VCC连接至3v3,将GND连接至GND,将Out连接至与您要从其采样的ADC通道相对应的GPIO引脚。
尝试MAX9814的方法相同-您也可以通过将增益引脚连接至VCC或GND来发挥MAX9814的增益。
原文地址:https://blog.cmgresearch.com/2020/09/12/esp32-audio-input.html
ESP32音频输入-MAX4466,MAX9814,SPH0645LM4H,INMP441(翻译)的更多相关文章
- Android音频输入通道的底层硬件和软件开发分析
Android潜在的发展音频输入通道的软硬件分析 我们都知道耳机Mic集成在一直的那种四段耳机Mic插头是Android设备上比較经常使用.可是也会有分开的情况,比較假设在普通的PC机中装Androi ...
- Audition CS6在Win 7中“音频输入的采样频率与输出设备不匹配”问题的解决 - imsoft.cnblogs
1.运行Audion CS6,出现问题框. 2.右击任务栏右下方的那个小喇叭图标,在弹出的提示框里,单击“播放设备”.如图: 3.单击“播放设备”后,在图内左键单击“扬声器”然后双击“扬声器”,出现下 ...
- USB耳机声卡-音频输入/输出控制器:DP108替代兼容CM108
DP108是一款完全替代CM108的高度集成的单芯片USB音频解决方案芯片.方便的USB即插即用的兼容性,用户可以快速创建易用性,高质量和便携式USB音频产品基于高度集成的单芯片解决方案.所有重要的模 ...
- ESP32音频开发板ESP32-Korvo V1.1踩坑
电池供电ESP32-Korvo V1.1开发板供电电压低于3.9V不断复位: 报错->Brownout detector was triggered 断电探测器触发复位 根据同行资料发现,禁用断 ...
- 第38章 I2S—音频播放与录音输入—零死角玩转STM32-F429系列
第38章 I2S—音频播放与录音输入 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/ ...
- 调用WebService 实现在线双向翻译
>先了解一下Web Service的基本概念: Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传 ...
- 最简单的视音频播放示例4:Direct3D播放RGB(通过Texture)
本文接着上一篇文章继续记录Direct3D(简称D3D)播放视频的技术.上一篇文章中已经记录了使用Direct3D中的Surface渲染视频的技术.本文记录一种稍微复杂但是更加灵活的渲染视频的方式:使 ...
- 最简单的视音频播放演示样例4:Direct3D播放RGB(通过Texture)
===================================================== 最简单的视音频播放演示样例系列文章列表: 最简单的视音频播放演示样例1:总述 最简单的视音频 ...
- Deep Learning论文翻译(Nature Deep Review)
原论文出处:https://www.nature.com/articles/nature14539 by Yann LeCun, Yoshua Bengio & Geoffrey Hinton ...
随机推荐
- nginx 配置 conf stream
nginx从1.9.0版本开始,新增了ngx_stream_core_module模块,使nginx支持四层负载均衡.默认编译的时候该模块并未编译进去,需要编译的时候添加--with-stream参数 ...
- 安装Boost库
获取方式 官网下载合适版本:https://www.boost.org/ 此处用的是boost_1_75_0版本 开发环境 推荐使用GCC 7.x.x或以上编译器 安装Boost库 此处采用简易安装, ...
- GO学习-(37) 使用Air实现Go程序实时热重载
使用Air实现Go程序实时热重载 今天我们要介绍一个神器--Air能够实时监听项目的代码文件,在代码发生变更之后自动重新编译并执行,大大提高gin框架项目的开发效率. 为什么需要实时加载? 之前使用P ...
- GO学习-(3) VS Code配置Go语言开发环境
VS Code配置Go语言开发环境 VS Code配置Go语言开发环境 说在前面的话,Go语言是采用UTF8编码的,理论上使用任何文本编辑器都能做Go语言开发.大家可以根据自己的喜好自行选择.编辑器/ ...
- Clang:LLVM的C语言家族前端
Clang:LLVM的C语言家族前端 Clang项目为LLVM 项目的C语言家族(C,C ++,Objective C / C ++,OpenCL,CUDA和RenderScript)中的语言提供了语 ...
- NX二次开发-克隆操作
模板文件: 克隆替换字符串: 1 #include "Text.h" 2 extern DllExport void ufsta(char *param, int *returnC ...
- 【NX二次开发】创建老版的基准平面uf5374
使用uf5374() 源码: double dP1[3] = { 0.0,0.0,0.0 }; double dP2[3] = { 0.0,1.0,0.0 }; double dP3[3] = { 0 ...
- QueryTable的使用以及错误
1.QuerySeter的filter使用遇到的错误 1.1 Filter里的字段名和操作符要用双下划线."__" 不是" _",否则会被认为成是列名的一部分, ...
- 听说你还不知道Spring是如何解决循环依赖问题的?
Spring如何解决的循环依赖,是近两年流行起来的一道Java面试题. 其实笔者本人对这类框架源码题还是持一定的怀疑态度的. 如果笔者作为面试官,可能会问一些诸如"如果注入的属性为null, ...
- Redis不是只有get set那么简单
我以前还没接触Redis的时候,听到大数据组的小伙伴在讨论Redis,觉得这东西好高端,要是哪天我们组也可以使用下Redis就好了,好长一段时间后,我们项目中终于引入了Redis这个技术,我用了几下, ...