基于树莓派RP2040设计的简易烟雾报警
wedesign第二期活动,使用RP2040调试ADPD188BI烟雾传感器。
标签
RP2040
WeDesign1
adpd188bi
烟雾传感器
岁月静好 山河无恙
更新2023-06-29
1710

一、背景

      之前做Fastbond活动时顺手买了一块ADI烟雾报警器芯片ADPD188BI,一直闲置,正好借这个机会测试一下这块芯片。

      ADPD188BI 是一种采用光学双波长技术的完备的光电式烟雾检测系统。该模块集成高效率的光电式测量前端、蓝光和红外 (IR) 发光二极管 (LEDs) 以及光电二极管 (PD)。可以有效判别干扰源,减少误报率,并且双波长在一定程度上具有分辨不同烟雾的能力。

   活动已给定主控芯片为RP2040,硬件绘图工具为Kicad,软件开发平台使用官方推荐的thonny。

二、硬件设计过程

   1.先梳理一下需求:

      (1).板卡使用usb或者电池供电;

      (2).能够检查环境温湿度;

      (3).具有报警器件;

      (4).需搭配一块显示屏实时显示传感器信息;

      绘制硬件框图如下:

FknYlfEYXPvncgmnCLrWZXW-7Is6

   2.确定关键器件:

         主控:RP2040
         烟雾报警芯片:ADPD188BI
         电平转换芯片:TXB0108(IIC通讯需换成TXS0108EPWR)
         温湿度传感器:ENS210
         屏幕显示:0.96寸TFT 240*240彩屏
         充电芯片:LTC4054
         USB转串口:CH340E
   3.搜集资料:
         电源电压:
         查阅芯片数据手册确定关键器件所需工作电压:
         (1).rp2040: 3.3V
FksZnRKMBklxc_zoiz_ehW9IVdHX
         (2).ADPD188BI:1.8V,6V,3.3V
      FsGAN3tI38Z0im-aKhHisqDJbZgK
 
         (3).ENS210: 3.3V
FiQsw_SW5MaCvHDXwJtrGh-nNEhu
         
         (4).0.96寸TFT彩屏:
   Fvo1VEXvKzhJoqxHybBXIbNDqvP8
 
 
 
   4.原理图:   
      使用kicad绘制原理图如下:
FrPqjZPhRs3WTplPn7mwFE6cYtkF
      绘制PCB如下:
FlLF44-0fEye5ZCS3pzVt7jCjrKC
      第一次使用kicad画图,不太熟悉,画画停停,遇到几个小问题。
      问题(1):原理图选择封装的时候没有仔细检查,搞错了几个器件的封装,三极管没一个对的上的,解锁三极管焊接新姿势。0.96寸的显示屏座子封装选大了一号,只能飞线解决。
   
Fo4m01gL3O-crZQfU4z-IeNYfsU-FlPttk18uqyaE0yk_Fv8PJ4fBW_z
      问题(2):在调试ADPD188BI传感器的时候IIC通讯不成功,首先怀疑芯片没焊接好,毕竟LGA的封装也看不到引脚,拆焊了3次没解决。然后怀疑电平转换芯片买到假货了,查看TXB0108器件手册,翻到内部结构框图发现不适用于开漏通信。在ADI论坛搜了相关问题,确认该芯片不适用IIC,通讯。改用TXS0108EPWR后IIC通讯成功。
FoOITwb2AUnjHpuoll-VQW7t16Qk
      问题(3):调试烟雾传感器时,接收到的数据一直在无规律的跳。对比论坛示例代码中寄存器初始化数值,多次调整相关寄存器,接收到得结果还是跳一直没解决。盯着一闪一闪的绿光,就要放弃了,突然反应过来这个传感器没有绿色LED啊。赶紧回去翻看得捷电子购买记录,发现果然是传感器买错了,之前买的竟然是环境光传感器ADPD188GG,ADPD188GG和ADPD188BI封装一致,内部结构一致,只是封装得LED颜色不一样。购买正确型号传感器替换后,数据稳定了。
FjStBnPwgG7KuHobx0zSK3iWbLh4
 
 
三、代码设计
      1.TFT_096代码部分
      显示屏的驱动是ST7735,本设计借鉴微雪官网的示例代码,注意初始化的时候颜色和坐标翻转,以下是屏幕初始化部分:
 
