ESP32_实验10_声控灯的制作详解
声控灯制作详细步骤
接着我们之前的实验ESP32 & Python学习——实验9 声音传感器模块的原理和使用,很容易的,我们会联想到生活中的一个常用的应用场景——声控灯,于是这期就让我们来尝试理解并完成声控灯的项目。
1 写在前面
1.1 目的
使用MicroPython编程语言完成基于ESP32单片机的声控灯的制作。
1.2 实现功能
使用声音传感器接收环境声音,声音(比如吼声、脚踏地板的声音)超过一定幅度,触发继电器吸合,使小灯的回路通电从而点亮小灯。
1.3 实现方式
1、编程语言:MicroPython,其实就是Python的嵌入式用法,和Python差不多。
2、主控ECU:ESP32。(这里我使用普中ESP32开发板)
3、相关传感器:声音传感器模块、继电器模块。(开发板自带)
1.4 使用软件
1、编码工具:PyCharm、VS-Code或其他编码工具。
2、调试器:Thonny。这个工具也可以编码,但是一般只会在调试中使用,类似于51单片机中常使用的keil等。
2 硬件及其连接
2.1 硬件选择
1、主控单片机:ESP32。在这里我使用的是开发套件——普中ESP32开发板。当然你也可以选择单独的ESP32芯片,开发板用于学习使用,可以验证软件算法逻辑。用于实际固定成产品当然就不需要那么多集成模块,就要单独选材了。
2、继电器模块:在开发板上继承了继电器模块,使用就直接找到对应引脚连线就可以了。
3、声音传感器:声音传感器是单独的模块,我这个买的中配版本,带有这个模块。
4、LED灯:这里把开发板上的LED灯作为控制的用电器。当然,实际的使用中可以使用功率更大的电灯等,这时候要注意匹配不同的电源。
2.2 基本原理
这里主要传感器是声音传感器,其原理可以参考我之前的文章,可以移步到这里ESP32 & Python学习——实验9 声音传感器模块的原理和使用,这里就不再赘述了。
2.3 硬件连线图
主要的外围电路硬件接口连接示意图如下:

3 软件代码
3.1 软件设计思路
有了具体要实现的功能之后,就涉及到软件的设计和代码的实现。一般的,可能会先画一个软件流程图,然后再进行代码实现。当然我们这个项目没有太多复杂的东西,也可以不用这么多条条框框。
我这里就大概描述一下整个软件流程——
程序开始:
1、声音传感器相关设置:设置ESP32和声音传感器的接口,设置AD转换相关参数;
2、继电器相关的设置:设置ESP32和继电器控制接口。
3、主程序逻辑:将继电器接口置为常开状态,检测声音传感器的音量值。有两种情况:(1)如果大于阈值,将继电器的常开阀吸合,延迟X秒,使用电器所在电路导通,点亮LED灯,LED灯会保持点亮X秒。然后返回继续检测音量。(2)如果小于阈值,继续回到主程序检测音量值。
以下是deepseek帮我生成的流程图。这里有点小问题,我认为硬件初始化和下边的三个配置应该可以合并到一起。然后再往下传递,其他的没啥问题。

