本次课程为昉·星光开发板IoT开发系列课程的第十一讲,将带领同学们在昉·星光开发板上,使用火焰传感器和蜂鸣器制作火灾报警装置。
本次课程,在昉·星光开发板V1和V2上,操作步骤相同。
一、学习目标
- 学习昉·星光开发板通过火焰传感器探测火光,通过蜂鸣器进行报警
二、准备工作
在开始本次课程的实际操作之前,同学们需要做好一些准备工作,课程中涉及到的硬件如下:
- 开发板:昉·星光开发板
- 火焰传感器: 带AO输出的火焰传感器
- 模数转换模块:ADS1115
- 蜂鸣器:无源蜂鸣器
- 杜邦线:若干

关于火焰传感器和ADS1115的具体使用,请提前阅读 昉·星光系列课程9:昉·星光开发板火焰传感器探测火光。
三、蜂鸣器使用原理
本次课程中,使用的蜂鸣器模块具体如下:

蜂鸣器分为有源蜂鸣器和无源蜂鸣器。这里的源不是指电源,而是指蜂鸣器内部的是否带有震荡源。
有源蜂鸣器内部自带震荡源,只要给他电压就能发声,其使用也较为简单,开发板上的程序使用一个数字GPIO口控制其信号输入口即可,输出高电平就发出声音,输出低电平就不发声。不过,其发声的频率都是固定的,使用中无法变化。
无源蜂鸣器内部没有震荡源,直接输出高电平到其信号输入口不会使其发声,需要通过200~5KHz的方波才能驱动其发声。不同频率的方波,能带来音调的变化,通过控制频率和时长,能够实现midi单声道音乐的播放。
在这篇课程中,讲的是无源蜂鸣器的使用。有源蜂鸣器的使用,大家可以自己了解,没有任何难度。
四、无源蜂鸣器使用
通过上述无源蜂鸣器的原理,我们可以得知,要驱动其发声,需要给其提供一个200~5KHz频率的方波驱动信号。
因为200~5KHz的频率并不高,所以可以直接控制GPIO口的高低电平时间来实现方波的输出。
首先,将火焰传感器模块的AO接口与和ADS1115的A0接口相连,使得ADS1115能够获取火焰传感器输出的模拟电压信号。具体连接方式,请参考 昉·星光系列课程9:昉·星光开发板火焰传感器探测火光。
然后,参考下图,将无源蜂鸣器连接到昉·星光开发板:

实物连接如下:

注意:
应根据实际使用的传感器,确定供电电压。本次课程中使用的火焰传感器模块和ADS1115模块,均使用5V供电电压,使用的无源蜂鸣器,可以使用5V或者3.3V供电,课程中为3.3V。
赛昉官方已经为我们提供了蜂鸣器测试的程序,可以从演示源代码 buzzer.py 下载,其具体内容如下:
'''Please make sure the buzzer is connected to the correct pins.The following table describes how to connect the buzzer to the 40-pin header.-----------------------------------------Passive Buzzer___Pin Number_____Pin Name VCC 1 3.3V Power GND 6 GND I/O 18 GPIO51-----------------------------------------'''import VisionFive.gpio as GPIOimport timebuzz_pin = 12ErrOutOfRange = 0def setup(): #Configure the direction of buzz_pin as out. GPIO.setup(buzz_pin, GPIO.OUT) #Configure the voltage level of buzz_pin as high. GPIO.output(buzz_pin, GPIO.HIGH)def pitch_in_check(): val_in = input('Enter Pitch (200 to 20000): ') val = float(val_in) if 200 <= val <= 20000: return val else: print('The input data is out of range (200 to 20,000 Hz). Please re-enter.') return ErrOutOfRangedef loop(pitch, cycle): delay = 1.0 / pitch cycle = int((cycle * pitch)/2) #Buzzer beeps. while cycle >= 0: GPIO.output(buzz_pin, GPIO.LOW) time.sleep(delay) GPIO.output(buzz_pin, GPIO.HIGH) time.sleep(delay) cycle = cycle - 1def destroy(): GPIO.output(buzz_pin, GPIO.HIGH) GPIO.cleanup()if __name__ == '__main__': setup() try: #Input value of pitch (200 to 20,000 Hz). pitch = pitch_in_check() while pitch == 0: pitch = pitch_in_check() #Input value of cycle time (seconds). cycle_in = input("Enter Cycle (seconds): ") cycle = int(cycle_in) #The buzzer beeps with the specified pitch and cycle. loop(pitch, cycle) finally: destroy()上述程序的关键部分,为loop(pitch, cycle),前者为频率,后者为播放时长。在loop()调用中,会根据频率,计算高低电平保持的时间,根据播放时长,计算需要循环的次数,从而实现特定频率的方波,并持续指定的时间。
要运行以上的程序,还需要安装相应的赛昉GPIO支持库,具体如下:
# 安装扩展库sudo pip show VisionFive.gpio编写完成后,运行 buzzer.py ,根据提示输入频率Pitch和循环时长Cycle,即可驱动蜂鸣器发声。
python3 buzzer.py