def Init(self):
        self.reset() 
        self.backlight(10000)  
        
        self.write_cmd(0x11)
        time.sleep(0.12)
        
        self.write_cmd(0xB1)
        self.write_data(0x05)
        self.write_data(0x3C)
        self.write_data(0x3C)
        self.write_cmd(0xB2)
        self.write_data(0x05)
        self.write_data(0x3C)
        self.write_data(0x3C)
        self.write_cmd(0xB3)
        self.write_data(0x05)
        self.write_data(0x3C)
        self.write_data(0x3C)
        self.write_data(0x05)
        self.write_data(0x3C)
        self.write_data(0x3C)
        self.write_cmd(0xB4)
        self.write_data(0x03)
        self.write_cmd(0xC0)
        self.write_data(0xAB)
        self.write_data(0x0B)
        self.write_data(0x04)
        self.write_cmd(0xC1)
        self.write_data(0xC5)
        self.write_cmd(0xC2)
        self.write_data(0x0D)
        self.write_data(0x00)
        self.write_cmd(0xC3)
        self.write_data(0x8D)
        self.write_data(0x6A)
        self.write_cmd(0xC4)
        self.write_data(0x8D)
        self.write_data(0xEE)
        self.write_cmd(0xC5)
        self.write_data(0x0F)
        
        self.write_cmd(0xE0)
        self.write_data(0x07)
        self.write_data(0x0E)
        self.write_data(0x08)
        self.write_data(0x07)
        self.write_data(0x10)
        self.write_data(0x07)
        self.write_data(0x02)
        self.write_data(0x07)
        self.write_data(0x09)
        self.write_data(0x0F)
        self.write_data(0x25)
        self.write_data(0x36)
        self.write_data(0x00)
        self.write_data(0x08)
        self.write_data(0x04)
        self.write_data(0x10)
        self.write_cmd(0xE1)
        self.write_data(0x0A)
        self.write_data(0x0D)
        self.write_data(0x08)
        self.write_data(0x07)
        self.write_data(0x0F)
        self.write_data(0x07)
        self.write_data(0x02)
        self.write_data(0x07)
        self.write_data(0x09)
        self.write_data(0x0F)
        self.write_data(0x25)
        self.write_data(0x35)
        self.write_data(0x00)
        self.write_data(0x09)
        self.write_data(0x04)
        self.write_data(0x10)
        
        self.write_cmd(0xFC)
        self.write_data(0x80)
        
        self.write_cmd(0x3A)
        self.write_data(0x05)
        self.write_cmd(0x36)
        self.write_data(0x78)
#         self.write_cmd(0x21)   #反色控制
        self.write_cmd(0x29)
        
        self.write_cmd(0x2A)
        self.write_data(0x00)
        self.write_data(0x00)
        self.write_data(0x00)
        self.write_data(0x50)
        
        self.write_cmd(0x2B)
        self.write_data(0x00)
        self.write_data(0x00)
        self.write_data(0x00)
        self.write_data(0x9f)
        self.write_cmd(0x2C)

2.ENS210驱动:

      温湿度传感器的器件地址是0X43,按照数据手册介绍,只需要王0x22寄存器写入0x03,即可读取温湿度数据;温湿度数据存储在0X30中。温度摄氏度计算公式为:code/64-273.15; 湿度计算公式为:code/512; 关键代码如下:

def temp_hum(temp_hum_arr):
        i2c1.writeto_mem(67, 34, b'3')
        temp_hum_arr=i2c1.readfrom_mem(67, 48, 6)
        ens210_val[0]=(temp_hum_arr[1]*256+temp_hum_arr[0])/64-273.15
        ens210_val[0]=round(ens210_val[0],1)
        
        ens210_val[1]=(temp_hum_arr[4]*256+temp_hum_arr[3])/512
        ens210_val[1]=round(ens210_val[1],1)
        time.sleep(0.2)

3.ADPD188BI烟雾传感器:

      ADI这款烟雾传感器设计的模式较多,此处借鉴了https://blog.csdn.net/m0_51294753/article/details/120872468相关代码,博主注释很详细,不做赘述;调整后寄存器初始化数据如下:

adpd_ini1=bytes((0x0F,0x00,0x01))          #  软件复位 寄存器清零
adpd_ini2=bytes((0x01,0xC0,0xFF))          #  FIFO中断配置 数据长度超出0x06位[13:8))时产生中断
adpd_ini3=bytes((0x02,0x00,0x05))          #  使能GPIO0引脚
adpd_ini4=bytes((0x06,0x00,0x01))          #  设置FIFO长度阈值
adpd_ini5=bytes((0x10,0x00,0x01))              #  进入编程模式
adpd_ini6=bytes((0x11,0x31,0xb9))          #  设置时隙A,B的FIFO数据格式      32  位和
adpd_ini7=bytes((0x4F,0x20,0x90))          #  样本同步选择和GPIO管脚设置
adpd_ini8=bytes((0x5F,0x00,0x00))          #  时钟设置
adpd_ini9=bytes((0x12,0x0a,0x50))          #  设置采样频率为50Hz fSAMPLE=bytes((2KHz/((0x12[15:0))*4))
adpd_ini10=bytes((0x15,0x01,0x20))          #  时隙A,B样本和/均值系数为4,抽取
adpd_ini11=bytes((0x14,0x01,0x1d))          #  时隙A,B双脉冲配置
adpd_ini12=bytes((0x18,0x00,0x00))          #  时隙A通道1 ADC失调
adpd_ini13=bytes((0x19,0x3F,0xFF))          #  时隙A通道2 ADC失调
adpd_ini14=bytes((0x1A,0x3F,0xFF))          #  时隙A通道3 ADC失调
adpd_ini15=bytes((0x1B,0x3F,0xFF))          #  时隙A通道4 ADC失调
adpd_ini16=bytes((0x30,0x03,0x20))          #  时隙A 3us LED pulse
adpd_ini17=bytes((0x31,0x04,0x0E))          #  时隙A 4 pulses
adpd_ini18=bytes((0x39,0x22,0xF0))          #  时隙A 4us AFE
adpd_ini19=bytes((0x42,0x1C,0x34))          #  AFE配置 配置为1的缓冲器,正常积分器配置 1.27V 200KΩ
adpd_ini20=bytes((0x43,0xAD,0xA5))          #  模拟全路径模式
adpd_ini21=bytes((0x5E,0x08,0x08))          #  时隙A禁用悬空
adpd_ini22=bytes((0x16,0x30,0x00))          #  No Dark Bits
adpd_ini23=bytes((0x17,0x00,0x09))          #  Chop -++-
adpd_ini24=bytes((0x1E,0x00,0x00))          #  时隙B通道1 ADC失调
adpd_ini25=bytes((0x1F,0x3F,0xFF))          #  时隙B通道2 ADC失调
adpd_ini26=bytes((0x20,0x3F,0xFF))          #  时隙B通道3 ADC失调
adpd_ini27=bytes((0x21,0x3F,0xFF))          #  时隙B通道3 ADC失调
adpd_ini28=bytes((0x35,0x03,0x20))          #  时隙B 3us LED pulse
adpd_ini29=bytes((0x36,0x04,0x0E))          #  时隙B 4 pulses
adpd_ini30=bytes((0x3B,0x22,0xF0))          #  时隙B 4us AFE
adpd_ini31=bytes((0x44,0x1C,0x34))          #  AFE配置 配置为1的缓冲器,正常积分器配置 1.27V 200KΩ
adpd_ini32=bytes((0x45,0xAD,0xA5))          #  模拟全路径模式
adpd_ini33=bytes((0x59,0x08,0x08))          #  时隙B禁用悬空
adpd_ini34=bytes((0x1C,0x30,0x00))          #  No Dark Bits
adpd_ini35=bytes((0x1D,0x00,0x09))          #  Chop -++-
adpd_ini36=bytes((0x58,0x05,0x44))          #  时隙A,B控制
adpd_ini37=bytes((0x22,0x35,0x36))          #  配置LEDx3驱动器  电流粗调 
adpd_ini38=bytes((0x23,0x35,0x36))          #  配置LEDx1驱动器  电流粗调
adpd_ini39=bytes((0x24,0x15,0x30))          #  配置LEDx2驱动器  电流粗调
adpd_ini40=bytes((0x25,0x63,0x0C))          #  配置LEDx驱动器   电流精调
adpd_ini41=bytes((0x34,0x00,0x00))          #  时隙A,B LED禁用
adpd_ini42=bytes((0x3C,0x31,0xC6))          #  通道开关
adpd_ini43=bytes((0x3D,0x00,0x00))           
adpd_ini44=bytes((0x54,0x0A,0xA0))          #  配置PD电压
adpd_ini45=bytes((0x55,0x00,0x00))          #  配置TIA增益
adpd_ini46=bytes((0x5A,0x00,0x10))          #  
adpd_ini47=bytes((0x4B,0x26,0xA2))          #  时钟时序设置
adpd_ini48=bytes((0x4C,0x00,0x04))          #
adpd_ini49=bytes((0x4D,0x00,0x90))          # 
adpd_ini50=bytes((0x10,0x00,0x02))          #   进入采样模式 
      烟雾传感器的接收到的亮度数值会存储在FIFO寄存器中,将读取的数值与初始化时LED的配置参数进行比较计算,分别计算出红光和蓝光的PTR值。在有烟雾的时候这个值会上升。
