树莓派:烟雾报警装置

组件

  • Rasberry Pi主板
  • 树莓派电源
  • 40P软排线
  • PCF8591模数转换器模块
  • 烟雾传感器模块
  • 有源蜂鸣器模块
  • 面包板
  • 跳线

烟雾传感器模块原理图

MQ-2气体传感器:使用氧化锡半导体气敏材料。当环境温度在200-300℃时,氧化锡会吸附空气中的氧气并形成氧阴离子吸附,从而降低半导体中的电子密度,从而增加其电阻。当与烟雾接触时,如果晶界阻挡层被烟雾调制并发生变化,则可能导致表面电导率发生变化。因此可以获得烟雾存在的信息,烟雾浓度越高,材料的导电性越高,因此输出电阻越低。若有害气体达到一定浓度,蜂鸣器会发出蜂鸣声警告。

烟雾报警传感器有两个LED指示灯。POWER-LED是电源指示灯,接通电源后常亮。DOUT-LED是数字输出指示灯,当没有检测到烟雾时熄灭,DO输出高电平;当检测到烟雾时,DO输出低电平,DOUT-LED指示灯亮。而判定是否有烟雾的临界值可以通过旋转蓝色元件上的十字螺丝调节,调节到没有烟雾时DOUT-LED灯刚好熄灭时即可。

实验步骤

连接电路

有源蜂鸣器使用的电源为3.3V,烟雾传感器使用的是5V

树莓派 T型转接板 PCF8591模块
SDA(串行数据线) SDA SDA
SCL(串行时钟线) SCL SCL
5V 5V VCC
GND GND GND
烟雾传感器模块 T型转接板 PCF8591模块
AO * AIN0
DO G17 *
VCC 5V VCC
GND GND GND
有源蜂鸣器 T型转接板
I/O G18
VCC 3.3V
GND GND

开始编程

  • PCF8591模块采用的是I2C(IIC)总线通信,但在树莓派的镜像中默认是关闭的,在使用该传感器的时候,我们必须首先允许IIC总线通信。

  • PCF8591.py库文件就是PCF8591模块的程序,单独编写是为了便于重用。在此py文件使用了一个放大器用于模拟输入和一个LED灯用于模拟输出,模拟输入不能超过3.3V
     该程序也可以单独运行,用于测试3个电阻模块的功能。需用短路帽连接AIN0和INPUT0(电位计模块),连接AIN1和INPUT1(光敏电阻模块),以及连接AIN2和INPUT2(热敏电阻模块)。
     连接LED灯,AIN0(模拟输入0)端口用于接收来自电位计模块的模拟信号,AOUT(模拟输出)用于将模拟信号输出到双色LED模块,以便改变LED的亮度。

  • PCF8591.py文件参考:

#!/usr/bin/env python
#------------------------------------------------------
#
#       可以使用下面语句将此脚本导入另一个脚本:
#           “import PCF8591 as ADC”                
#   
#   ADC.Setup(Address)  # 查询PCF8591的地址:“sudo i2cdetect -y 1”
# i2cdetect  is  a  userspace  program to scan an I2C bus for devices.
# It outputs a table with the list of detected devices on the specified bus.
#   ADC.read(channal)   # Channal范围从0到3 
#   ADC.write(Value)    # Value范围从0到255
#
#------------------------------------------------------
#SMBus (System Management Bus,系统管理总线) 
import smbus   #在程序中导入“smbus”模块
import time

# for RPI version 1, use "bus = smbus.SMBus(1)"
# 0 代表 /dev/i2c-0, 1 代表 /dev/i2c-1 ,具体看使用的树莓派那个I2C来决定
bus = smbus.SMBus(1)         #创建一个smbus实例

#在树莓派上查询PCF8591的地址:“sudo i2cdetect -y 1”
def setup(Addr):
    global address
    address = Addr

def read(chn): #channel
    if chn == 0:
        bus.write_byte(address,0x40)   #发送一个控制字节到设备
    if chn == 1:
        bus.write_byte(address,0x41)
    if chn == 2:
        bus.write_byte(address,0x42)
    if chn == 3:
        bus.write_byte(address,0x43)
    bus.read_byte(address)         # 从设备读取单个字节,而不指定设备寄存器。
    return bus.read_byte(address)  #返回某通道输入的模拟值A/D转换后的数字值

def write(val):
    temp = val  # 将字符串值移动到temp
    temp = int(temp) # 将字符串改为整数类型
    # print temp to see on terminal else comment out
    bus.write_byte_data(address, 0x40, temp) 
    #写入字节数据,将数字值转化成模拟值从AOUT输出

if __name__ == "__main__":
    setup(0x48) 
 #在树莓派终端上使用命令“sudo i2cdetect -y 1”,查询出PCF8591的地址为0x48
    while True:
        print '电位计   AIN0 = ', read(0)   #电位计模拟信号转化的数字值
        print '光敏电阻 AIN1 = ', read(1)   #光敏电阻模拟信号转化的数字
        print '热敏电阻 AIN2 = ', read(2)   #热敏电阻模拟信号转化的数字值
        tmp = read(0)
        tmp = tmp*(255-125)/255+125 
