测试功能描述:

程序会先测量 2 秒环境音量作为基准,然后开始实时显示音量柱状图,并在 30 秒后自动结束,当检测到音量超过阈值时会显示提示并打开led灯

一,硬件准备:

1.ESP32 CH3 USB开发板1块

2.INMP441 麦克风1个

3.LED灯一个

二,连线

1.麦克风与esp32连接

  • SCK -> GPIO14
  • WS -> GPIO15
  • SD -> GPIO2
  • VDD -> 3.3V
  • GND -> GND

2.麦克风与esp32连接

  • 正极 -> GPIO25
  • 负极 -> GND

三,测试代码

import machine
import ustruct
import utime
import math# 硬件配置 - INMP441麦克风连接到I2S0
i2s = machine.I2S(0,sck=machine.Pin(14),   # 时钟引脚ws=machine.Pin(15),    # 字选择引脚sd=machine.Pin(2),     # 数据引脚mode=machine.I2S.RX,   # 接收模式bits=16,               # 16位采样深度format=machine.I2S.MONO, # 单声道rate=16000,            # 采样率16kHzibuf=40000             # 内部缓冲区大小
)# LED配置
led = machine.Pin(25, machine.Pin.OUT)  # LED连接到GPIO25# 采样参数
SAMPLE_RATE = 16000
BUFFER_SIZE = 1024  # 每次读取的样本数
FFT_SIZE = 256      # FFT大小(必须是2的幂,降低以提高性能)
DETECTION_THRESHOLD = 20000  # 语音检测阈值
COMMAND_TIMEOUT = 1  # 命令持续时间(秒)
LED_ON_DURATION = 3  # LED亮起持续时间(秒)
VOLUME_BAR_LENGTH = 40  # 音量条长度# 汉宁窗函数
def hanning_window(size):"""生成汉宁窗函数"""window = []for i in range(size):window.append(0.5 * (1 - math.cos(2 * math.pi * i / (size - 1))))return window# 简易FFT实现(Cooley-Tukey算法)
def fft(samples):"""简易FFT实现"""n = len(samples)if n <= 1:return sampleseven = fft(samples[0::2])odd = fft(samples[1::2])result = [0j] * n  # 使用复数列表for k in range(n//2):angle = -2 * math.pi * k / nt = odd[k] * (math.cos(angle) + 1j * math.sin(angle))result[k] = even[k] + tresult[k + n//2] = even[k] - treturn result# 计算频谱能量
def calculate_spectrum(samples):"""计算信号的频谱能量"""# 应用汉宁窗window = hanning_window(len(samples))windowed_samples = [samples[i] * window[i] for i in range(len(samples))]# 计算FFTfft_data = fft(windowed_samples)# 计算幅度谱(能量)magnitudes = [math.sqrt(fft_data[i].real**2 + fft_data[i].imag**2) for i in range(len(fft_data)//2)]return magnitudes# 提取语音特征
def extract_features(spectrum):"""从频谱中提取语音相关特征"""# 人类语音主要集中在300-3400Hz# 计算这个范围内的能量low_freq = int(300 * FFT_SIZE / SAMPLE_RATE)high_freq = int(3400 * FFT_SIZE / SAMPLE_RATE)# 确保索引在有效范围内low_freq = max(0, min(low_freq, len(spectrum)-1))high_freq = max(0, min(high_freq, len(spectrum)-1))# 计算语音频率范围内的能量voice_energy = sum(spectrum[low_freq:high_freq])return voice_energy# 环境特征校准
def calibrate_environment(duration=2):"""测量环境特征,返回建议的阈值"""print(f"正在校准环境特征 ({duration}秒)...")mic_samples = bytearray(BUFFER_SIZE * 2)samples_array = [0] * BUFFER_SIZEmax_feature = 0avg_feature = 0samples_count = 0for _ in range(int(SAMPLE_RATE / BUFFER_SIZE * duration)):# 从I2S读取数据i2s.readinto(mic_samples)# 转换为整数数组for i in range(BUFFER_SIZE):samples_array[i] = ustruct.unpack_from('<h', mic_samples, i*2)[0]# 计算频谱和特征spectrum = calculate_spectrum(samples_array[:FFT_SIZE])feature = extract_features(spectrum)avg_feature += featuresamples_count += 1if feature > max_feature:max_feature = feature# 显示实时特征normalized = min(1.0, feature / 100000)bar_length = int(normalized * VOLUME_BAR_LENGTH)feature_bar = '█' * bar_length + '-' * (VOLUME_BAR_LENGTH - bar_length)print(f"\r环境特征: [{feature_bar}] {feature:.1f}", end='')utime.sleep_ms(50)if samples_count > 0:avg_feature /= samples_count# 建议阈值:环境最大特征的1.5倍suggested_threshold = max_feature * 1.5# 确保阈值不低于默认值suggested_threshold = max(DETECTION_THRESHOLD, suggested_threshold)print(f"\n环境校准完成: 平均={avg_feature:.1f}, 最大={max_feature:.1f}")print(f"建议阈值: {suggested_threshold:.1f}")return suggested_threshold# 语音命令识别
def detect_command(buffer, threshold=DETECTION_THRESHOLD):"""检测语音命令"""samples_array = [0] * BUFFER_SIZE# 转换为整数数组for i in range(BUFFER_SIZE):samples_array[i] = ustruct.unpack_from('<h', buffer, i*2)[0]# 计算频谱spectrum = calculate_spectrum(samples_array[:FFT_SIZE])# 提取特征feature = extract_features(spectrum)# 计算音量(用于显示)volume = sum(abs(samples_array[i]) for i in range(BUFFER_SIZE)) // BUFFER_SIZEreturn feature > threshold, feature, volume# 主控制循环
def voice_control_loop(threshold=DETECTION_THRESHOLD):print("语音控制LED系统已启动")print(f"语音检测阈值: {threshold}")# 创建缓冲区mic_samples = bytearray(BUFFER_SIZE * 2)led_state = Falselast_command_time = 0command_active = Falsetry:while True:# 从I2S读取数据i2s.readinto(mic_samples)# 检测命令command_detected, feature_value, volume = detect_command(mic_samples, threshold)current_time = utime.ticks_ms()# 状态显示status = "ON " if led_state else "OFF"cmd_status = "CMD" if command_detected else "   "# 显示特征值柱状图normalized = min(1.0, feature_value / 100000)bar_length = int(normalized * VOLUME_BAR_LENGTH)feature_bar = '█' * bar_length + '-' * (VOLUME_BAR_LENGTH - bar_length)print(f"\r特征: [{feature_bar}] {feature_value:.1f} | 音量: {volume:4d} | 状态: {status} | {cmd_status}", end='')# 命令逻辑if command_detected and not command_active:command_active = Trueprint("\n命令开始检测")if command_detected:last_command_time = current_time# 如果命令持续时间超过阈值,执行动作if command_active and utime.ticks_diff(current_time, last_command_time) > COMMAND_TIMEOUT * 1000:command_active = False# 如果LED关闭,则打开if not led_state:led.on()led_state = Trueprint("\nLED已点亮")else:# 如果LED已打开,则关闭led.off()led_state = Falseprint("\nLED已关闭")# 如果LED已打开且超时,则关闭if led_state and utime.ticks_diff(current_time, last_command_time) > LED_ON_DURATION * 1000:led.off()led_state = Falseprint("\nLED已关闭(超时)")# 短暂延迟utime.sleep_ms(50)except KeyboardInterrupt:print("\n程序已停止")finally:# 关闭资源i2s.deinit()led.off()# 运行语音控制程序
def main():# 执行环境校准threshold = calibrate_environment()# 使用校准后的阈值voice_control_loop(threshold)# 启动程序
main()    