4.蜂鸣器报警
      借鉴示例代码呼吸灯部分:
      
 if ens210_sensor.ens210_val[1]>300:        #蜂鸣器报警
        duty = 0
        direction = 1
        for _ in range(8 * 256):
            duty += direction
            if duty > 255:
                duty = 255
                direction = -1
            elif duty < 0:
                duty = 0
                direction = 1
            beep_pwm.duty_u16(duty * duty)
            time.sleep(0.001)

四、实现过程

      该烟雾传感器为光电式,为了排除环境光的干扰,需要给它配一个烟室(一个四处漏风的罩子,但光照不进去)。在这里我用涂黑的酒精瓶的盖子代替,并在上面戳几个洞保证烟雾能够进入,测试室内开关灯时传感器数值基本不变,满足需求。

FvAXwo-Of3Lg3isD3lSFuBfF6FXa

      传感器数据调出来后就可以进行测试了。将板子丢进一个箱子,在里面点个火制造些烟雾。传感器接收到的光强度会随烟雾浓度的上升而上升,为系统设置一个阈值此处是300,一旦传感器数值超过该阈值即驱动蜂鸣器报警。

FvrnxUtlx4gGyk2Ztf2vtBA-LWfZ

      进一步测试发现:

      (1).纸火较木柴火更容易产生烟雾,烟雾浓度上升速度也就越快;

      (2).不同种类燃烧物产生的烟雾,红蓝光照强度数据上升过程有细微差别;

      (3).我为什么要搞烟雾传感器,房间里乌烟瘴气的.....

      最后实现了烟雾报警功能,种类识别未调试成功。

五、多余的考虑

      做项目前了解到,RP2040使用U盘模式下载程序。需要先按着按键再上电才能进入U盘模式,觉得很不方便。所以增加了一个模拟开关CH440E,EN引脚高电平的时候内部开关断开变为高阻状态,EN引脚低电平内部开关有效,开关回路由IN脚电平决定。这样我们可以在EN引脚接一路轻触开关拉高,开关按下抬起就相当于拔插一次USB。实际调试时才发现,只用在一开始时进入一次U盘模式烧录固件,之后不用进U盘模式。

六、芯片优势和局限

      就本项目而言,这块单片机性能完全满足需求,外围接口也丰富,够用。有麻烦的是QFN封装比较难焊接,需要配一块外部flash。

      优势:

         1.RP2040主频高133M,还是双核ARM Cortex-m0+内核,处理能力强;

         2.RP2040外围接口丰富,多路串口通讯满足大部分应用场景,另外PIO还可以模拟出多种硬件接口,非常方便;

    • 8080/6080 并行接口
    • I2C
    • I2S
    • SDIO
    • SPI/DSPI/QSPI
    • UART
    • DPI/VGA

         3. 具有低动态功耗以及多种低功耗模式。低额定功率为电池供电应用提供了灵活性,因此在移动应用中非常有用。

      局限性:

         1.RP2040芯片封装单一,没有其他选择;

         2.系统需要一块外部flash芯片,增加了项目成本;

七、附录

      参考资料如下:

      1.烟雾检测模块ADPD188BI介绍与应用:https://blog.csdn.net/m0_51294753/article/details/120872468

      2.校准ADPD188BI光学烟雾和气溶胶检测模块:https://www.elecfans.com/d/2016865.html

      3.ADPD188BI - PTR 比率:https://ez.analog.com/optical_sensing/f/q-a/566776/adpd188bi---ptr-ratio

附件下载
test_01.zip
图纸工程文件
wedesign_2 adpd188 .zip
thonny备份代码
团队介绍
长草的小破号
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号