zoukankan      html  css  js  c++  java
  • 快速实现一个室内空气质量检测仪

      冬天我们大多会关闭门窗,而依靠暖通空调设备来维持室内温度。而在保证居室温度的同时,我们也希望保持居室内大气环境的健康度。鉴于此,我们设计了一个简单的室内空气质量检测器。

    1、系统概述

      我们依靠暖通空调设备来维持室内温度、湿度和通风水平,以保证居住者的健康和舒适。所以我们希望设计一个小巧的、简单的、低成本室内空气质量检测器来随时监测我们居室内的空气质量。

      一般来说,我们关心的居室环境的温度、湿度、可吸入颗粒物浓度、挥发性有机物的浓度等。当然还有二氧化炭浓度等其它一些参数,不过这次我们只考虑温度、湿度、可吸入颗粒物浓度、挥发性有机物的浓度。

      对于这个室内空气检测器,我们的基本想法是设计一个可以快速成型、监测温度、湿度、可吸入颗粒物浓度、挥发性有机物浓度的手持设备。这台室内空气质量检测器温湿度、可吸入颗粒物浓度、挥发性有机物浓度并可以实时显示出来,并可以将检测出的数据向外传送。

    2、硬件设计

      根据前面的描述,我们使用一个温湿度传感器来监测温度和湿度、一个可吸入颗粒物激光检测传感器来检测可吸入颗粒物浓度,一个VOC传感器来检测挥发性有机物浓度。

      为了快速实现一个室内空气质量检测器,我们采用我们所熟知的传感器及其他相应设备来实现。我们使用SHT20来实现温湿度数据的检测;使用SGP40来检测VOC浓度;使用HLPM025K3激光PM2.5传感器来检测可吸入颗粒物浓度;使用OLED来显示数据;使用串口来实现数据的传送。而处理器我们采用STM32F103C8T6来实现。

      HLPM025K3激光PM2.5传感器数据接口为TTL串行口,所以我们采用USART1端口来与之通讯。SHT20传感器的数据接口为I2C接口,我们使用I2C1来与之通讯。SGP40传感器数据接口为I2C接口,我们使用I2C2来与之通讯。显示屏我们采用了SPI接口的0.96寸OLED,所以我们使用SPI1端口来与之通讯。数据传输我们采用USART2端口来实现。所以我们设计室内空气质量检测器的组成结构图如下:

      根据上述分析及结构示意图,我们就能很容易的设计出室内空气质量检测器的控制板。

    3、软件实现

      我们已经描述了室内空气质量检测器的控制板及各部分组件,接下来我们需要实现相应的软件功能。

    3.1、数据采集

      数据的采集主要包括三个方面:一是使用SHT20采集温湿度数据;二是使用SGP40来采集VOC浓度数据;三是使用HLPM025K3激光PM2.5传感器来检测可吸入颗粒物浓度数据。这些数据的采集并不麻烦,在以前的文章中我们已经简述多这些设备的驱动程序的设计。在这里我们直接使用已经封装过的驱动程序来实现就可以了。

      HLPM025K3激光PM2.5传感器通过串口输出数据,包括PM2.5和PM10的数据,我们使用封装的驱动程序可以很方便的获取和解析对应的数据。具体的实现程序如下:

    HlpmObjectType hlpm; //声明对象
    
    /*PM25数据采集处理*/
    void Ampm25DataProcess(void)
    {
      /*解析PM2.5和PM10的数据*/
      ParsingPMData(&hlpm);
      
      aPara.phyPara.pm10Value=hlpm.pm100;
      aPara.phyPara.pm25Value=hlpm.pm25;
    }
     
    /*PM25数据采集配置*/
    void Ampm25Configuration(void)
    {
      /* PM25相关GPIO初始化配置 */
      Ampm25_GPIO_Initialization();
      
      /* USART1端口初始化配置 */
      USART1_Init_Configuration();
      
      /*允许数据发送*/
      AMPM25_RUNNING_ENABLE();
      
      /*HLPM对象初始化函数*/
      HlpmInitialization(&hlpm);
    }
    

      需要注意的是HLPM025K3激光PM2.5传感器有一个测量控制信号,必须提供高电平才会工作。

      同样测量其它的参数也是使用我们封装的驱动程序,如使用SHT20温湿度传感器获取温湿度数据也是一样的。

    /* 温湿度数据处理 */
    void AmShtDataProcess(void)
    {
      aPara.phyPara.temperature=GetSHT2xTemperatureValue(&sht,MEASURE_T_COMMAND_NOHOST);
      aPara.phyPara.humidity=GetSHT2xHumidityValue(&sht,MEASURE_RH_COMMAND_NOHOST);
    }
     
    /* 温湿度配置 */
    void AmShtConfiguration(void)
    {
      /* I2C1端口初始化 */
      I2C1_Init_Configuration();
      
      /* 初始化配置SHT2x */
      SHT2xInitialization(&sht,        //SHT2X对象变量
                 SHT2x_DPI_RH8_T12, //测量分辨率配置
                 SHT2x_End_High,   //电池结束状态配置
                 SHT2xHEATERDISABLE, //加热器是否启用配置
                 SHT2xOTPDISABLE,  //是否加载OTP配置
                 WriteToSHT2x,    //写操作指针
                 ReadFromSHT2x,   //读操作指针
                 HAL_Delay);     //毫秒延时指针
    }
    

    3.2、数据显示

      前述我们已经提到了使用0.96寸的OLED来显示相应的数据。我们选用的是SPI接口的OLED显示屏。其实0.96寸的OLED驱动程序我们也是封装过的,直接使用就好。具体实现代码如下:

    OledObjectType oled;  //声明OLED对象
    
    /*OLED显示处理*/
    void AmoledDisplayProcess(void)
    {
      char temp[]="temp=%.2f";
      char humi[]="humi=%.2f";
      char pm25[]="PM2.5=%.2f";
      char pm10[]="PM10=%.2f";
      
      OledShowString(&oled,OLED_FONT_8x16,0,0,temp,aPara.phyPara.temperature);
      OledShowString(&oled,OLED_FONT_8x16,2,0,humi,aPara.phyPara.humidity);
      OledShowString(&oled,OLED_FONT_8x16,4,0,pm25,aPara.phyPara.pm25Value);
      OledShowString(&oled,OLED_FONT_8x16,6,0,pm10,aPara.phyPara.pm10Value);
      
    }
     
    /*OLED初始化配置*/
    void AmoledConfiguration(void)
    {
      /* OLED显示控制相关GPIO初始化配置 */
      Amoled_GPIO_Initialization();
     
      /* SPI1端口初始化 */
      SPI1_Init_Configuration();
     
      /*OLED显示屏对象初始化*/
      OledInitialization(&oled,      //OLED对象
                 OLED_SPI,       //通讯端口
                 0xFF,        //I2C设备地址
                 AmOledWrite,        //写数据函数
                 AmOledChipReset,       //复位信号操作函数指针
                 AmOledDCSelcet,        //DC信号控制函数指针
                 NULL,       //SPI片选信号函数指针
                 HAL_Delay       //毫秒延时函数指针
                   );
    }
    

    3.3****、数据传送

      数据的传输我们使用RS485的接口方式,应用层协议采用Modbus RTU协议。因为我们已经封装过Modbus协议栈,并且已经开源到GitHub,所以我们直接使用Modbus协议栈来实现我们的数据传送。

    /* 上位通讯处理函数 */
    void AmUpperCommunication(void)
    {
      uint16_t respondLength=0;
      if(amupcRxLength>=8)
      {
         uint8_t respondBytes[AMUPCRECEIVELENGTH];
    
          respondLength=ParsingMasterAccessCommand(amupcRxBuffer,respondBytes,amupcRxLength,aPara.phyPara.activeAddress);
         if(respondLength!=65535)
         {
           if(respondLength > 0)
           {
              AmupcSendByte(respondBytes,respondLength);
           }
           
           amupcRxLength=0;
         }
      }
    }
    

      关于数据传送这块,我们使用串口接收中断来接收数据请求。当然也可以直接使用定期上传的方式发送数据,则根据实际需求修改。

    4、验证测试

      我们已经设计了室内空气质量检测器的软件和硬件,接下来我们运行看看其结果如何。我们将其运行起来,在我们的OLED软件中设置为一次能显示4行数据,具体结果如下图:

      这只是一个小制作,实现了一些简单的功能。在后续我们实际上可以将其功能扩展的更多。如将数据上传到网络实时查看居室内的大气环境;根据PM2.5的情况控制空气净化器的工作等。

    欢迎关注:

    如果阅读这篇文章让您略有所得,还请点击下方的【好文要顶】按钮。

    当然,如果您想及时了解我的博客更新,不妨点击下方的【关注我】按钮。

    如果您希望更方便且及时的阅读相关文章,也可以扫描上方二维码关注我的微信公众号【木南创智

  • 相关阅读:
    我的第一颗二叉链树的笔记
    我的kmp笔记
    链表操作笔记
    POJ 2559 Largest Rectangle in a Histogram (单调栈)
    牛客网 wyh的数列(循环节+快速幂)
    数论知识点
    牛客网 n的约数 (唯一分解定理)
    POJ 3783 Balls (DP)
    关于unordered_map和map
    2018年四校联合周赛-第二场 B.异或和问题(二维树状数组)
  • 原文地址:https://www.cnblogs.com/foxclever/p/15676811.html
Copyright © 2011-2022 走看看