四,运行效果截图

 

 

  • 代码中的引脚定义可以根据实际接线情况调整
  • 内部缓冲区大小 (ibuf) 可能需要根据 ESP32 的内存情况调整
  • 采样率和位深度可以根据需要修改,但会影响音频质量
  • 如果出现内存不足错误,尝试减小 BUFFER_SIZE 值
  • 麦克风的灵敏度可以通过修改 INMP442 的增益设置来调整

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/909871.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/909871.shtml
英文地址,请注明出处:http://en.pswp.cn/news/909871.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

io.net 携手 Walrus,为 AI 和机器学习应用提供去中心化存储与计算能力

作为最大规模的按需云计算提供商之一&#xff0c;io.net 部署并管理来自地理分布式节点的去中心化 GPU 集群&#xff0c;现正与基于 Sui 构建的去中心化数据存储协议 Walrus 深度整合。此次合作为去中心化 AI 和机器学习&#xff08;machine learning&#xff0c;ML&#xff09…

【上市公司文本分析】根据句号和分号进行文本分割,提取含有特定关键词的语句并导出为EXCEL

本文介绍了一种基于Python的中文文本分析方法&#xff0c;用于从年报文件中提取含有关键词的语句。方法使用jieba分词库进行中文分词&#xff0c;通过自定义词典提高分词准确性。程序首先读取并预处理文本&#xff08;统一标点符号、去除换行符&#xff09;&#xff0c;然后按句…

