zoukankan      html  css  js  c++  java
  • OneNET麒麟座应用开发之十:空气质量数据监测站项目总结

    大气质量数据监测站用于测试空气质量监测及数据采集,实现野外或者室内空气质量的检测。

    1、项目概述

    本项目是一个定制项目,要求采集大气的压力、温度、湿度、PM25、位置等数据并上传到指定的后台服务器。但有时候因为没有条件或因为各种原因不能联网,则采用本地保存的方式,本地保存我们决定使用SD卡来实现。除此外,为了实现显式需求,还需要配套一些东西来实现饮食的需求,如实时时钟记录,上传联网方式的选择等。

    2、硬件设计

    本项目涉及到的硬件并不复杂,我们对其中几个实用比较多的电路做一个说明。首先说一下串口通讯电路,在本项目中激光PM25传感器、气体质量流量控制器、SD读卡器等都是使用串口来实现通讯,所以我们采用如下的串口电路设计:

    该方式即可支持RS232,也可实现RS485,当然简单的TTL也没问题,只需要根据自己的不同需求焊接不同的元器件就可实现。

    接下来我们说一说PWM控制电路,其实用的是计时器来实现,由于点击需要12V-24V的电源,所以我们外加一部分电路来实现电机的驱动,而PWM信号则有MCU产生,并能够通过电路提升电压。

     

    最后我们说一下联网部分,联网有多种方式,有线连接、wifi连接都支持,首先说一说wifi,我们使用了ESP8266来实现这一需求,之所以选择ESP8266是因为软硬件实现都比较简单,而且我们对通讯的要求并不十分高,因为10m秒钟记录一个数据就好了,所以成本就是主要理由了。

     

    至于有线我们使用W5500来实现,在以前的文章中已经多次说明过,这一次就不再重复了。

    3、软件设计

    接下来我们说一说软件的设计,软件的设计较硬件要繁杂的多,我们选取其中一部分前面没有说明过的做一些说明。首先我们说一下PWM控制,每台采集站有2路进气,所以我们需要控制两个气泵,以及2路的PWM,每路可以单独控制,在试验时我们使用50%的占空比。

    void PWM_Configuration(void)
    {
      //计算初始化的频率和占空比
      TimerPeriod = PWMTimePeriod;//计算用于设置ARR寄存器的值使产生信号的频率为17.57 Khz
    
      PWM1Pulse = (uint16_t) (((uint32_t) 5 * (TimerPeriod - 1)) / 10);//计算CCR1寄存器的值在通道1和1N产生50%占空比,用于TIM1
    
      PWM2Pulse = (uint16_t) (((uint32_t) 5 * (TimerPeriod - 1)) / 10);//计算CCR1寄存器的值在通道1和1N产生50%占空比,用于TIM8
    
      PWM_InitProcess(TIM1,TimerPeriod,PWM1Pulse);
    }

          其次我们说以说I2C控制,有好几路传感器都使用的是I2C数据通讯来实现,我们在这里我们只说两个基本的I2C操作函数,一个是下发命令,一个是读取数据。所有的操作都刻以通过调用这两个函数来实现。

    /*向I2C从站下发指令,指令格式均为1个字节*/
    void SendCommandToI2CSlave(I2C_TypeDef* I2Cx,uint8_t deviceAddress,uint8_t command)
    {
      uint16_t i2cTimeout=TimeoutPeriod;
    
      /*产生I2C起始信号*/
      I2C_GenerateSTART(I2C2, ENABLE);
    
      /*检测 EV5 事件并清除标志*/
      while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
      {
        if ((i2cTimeout--) == 0) return ;
      }
    
      /*发送I2C从站的地址*/
      I2C_Send7bitAddress(I2Cx,deviceAddress,I2C_Direction_Transmitter);
    
      i2cTimeout=TimeoutPeriod;
    
      /*检测 EV6 事件并清除标志*/
      while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
      {
        if ((i2cTimeout--) == 0) return ;
      }
    
      /*下发操作命令*/
      I2C_SendData(I2Cx, command);
      i2cTimeout=TimeoutPeriod;
    
      /*检测 EV8 事件并清除标志*/
      while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
      {
    
        if ((i2cTimeout--) == 0) return ;
    
      }
    
      /* 产生I2C停止信号 */
      I2C_GenerateSTOP(I2Cx, ENABLE);
    }
    
     /*从I2C从站读取多个字节数据的值*/
    void GetBytesFromI2CSlave(I2C_TypeDef* I2Cx,uint8_t deviceAddress,uint8_t *pData,uint16_t bytesNum)
    {
      uint16_t i2cTimeout=TimeoutPeriod;
      /*如果I2C总线忙,则等待一段时间*/
      while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY))
      {
        if ((i2cTimeout--) == 0) return ;
      }
    
      /* 产生 I2C 起始信号 */
      I2C_GenerateSTART(I2Cx, ENABLE);
    
      /*检测 EV5 事件并清除标志*/
      while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
      {
        if ((i2cTimeout--) == 0) return ;
      }
    
      /*发送I2C从站的地址*/
      I2C_Send7bitAddress(I2Cx,deviceAddress+1,I2C_Direction_Receiver);
      i2cTimeout=TimeoutPeriod;
    
      /*检测 EV6 事件并清除标志*/
      while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
      {
    
        if ((i2cTimeout--) == 0) return ;
    
      }
    
      while(bytesNum)
      {
        if(bytesNum==1)
        {
          I2C_AcknowledgeConfig(I2Cx, DISABLE);//关闭应答
          I2C_GenerateSTOP(I2Cx, ENABLE);//停止信号
        }
        i2cTimeout=TimeoutPeriod;
        /*检测 EV7 事件并清除标志*/
        while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED))
        {
    
          if ((i2cTimeout--) == 0) return ;
    
        }
    
        /*通过 I2C,从设备中读取一个字节的数据 */
        *pData=I2C_ReceiveData(I2Cx);
    
        pData++;
    
        bytesNum--;
      }
    
      /*使能应答,方便下一次 I2C 传输*/
      I2C_AcknowledgeConfig(I2Cx, ENABLE);
    }

    接下来我们看看将数据存储到本地SD卡的操作过程,数据保留2位小数,并且采用4舍5入处理。

    //将数据写入到SD卡
    void WriteDataToSDCard(void)
    {
      //将数据写入SD卡
      saveData[0]=((int16_t)(tempProcessValue*100+0.5))/100.0;//温度测量值
      saveData[1]=((int16_t)(presProcessValue*100+0.5))/100.0;//压力测量值
      saveData[2]=((int16_t)(flowProcessValue1*100+0.5))/100.0;//流量计1的标况流量
      saveData[3]=flowTatolVolume1;//流量计1的工况累计流量
      saveData[4]=flowStdTatolVolume1;//流量计1的标况累计流量
      saveData[5]=((int16_t)(flowProcessValue2*100+0.5))/100.0;//流量计2的标况流量
      saveData[6]=flowTatolVolume2;//流量计2的工况累计流量
      saveData[7]=flowStdTatolVolume2;//流量计2的标况累计流量
         
    
      saveDate[0]=systemYear;
      saveDate[1]=systemMonth;
      saveDate[2]=systemDate;
      saveDate[3]=systemHour;
      saveDate[4]=systemMinute;
      saveDate[5]=systemSecond;    
    
      SDCardFileOperation();
    }

    4、结果展示

    我们在OneNET上创建了一个产品,6台设备,以及4个应用,来验证方案的效果,在测试过程中我们使用了Wifi方式来进行此次测试,因为这也是我们正是产品主要使用的连网方式。我们看一看数据上传的趋势图:

     

    接下来我们看看显示位置及温湿度的应用截图:

     

    我们再来看看显示大气压、温度和湿度的截图:

     

    我们再来看看气体流量及柱状图显示:

     

    至此,我们的测试项目完成,再次感谢电子发烧友和中国移动OneNET给我们带来的完美体验。

  • 相关阅读:
    PAT甲级——A1113 Integer Set Partition
    PAT甲级——A1112 Stucked Keyboard【20】
    PAT甲级——A1111 Online Map【30】
    左神算法书籍《程序员代码面试指南》——2_12将搜索二叉树转换成双向链表【★★】
    PAT甲级——A1110 Complete Binary Tree【25】
    PAT甲级——A1109 Group Photo【25】
    PAT甲级——A1108 Finding Average【20】
    左神算法书籍《程序员代码面试指南》——2_12将搜索二叉树转换成双向链表
    PAT甲级——A1107 Social Clusters
    shiro 框架
  • 原文地址:https://www.cnblogs.com/foxclever/p/7003544.html
Copyright © 2011-2022 走看看