发声体产生的振动在空气或其他物质中的传播叫作声波。声波可以借助各种介质向四面八方传播,根据频率的不同,可分为普通的声波(人耳能听到的,频率为20~20000Hz)和超声波(人耳不能听到,频率大于20000Hz)。声波传感器可以检测环境中的声波信号,根据检测频率的不同也可分为普通的声音传感器和超声波传感器两类。本文将介绍普通的声音传感器,下文再介绍超声波传感器。
1、声音传感器简介
声音传感器的作用相当于一个话筒(麦克风)。它用来接收声波,显示声音的振动图像,该传感器内置一个对声音敏感的电容式驻极体话筒。声波使话筒内的驻极体薄膜振动,导致电容的变化,而产生与之对应变化的微小电压。这一电压随后被转化成0-5V的电压,经过A/D转换被数据采集器接收,并传送给计算机。
2、DO与AO模块
DO与AO和光敏、热敏传感器模块一样。DO模块只传送数字量,就是根据震动的原理识别声音 的有无,不能识别特定频率的声音,也不能对噪声的强度进行测量。下图是只有DO模块的声音传感器。
当声音传感器模块检测到的环境声音强度达不到设定阈值时,OUT引脚输出高电平;当外界环境声音强度超过设定阈值时,OUT输出低电平。低电平并不会持续,声音一旦结束,传感器马上停止输出低电平。另外该传感器上面的蓝色的电位器可以调节声音敏感度(触发音量的阈值)。
还有一种声音传感器模块是4引脚带AO的,不仅能检测声音是否能够达到阈值,还能检测具体的声音强度,该传感器模块上的麦克风可将音频信号转换为模拟信号,模拟信号送AD模块PCF8591将模拟信号转为数字信号通过IIC总线送树莓派进行处理显示。
3、声音传感器与树莓派的连接
我们使用4引脚声音传感器,DO接树莓派GPIO19,VO(AO)接PCF8591的IN0。PCF8591接法参考25电阻传感器那部分。
4、实验代码与结果
实验一用DO输出检测是否有声音。如果有声音则LED灯亮,没有声音则LED灯灭
import time
import RPi.GPIO as GPIO# 指定编号规则为BOARD
GPIO.setmode(GPIO.BOARD)# 定义传感器连接的GPIO引脚
sound = 35
Led = 11
Button = 13# 指定13/35号引脚模式为输入模式,11为LED灯输出引脚
# 默认拉高到高电平,低电平表示OUT口有输出
GPIO.setup(Led, GPIO.OUT)
GPIO.setup(Button, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(sound, GPIO.IN, pull_up_down=GPIO.PUD_UP)try:while True:if GPIO.input(Button)==1: # 检测声音传感器模块是否输出低电平if GPIO.input(sound) == 0:print("检测到声音!")GPIO.output(Led, GPIO.LOW)time.sleep(0.2)else:print("没有检测到声音!")GPIO.output(Led, GPIO.HIGH)time.sleep(0.2)else:GPIO.cleanup()exit()except KeyboardInterrupt:print("停止检测声音!")finally:GPIO.cleanup()
实验二:通过IIC总线通信,PCF8591将AD转换后的值送树莓派,可以根据声音强度的大小控制LED灯的亮暗。 当然也可以把声音值送OLED显示(同学们自行实现OLED)。
import time
import RPi.GPIO as GPIO
import smbus# 指定编号规则为BCM
GPIO.setmode(GPIO.BOARD)
PWM_LED = 11
# 将第11个引脚设置为输出模式
GPIO.setup(PWM_LED, GPIO.OUT)
pwm = GPIO.PWM(PWM_LED, 80)
pwm.start(0)# 设置PCF8591地址
address = 0x48
# 创建一个smbus实例
bus = smbus.SMBus(1)def loop_print():while True:# 发送一个控制字节到设备bus.write_byte(address, 0x40)# 从设备读取单个字节# 若检测到有声音,该值会变小vioce_value = bus.read_byte(address)if vioce_value:print("读取到的声音值为:", vioce_value)pwm.ChangeDutyCycle(100-int(vioce_value/255*100))time.sleep(0.02)if __name__ == '__main__':try:loop_print()except KeyboardInterrupt:print("程序结束!")finally:pwm.stop()GPIO.cleanup()
这里将获取的声音值(0-255)转成0-100的值送PWM改变占空比。pwm.ChangeDutyCycle(100-int(vioce_value/255*100)),声音越大,LED灯越亮,反之越暗,time.sleep别延时太长时间,同学们可以试试,很好玩。