驱动蜂鸣器发声成功后,我们再编写一个程序buzzer_alarm.py,让蜂鸣器能够交替以两种频率发声,具体代码如下:
# -*- coding: utf-8 -*-# file: ~/projects/buzzer/buzzer_alarm.pyimport VisionFive.gpio as GPIOimport timebuzz_pin = 12ErrOutOfRange = 0def setup(): #Configure the direction of buzz_pin as out. GPIO.setup(buzz_pin, GPIO.OUT) #Configure the voltage level of buzz_pin as high. GPIO.output(buzz_pin, GPIO.HIGH)def loop(pitch, cycle): delay = 1.0 / pitch cycle = int((cycle * pitch)/2) #Buzzer beeps. while cycle >= 0: GPIO.output(buzz_pin, GPIO.LOW) time.sleep(delay) GPIO.output(buzz_pin, GPIO.HIGH) time.sleep(delay) cycle = cycle - 1def destroy(): GPIO.output(buzz_pin, GPIO.HIGH) GPIO.cleanup()if __name__ == '__main__': setup() try: while True: pitch = 1200 cycle = 1 loop(pitch, cycle) pitch = 1000 cycle = 1 loop(pitch, cycle) finally: destroy()编写完成后,运行 buzzer_alarm.py,蜂鸣器就会以两种不同的音调,交替发声了。
python3 buzzer_alarm.py五、火灾报警器功能实现
在 无源蜂鸣器使用 部分,已经能够驱动蜂鸣器发声了,再结合 昉·星光系列课程9:昉·星光开发板火焰传感器探测火光,当检测到火光强度高于一定阈值的时候,就驱动蜂鸣器发声,从而实现火灾报警的功能。
具体的代码如下:
# -*- coding: utf-8 -*-# file: ~/projects/buzzer/fire_alarm.pyimport VisionFive.gpio as GPIOimport ADS1115import timeimport numpyimport smbus2FIRE_ALARM_VALUE = 40buzz_pin = 12# 初始化ADS1115模块ads = ADS1115.ADS1115()def setup(): #Configure the direction of buzz_pin as out. GPIO.setup(buzz_pin, GPIO.OUT) #Configure the voltage level of buzz_pin as high. GPIO.output(buzz_pin, GPIO.HIGH)def loop(pitch, cycle): delay = 1.0 / pitch cycle = int((cycle * pitch)/2) #Buzzer beeps. while cycle >= 0: GPIO.output(buzz_pin, GPIO.LOW) time.sleep(delay) GPIO.output(buzz_pin, GPIO.HIGH) time.sleep(delay) cycle = cycle - 1def destroy(): GPIO.output(buzz_pin, GPIO.HIGH) GPIO.cleanup()if __name__ == '__main__': setup() try: while True: # 读取ADS1115模块通道0的数据,也就是A0 volt = ads.readADCSingleEnded(0) # 转换 per = numpy.interp(volt, [0, 5000], [0, 100]) # 输出信息 print("%d mV of A0, val is %f" % (volt, per)) if per >= FIRE_ALARM_VALUE: print(" Fire Alarm!!!") pitch = 800 cycle = 0.2 loop(pitch, cycle) pitch = 1000 cycle = 0.2 loop(pitch, cycle) else: time.sleep(1) finally: destroy()在上面的程序中,先通过ADS1115获取火焰传感器的检测数据,然后检查该数据是否达到了阈值,如果达到了,则驱动蜂鸣器发声,否则不发声。
编写完成后,运行 fire_alarm.py,蜂鸣器默认不会发声,如果使用火光靠近火焰传感器,达到一定距离内,将会发声,并且使用不同的频率变化。
python3 fire_alarm.py本课程实际测试的情况如下:
- 火柴点火后靠近:

- 实际报警的数据:

测试时,没有检测到时,火焰传感器模拟输出结果数值较小。
当使用火柴火焰靠近到一定距离时,火焰传感器的模拟输出结果显著上升超过40,从而触发报警,并使用不同的频率交替发声提醒注意。
六、总结
在本次课程中,我们学习了无源蜂鸣器的使用,以及配合火焰传感器,实现火灾报警的功能。
在实际应用中,往往需要多种外部设备相互配合,来实现特定的功能。火灾报警的功能,除了配合蜂鸣器发生声音警告,还可以配合使用红色灯光闪烁警告。
|