# 125以下LED不会亮,所以将“0-255”转换为“125-255”,调节亮度时灯不会熄灭
        write(tmp)
        time.sleep(2)

编写控制程序

编写控制程序。通过点烟的方式产生可燃性气体靠近MQ-2气体传感器的位置。屏幕上将显示0到255之间的值。如果有害气体达到一定浓度,蜂鸣器会发出断续蜂鸣声,并且屏幕上会印有“Danger Gas”。
 你可以转动模块上电位器的轴来提高或降低浓度阈值。
 MQ-2气体传感器需要加热一段时间。等到屏幕上打印的值保持稳定并且传感器变热,这意味着它可以正常且敏感的工作。(气体传感器发热是正常的,实际上,温度越高传感器就越敏感。)

主程序:

#!/usr/bin/env python
import PCF8591 as ADC
import RPi.GPIO as GPIO
import time
import math

DO = 17
Buzz = 18
GPIO.setmode(GPIO.BCM)

def setup():
    ADC.setup(0x48)
    GPIO.setup  (DO,    GPIO.IN)
    GPIO.setup  (Buzz,  GPIO.OUT)
    GPIO.output (Buzz,  1)  #高电平不响,低电平触发报警蜂鸣

def Print(x):
    if x == 1:
        print ''
        print '   *********'
        print '   * Safe~ *'
        print '   *********'
        print ''
    if x == 0:
        print ''
        print '   ***************'
        print '   * Danger Gas! *'
        print '   ***************'
        print ''

def loop():
    status = 1
    count = 0
    while True:
        print 'ADC.read(0)==' , ADC.read(0)  #有烟雾时,该值增大
        
        tmp = GPIO.input(DO);
        print 'tmp==' ,tmp    
#无烟雾时为高电平,tmp=1,打印safe,有烟雾时为低电平,打印Danger Gas!
        if tmp != status:
            Print(tmp)
            status = tmp
        if status == 0:
            count += 1
            if count % 2 == 0:
                GPIO.output(Buzz, 0)  #检测到烟雾后,报警声为断续蜂鸣声,低电平为响
            else:
                GPIO.output(Buzz, 1)  #高电平不响
        else:
            GPIO.output(Buzz, 1)
            count = 0
                
        time.sleep(0.2)

def destroy():
    GPIO.output(Buzz, 1)
    GPIO.cleanup()

if __name__ == '__main__':
    try:
        setup()
        loop()
    except KeyboardInterrupt: 
        destroy()


PCF8591模数转换器

PCF8591原理图

实物图:

右边JP1, 5对接口:

  • AOUT 芯片DA输出接口
     AINO 芯片模拟输入接口0
     AIN1 芯片模拟输入接口1
     AIN2 芯片模拟输入接口2
     AIN3 芯片模拟输入接口3
    右排是:
     GND 接地
     GND 接地
     INPUT2 热敏电阻接口
     INPUT1 光敏电阻接口
     INPUT0 电位计接口
    左边J1, 4个接口:
     SCL IIC时钟接口 接树莓派的scl口(接树莓派 I2C1 SCL口)
     SDA IIC数字接口 接树莓派的sda口(接单树莓派 I2C1 SDA口)
     GND 模块地 外接地(接树莓派GND)
     VCC 电源接口 外接3.3v-5v (接树莓派电源)
    这里用的是5V。

对应的端口分别作用如下:
INPUT0端口 用短路帽接上AIN0,选择0-5V可调电压接入电路

INPUT1端口 用短路帽接上AIN1,选择光敏电阻接入电路

INPUT2端口 用短路帽接上AIN2,选择热敏电阻接入电路

  • AIN0~AIN3:模拟信号输入端。

    A0~A3:引脚地址端。

    VDD、VSS:电源端(2.5~6V)

    SDA、SCL:I2C总线的数据线、时钟线。

    OSC:外部时钟输入端,内部时钟输出端。

    EXT:内部、外部时钟选择线,使用内部时钟时EXT接地。

    AGND:模拟信号地。

    AOUT:D/A转换输出端。

    VREF:基准电源端。

  • AD的位数:表明这个AD共有2n个刻度,8位AD,输出的刻度是0~255. 8591就是8为精度的,因此它digtalRead的数据在0-255之间。
    分辨率:就是AD能够分辨的最小的模拟量变化,假设5.10V的系统用8位的AD采样,那么它能分辨的最小电压就是5.10/255=0.02V。

  • AD转换的原理简单来理解就是通过电路将非电信号转为电信号,然后通过一个基准电压(PCF8591的基准电压是5V),然后判断这个电信号的电压高低,然后得到一个0-255(8位精度)的比值。