小白畅通Linux之旅-----DHCP服务项目实战

目录 一、项目拓扑 二、项目要求 三、项目准备 DHCP服务器 1、下载dhcp服务 2、准备 1.txt 文件 &#xff08;为内部客户机设置为固定获得ip&#xff09; 3、准备2.txt文件 &#xff08;为内部网络分配ip&#xff09; 4、准备 3.txt 文件&#xff08;为外部网络配置ip&…

eps转pdf-2025年6月18日星期三

1.打开cmd。 使用 cd 命令切换到包含 EPS 文件的目录。例如&#xff0c;如果 EPS 文件在 E:\eps_files 目录下&#xff0c;输入以下命令&#xff1a; cd E:\eps_files 2. 转换单个 EPS 文件&#xff1a; 输入以下命令将单个 EPS 文件转换为 PDF 文件 epstopdf input.eps …

处理器特性有哪些?

处理器特性有哪些&#xff1f; 处理器的特性可以从多个维度进行划分&#xff0c;包括架构设计、性能指标、功能支持等。以下是处理器的主要特性分类及详细说明&#xff1a; 1. 架构特性 指令集架构&#xff08;ISA&#xff09; CISC&#xff08;复杂指令集&#xff0c;如x86&…

Vue3+TypeScript 导入枚举(Enum)最佳实践

在 Vue 3 TypeScript 项目中&#xff0c;导入枚举时通常不需要使用 import type&#xff0c;但具体取决于使用场景。以下是详细说明&#xff1a; 1. 枚举的特殊性 枚举在 TypeScript 中既是类型&#xff08;Type&#xff09;也是值&#xff08;Value&#xff09;&#xff1a…

主成分分析(PCA)例题——给定协方差矩阵

向量 x x x的相关矩阵为 R x [ 0.3 0.1 0.1 0.1 0.3 − 0.1 0.1 − 0.1 0.3 ] {\bm R}_x \begin{bmatrix} 0.3 & 0.1 & 0.1 \\ 0.1 & 0.3 & -0.1 \\ 0.1 & -0.1 & 0.3 \end{bmatrix} Rx​ ​0.30.10.1​0.10.3−0.1​0.1−0.10.3​ ​ 计算输入向量…

RTSP播放器低延迟实践:一次对毫秒级响应的技术探索

✅ 为什么说“大牛直播SDK的RTSP播放器延迟表现行业领先”&#xff1a; 1. 毫秒级延迟&#xff08;100ms~250ms&#xff09; windows平台rtsp播放器延迟测试 在业内常见的 RTSP 播放器中&#xff0c;传统开源方案&#xff08;如 VLC、FFmpeg 播放器封装&#xff09;延迟普遍在…

【postgresql中timestamp为6是什么意思?】

postgresql中timestamp为6是什么意思&#xff1f; postgresql中timestamp为6是什么意思&#xff1f;示例注意事项 postgresql中timestamp为6是什么意思&#xff1f; 在 PostgreSQL 中&#xff0c;TIMESTAMP 类型用于存储日期和时间信息。当你提到 TIMESTAMP(6)&#xff0c;这里…

EC2实例(Amazon Linux 2023)监控磁盘读写速度和I/O负载

