Overview

本文介绍如何用树莓派实现声光控开关设计,声光控开关是通过声音和光照度控制的开关,当环境的亮度达到某个设定值以下,同时环境的噪音超过某个值,这种开关就会开启。在本文中通过树莓派采集声音检测模块和光敏电阻模块输出的声音和光照度信号,通过采集到的声光信号控制开关通断,这里的开关是软件开关(用软件实现),当开关闭合时候,蜂蜜器响起。

DSC_5477

Experimental Parts

为了完成设计需要用到一下器件

PI
Pi3 x1
18
有源蜂鸣器模块 x1
16
声音检测模块 x1
14
光敏电阻模块 x1
LACC2006AD-12
面包板 x1
MCP3008
模数转换器 x1
LACC2006AD-31
公对公跳线 x若干
19
公对母跳线 x若干

Hardware

Raspberry Pi是一个出色的微型计算机,你可以使用它来控制数字输入和输出。但是当你想用它来处理模拟信号,例如像热敏电阻、电位器等模拟传感器输出时候,Raspberry Pi就有些力不从心了,就需要借助模数转换芯片将模拟信号转换成数字信号。本项目中利用MCP3008把光敏电阻模块输出的电压信号转换成数字信号,Pi根据转换后的数值大小以及声音检测传感器输出的信号控制蜂鸣器鸣叫。MCP3008是一款8通道10位精度的模数转换芯片。

声音检测模块可以检测周围环境的声音强度 , 此传感器只能识别声音的有无 , 能识别声音的大小或者特定频率的声音; 灵敏度可通过模块上的蓝色电位器调节;工作在3.3V-5V,因为树莓派GPIO口一般工作在3.3V电压,所以采用3.3V供电;模块输出数字’0’和数字’1’信号,块在环境声音强度达不到设定阈值时, DO 口输出高电平,当外界环境声音强度超过设定阈值时,模块D0输出低电平 ,阈值通过调节电位器设定。器原理图如图所示。

soundsensor

有源蜂鸣器模块采用2TY三极管(8550)驱动,工作在3.3V-5V之间,本文将其接到3.3V电压上,模块低电平触发。

各模块之间与树莓派具体连接请参考下图

Untitled Sketch_sound

在接线的时候请认清模块正负极,不要接反了,否则会烧坏你的Pi和模块。模块的上的GND接Pi上的0V;模块上的VCC接3.3V。对于如何识别Pi的IO口请参考这篇文章: How to read Raspberry Pi i/o pin diagram (GPIO pin graph)

Software

可以把pi直接接到显示器上,也可以通过SSH方式远程登录Pi。

1)编写代码

在/home/pi路径下用nano新建一个alarm.py(名字随意,你喜欢就好!)

sudo nano alarm.py

并往新建的文件中写入如下代码:

import RPi.GPIO as GPIO
import time
import os

buzzer = 14
sound = 26
# change these as desired - they're the pins connected from the
# SPI port on the ADC to the Cobbler
SPICLK = 11
SPIMISO = 9
SPIMOSI = 10
SPICS = 8

def init():
         GPIO.setwarnings(False)
         GPIO.setmode(GPIO.BCM)
         GPIO.setup(buzzer,GPIO.OUT)
         #GPIO.output(buzzer,GPIO.HIGH)
         GPIO.setup(sound,GPIO.IN,pull_up_down=GPIO.PUD_UP)
         # set up the SPI interface pins
         GPIO.setup(SPIMOSI, GPIO.OUT)
         GPIO.setup(SPIMISO, GPIO.IN)
         GPIO.setup(SPICLK, GPIO.OUT)
         GPIO.setup(SPICS, GPIO.OUT)
         pass

#buzzer alarm
def alarm():
         GPIO.output(buzzer,GPIO.LOW)
         time.sleep(1)
         GPIO.output(buzzer,GPIO.HIGH)
         time.sleep(1)


#read SPI data from MCP3008(or MCP3204) chip,8 possible adc's (0 thru 7)
def readadc(adcnum, clockpin, mosipin, misopin, cspin):
        if ((adcnum > 7) or (adcnum < 0)):
                return -1
        GPIO.output(cspin, True)  

        GPIO.output(clockpin, False)  # start clock low
        GPIO.output(cspin, False)     # bring CS low

        commandout = adcnum
        commandout |= 0x18  # start bit + single-ended bit
        commandout <<= 3    # we only need to send 5 bits here
        for i in range(5):
                if (commandout & 0x80):
                        GPIO.output(mosipin, True)
                else:
                        GPIO.output(mosipin, False)
                commandout <<= 1
                GPIO.output(clockpin, True)
                GPIO.output(clockpin, False)

        adcout = 0
        # read in one empty bit, one null bit and 10 ADC bits
        for i in range(12):
                GPIO.output(clockpin, True)
                GPIO.output(clockpin, False)
                adcout <<= 1
                if (GPIO.input(misopin)):
                        adcout |= 0x1

        GPIO.output(cspin, True)
        
        adcout >>= 1       # first bit is 'null' so drop it
        return adcout

# photoresistor connected to adc #0
photo_ch = 0

def main():
         init()
         time.sleep(2)
         print"will detect sonud and light signal"
         while True:
                  photo_value = readadc(photo_ch, SPICLK, SPIMOSI, SPIMISO, SPICS)
                  if (GPIO.input(sound) == False)and (photo_value>=650):  #detected sound signal and light intensity is low
                           print "Alarm!"
                           alarm()
                           time.sleep(1)
                  elif (GPIO.input(sound) == False)and (photo_value<=650):  #detected sound signal,but light intensity is high
                           GPIO.output(buzzer,GPIO.HIGH)
                           print "sound signal is detected ,but light intensity is high!"
                           time.sleep(1)
                  elif (GPIO.input(sound) == True)and (photo_value<=650):
                           GPIO.output(buzzer,GPIO.HIGH)
                           print "sound signal not detected ,light intensity is high!"
                           time.sleep(1)
                  elif (GPIO.input(sound) == True)and (photo_value>=650):
                           GPIO.output(buzzer,GPIO.HIGH)
                           print "sound signal not detected ,light intensity is low!"
                           time.sleep(1)
                           
                  print "light intensity is: " + str("%.1f"%((1024-photo_value)/1024.*100))+"%"
                  
                           
        

if __name__ =='__main__':
         try:
                  main()
         except KeyboardInterrupt:
                  pass
GPIO.cleanup()

上面的代码可以通过执行下面的shell命令得到

sudo wget http://osoyoo.com/driver/alarm.py

2)执行python程序

sudo python ./alarm.py

2017-03-24-091327_1824x984_scrot

3)测试

将手遮住光敏电阻模块,同时大声说话(或以其他方式发出响声),会发现间歇性蜂鸣器响起来了;只要将遮住光敏电阻模块的手移开或是停止发出声响,蜂鸣器也随即停止鸣叫。这样就实现了声光控开关的设计。