3.2 完整代码
好了,下边就是完整的软件代码实现。使用的编程语言为Python。
'''
实验名称:简单的声控灯设计
接线说明:使用普中ESP32开发板。
声音传感器部分:声音传感器模块AO口-->ESP32 IO 34;传感器VCC-->3.3V;传感器GND-->GND
继电器部分:IO口25和REL连接。继电器模块接口(COM)-->(3V3),(NC)常关接口-->LED灯(D1)。
实验现象:在Thonny软件的shell区能看见声音的数值。数值超过100后启动继电器开关并保持5s,从而使LED灯亮5s。
完成时间:2025/07/27
代码修改:罗特布克
备注内容:这里涉及到一个标定值,就是调试传感器的电位器AD11,可以插个薄片旋转,在安静的环境下调到1左右即可。
拓展思考:
1、可以监测声音分贝;
2、或者作为声控开关的检测部分。
'''
from machine import Pin,ADC
from machine import Pin #导入Pin模块
import time #导入time模块
sound = 34
relay=Pin(25,Pin.OUT) #定义继电器控制对象
# 初始化GPIO口
def setup():
global sound_ADC
sound_ADC = ADC(Pin(sound)) # 使用ADC类(模数转换器)创建名称为sound_ADC的ADC对象,该对象使用IO口34作为ADC的输入。
sound_ADC.atten(ADC.ATTN_11DB) # 11dB 衰减, 检测输入电压约0-3.6v。这里输入电源3.3v,满足条件。
# A0adc为ADC上传来的值,A0min为没有声音时ADC传来的电压,最大电压为3.3V。
# A0min可以定为1.7V,大概在3.3V的中间。因为声音转换后有正负半周,类似于正弦信号,音量大小只和幅值有关。
def Vvalue(A0adc,A0min):
vv1=(3.3*A0adc/4095-A0min)/(3.3-A0min)*1000 # 这里比较输入音量对应的电压值和1.7V的差距,除以总量程,放大1000倍,100倍声音辨识变化有点小。
# 1.7V就对应声音为0,和它的差距越大(不论正负)说明音量越大。调节电位器,就是在校准音量为0时的电压值。
vv1=abs(round(vv1)) # 先用round进行四舍五入,再用abs进行绝对值。因为音频有正负,绝对值表示音量大小。
return vv1 # 返回音量值0-1000.电压3.3V对应音量1000.
# 循环函数
def loop():
count = 0 # 计数值
while True: # 无限循环
voiceValue=Vvalue(sound_ADC.read(),1.7) # 设置0V对应的电压为1.7V
relay.value(0) # 将继电器开关置0,断开开关
if voiceValue: # 当声音值不为0
print ("Sound Value:", voiceValue) # 打印出声音值
if voiceValue > 100: # 如果声音传感器读取值大于100
print ("声音达到阈值! ", count) # 打印出计数值
count += 1 # 计数值累加
relay.value(1) # 将继电器开关置1,吸合开关
time.sleep(5) # 延时5s,LED灯开启5s
time.sleep(0.2) # 延时 200ms
# 程序入口
if __name__ == '__main__':
setup() # 初始化GPIO口
loop() # 循环函数
这里和上一个项目差不多,只是加了控制部分,当声音达到后控制继电器的吸合,从而实现由声音控制灯亮灭的效果。
4 调试结果
4.1 调试工具
编写代码一般使用VS-Code或者PyCharm等编码工具。而调试使用Thonny,这个工具也可以编写代码,最重要的是可以将代码导入单片机,让代码在单片机中运行起来,并且可以看到运行结果。一般在Thonny软件的shell界面可以打印调试运行结果。
4.1 shell调试界面
因为我们在代码中有写print语句,这个语句会在调试界面展示出来。这里是有输出音量大小和判断阈值是否超限两种。如下图所示。

4.2 运行图片
实际连接图如下,声音超过阈值,点亮LED灯:

5 拓展思考
这次使用的是AO接口,输出的是模拟量,这种方式会导致一个问题,就是经过了标定,然后阈值写到软件里边了,不便于随时调整触发的音量范围。而使用DO接口,可以调节触发的阈值大小。
顺便补充一下DO口输出原理。DO口只会输出高低电平,高电平表示声音超过阈值,并且此时led11会点亮。具体原理:声音比较大时,声音振幅大,音频信号类似于正弦信号,比较器LM393-1的2处的电压就会波动,当2处的电压小于3处电压(1.65v),B处就会产生高电平,导致6处电压高于5处,比较器LM393-2输出低电平,C处电压低,led11就会点亮。导致2处电压低的原因就是音频信号的负半周叠加经RP11降低的电压。如果没有声音时A处电压是1.7V,和本文中设置一样,那么一点小声音就会导致DO输出高电平。如果此时调节电位器使安静时电压升高比如到3V,那么音频信号来的电压的幅值至少要达到(3-1.65)V才能让2处电压低于3V(幅值大于1.35,负半周就会减去这个数值,就会减去这个值,让2处电压小于1.65V),DO才会输出高电平。
实际操作中就以一定音量为阈值,在这个声音下让led11点亮,然后再在这个音量下反向调节电位器让led11熄灭,这时候就设置好了触发阈值。

如果只是作为开关量,并且想要可以随时调节,可以选择DO输出。这种方式就是判断DO是否为高电平(输出1)。
6 版本
|
时间 |
修改内容 |
修改者 |
|
2025.08.11 |
初版形成:完成所有章节的内容编写。 |
罗特布克 |
|
2025.08.16 |
增加实物演示图,连线图等。整体完成 |
罗特布克 |
更多推荐



所有评论(0)