在viewer端进行日志分析的时候&#xff0c;由于日志比较大&#xff0c;每个4.5G&#xff0c;一共9个viewer端&#xff0c;对应9个日志文件&#xff0c;而且判断音频帧和视频帧是否卡顿时&#xff0c;需要的样本也很多&#xff0c;各15000行&#xff0c;分析完成需要5分20秒左右…

SpringBoot电脑商城项目--收获地址列表

1. 收获地址列表展示-持久层 1.1 sql语句 1.2 AddressMapper接口编写抽象方法 /*** 根据用户id查询用户的收货地址数据* param uid* return*/List<Address> findByUid(Integer uid); 1.3 在xml文件中进行sql映射 <!-- DESC降序 --><select id"fin…

学校住宿缴费系统h5-——东方仙盟——仙盟创梦IDE

代码: <div class"form-group"><h4 style"color: #006400; margin-bottom: 15px;">费用明细 <input name"room_unit_price" id"room_unit_price" type"number" value"" style"width:65px;…

docker 目录更改,必须做数据迁移才能启动

要修改 Docker 镜像的存储位置 并迁移数据&#xff08;如从 /var/lib/docker 迁移到 /mnt/data/docker&#xff09;&#xff0c;需要以下步骤&#xff1a; 1. 停止 Docker 服务 在修改配置和迁移数据前&#xff0c;先停止 Docker 服务&#xff1a; sudo systemctl stop docke…

根据图片理解maven

maven 是一款强大的项目管理与构建工具&#xff0c;在 Java 开发中尤为常用&#xff0c;结合这张图&#xff0c;从核心功能、仓库体系、工作流程三方面快速了解&#xff1a; 一、核心作用 项目构建&#xff1a;自动完成编译、测试、打包、部署等流程&#xff08;比如把 .java…

阿里云中间件:解锁云端应用的强大引擎

走进阿里云中间件 在云计算的宏大版图中&#xff0c;阿里云无疑是一位举足轻重的参与者。而阿里云中间件&#xff0c;作为阿里云服务体系的关键构成部分&#xff0c;在整个云计算架构里扮演着不可或缺的角色&#xff0c;宛如一座桥梁&#xff0c;紧密地连接着底层基础设施与上…

windows下FFmpeg精简

1. 安装MSYS2和必要工具 下载并安装MSYS2打开 MSYS2中的 MinGW 64-bit 终端更新系统包&#xff1a; pacman -Syu # 如果提示关闭终端&#xff0c;关闭后重新打开再次运行&#xff1a; pacman -Su装编译工具链&#xff1a; pacman -S --needed base-devel mingw-w64-x86_64-t…

WPF数据绑定疑惑解答--(关于控件的Itemsource,Collection绑定)

1. ListView绑定的数据类型问题 在 MainWindow 的构造函数中绑定 List11.ItemsSource List<string> rpcListnew List<string>(); public MainWindow() {InitializeComponent();// 确保 List11 的 ItemsSource 已经绑定到 rpcListList11.ItemsSource rpcList; } …

【Centos7安装Cloudera Manager5.12、CDH5.12详细步骤】

安装Cloudera Manager&#xff08;5.12.1&#xff09;一定要细心&#xff0c;每一步走错都可能造成最终安装失败。 安装Cloudera Manager&#xff08;5.12.1&#xff09;一定要硬件资源充足。 本示例参考了众多网上资料&#xff08;放在文末&#xff09;&#xff0c;消耗了1000…

青少年编程与数学 01-011 系统软件简介 25 Web服务器及代理软件

青少年编程与数学 01-011 系统软件简介 25 Web服务器及代理软件 一、Web 服务器软件&#xff08;一&#xff09;定义与功能&#xff08;二&#xff09;历史与主要产品1. Apache HTTP Server2. Nginx3. Microsoft Internet Information Services&#xff08;IIS&#xff09;4. L…

Vue的隐形魔法:虚拟DOM和Diff算法如何让页面飞起来?

大家好&#xff0c;我是江城开朗的豌豆&#xff0c;一名拥有6年以上前端开发经验的工程师。我精通HTML、CSS、JavaScript等基础前端技术&#xff0c;并深入掌握Vue、React、Uniapp、Flutter等主流框架&#xff0c;能够高效解决各类前端开发问题。在我的技术栈中&#xff0c;除了…