查看: 11412|回复: 19

[项目] 基于Arduino的家居监控装置

[复制链接]
  • TA的每日心情
    无聊
    2017-11-12 21:03
  • 签到天数: 26 天

    [LV.4]偶尔看看III

    发表于 2017-9-10 17:34 | 显示全部楼层 |阅读模式
    本帖最后由 Mr.fan 于 2018-1-19 13:58 编辑

    项目介绍:这个项目主要是通过Arduino来实现一些简单的物联网智能家居控制,通过OneNET平台实现远程的查看室内温湿度、光照强度等各项传感器数据,也能远程遥控开关。另外也能够按照自己的设定根据传感器数据做出一些相应的反应,最后还添加了一些实用的功能例如:天气预报、防火防盗、日历时钟显示等等。这个项目还搭配了一块3.2英寸的彩色屏幕来显示各项数据,更改系统的一些设置,为了操作方便特意增加了远距离红外控制。
    所需硬件材料Arduino Mega 2560、ESP8266、串口语音模块、串口屏、DTH11传感器、MQ-2传感器、SR501传感器、火焰传感器、光敏传感器、红外发射模块、红外接收模块、DS3231时钟模块、继电器*2、红外遥控器、开关、杜邦线若干、锂电池、锂电池充电板、升压模块、内存卡。
    硬件连接图就不发了,代码中有注释。


    制作前的准备:开发平台ArduinoIDE,添加所需要的库文件,合成语音文件,制作屏幕固件并烧写,给ESP8266烧写AT固件,调整各传感器灵敏度。
    实物图
    20171016_220433.jpg
    详细介绍:主要包括,数据传输、屏幕显示、语音播报、设备控制、传感器数据读取,5个部分。下面将依次介绍
    1.数据传输部分主要是通过esp8266 WiFi模块连接网络获取和传输数据,WiFi模块需要烧写AT固件,通过串口发送AT命令来实现联网功能。数据传输部分又包括获取天气信息和连接OneNet平台进行数据交互,关于天气信息的获取可参考我以前的帖子  获取天气信息的详细步骤与OneNet平台的信息交互请先参考平台的开发文档这里只介绍一下是如何实现传输的。源码中的edp.c是平台的edp协议的打包程序,所有的数据都需要经过处理后才能被平台接收到。在使用网络的时候我们需要先检查模块是否正常工作,需要先调用WiFi.cpp中的doCmdOK ( )这个函数来检查WiFi模块是否正常,由esp8266在透传模式下不会接收AT命令,所以当我们发送AT的时候没有接收到正确的返回消息的时候需要发送+++来退出透传模式,这个新手需要注意一下。当我们连接WiFi成功后就可以连接OneNet平台了,这时候只需将我们的APIkey和设备ID打包发送过去等待相应即可,这个操作在ConnectToOnenet()中实现

    kittenblock中小学创客名师推荐的图形化编程软件

    bool WiFi_Class::ConnectToOnenet()
    {
      edp_pkt rcv_pkt;
      unsigned char pkt_type;
      int i, tmp;
      while (!doCmdOk("AT", "OK"));
      while (!doCmdOk("AT+CIPSTART=\"TCP\",\"183.230.40.39\",876", "CONNECT"));
      while (!doCmdOk("AT+CIPMODE=1", "OK"));           //透传模式
      while (!doCmdOk("AT+CIPSEND", ">"));              //开始发送
      edp_flag = 0;
      if (!edp_flag)
      {
        while (Serial1.available()) Serial1.read(); //清空串口接收缓存
        packetSend(packetConnect(ID, KEY));             //发送EPD连接包
        while (!Serial1.available());                 //等待EDP连接应答
        if ((tmp = Serial1.readBytes(rcv_pkt.data, sizeof(rcv_pkt.data))) > 0 )
        {
          rcvDebug(rcv_pkt.data, tmp);
          if (rcv_pkt.data[0] == 0x20 && rcv_pkt.data[2] == 0x00 && rcv_pkt.data[3] == 0x00)
          {
            edp_flag = 1;
            Serial.println("EDP connected.");
          }
          else
            Serial.println("EDP connect error.");
        }
        packetClear(&rcv_pkt);
      }
    }

    连接平台后我们就可以向平台发送我们的传感器数据了,这时候需要用到packetSend(packetDataSaveTrans(NULL, 数据流名称, 数据 ))这个函数来打包和发送数据,另外也可以借助平台自带的应用管理来将我们上传的数据以图表的形式显示出来如下图
    123.PNG
    同时也可以接收平台下发的数据来实现远程控制功能,需要说明的是在创建产品的时候最好使用EDP协议,因为MQTT协议下好像不能实现平台的下发功能。远程控制功能是通过WiFi.cpp下的Control()这个函数来实现的。
    数据传输部分就这么多了,更详细的请看源码,关键部分都有注释的。应用链接地址

    2.屏幕显示部分:通过串口发送指令来控制屏幕,总共分为7个页面

    主菜单界面                                                                  
    111.png   
    天气显示界面  
    112.png
    时钟显示界面                                                         
    222.png    
    数据显示界面
       333.png
    设置界面                                                               
    444.png      
    控制界面
    666.png
    键盘
    555.png
    其中天气显示界面最为麻烦,因为Arduino不方便发送中文字符,因此我们只能通过发送相应的字符,然后串口屏根据这些字符来判断和组合成中文语句。页面都是提前做好了的,我们只需要给每个控件发送需要显示的数据即可,当我们通过屏幕点击切换页面的时候,只会切换到相应的页面,但是原来的数据无法保存,因此每次切换页面之后我们需要重新发送一遍数据信息。

    kittenblock中小学创客名师推荐的图形化编程软件

    String dp = Serial3.readString();  //判断页面属性,刷新对应的页面
        Serial.println(dp);
        if (dp.indexOf("Weather") == 1)
          showWeather();//刷新显示
        if (dp.indexOf("Time") == 1)
          showTime();
        if (dp.indexOf("Tem") == 1)
          showTemHum();

    通过屏幕来控制继电器,当我们点击控制界面按钮的时候屏幕会通过串口来发送设置好的数值,接受到数据后再做出相应的动作

    kittenblock中小学创客名师推荐的图形化编程软件

    if (Serial3.available() > 0)
            {
              int Switch = Serial3.read();
              Serial.println(Switch);
              if (Switch == 10)
                Switch3.Control(9, 0);      //关灯
              if (Switch == 11)
                Switch3.Control(9, 1);      //开灯
              if (Switch == 20)
                Switch3.Control(10, 0);     //关闭
              if (Switch == 21)
                Switch3.Control(10, 1);     //打开
              if (Switch == 31)
                flag1 = 1;                   //打开离家模式
              if (Switch == 30)
              {
                flag1 = 0;                   //关闭离家模式
                flag2 = 1;
                flag3 = 1;
                flag4 = 0;
                Voice3.play(10, 5);
              }
              if (Switch > 50)
                break;
            }

    另外当我们一段时间没有操作的时候会自动切换到时间显示界面,最后需要说明的是由于某些原因目前WiFi设置和天气地址设置还不能通过屏幕的键盘来修改,依然得在源码中修改,时间也是这样的,以后会来完善这几个地方。
    3.语音播报:这 部分依然是同过串口发送指令控制语音模块播放相应的语音片段,当然语音文件需要我们提前使用软件合成好,存入SD卡中,整个项目大概有四五百条语音文件,绝大部分是天气播报的,语音播报的操作都是通过Voice.cpp来实现的,主要包括四个功能:1播放天气信息、2、室内温湿度播报、3语音报警、4调整音量。由于每次播放的语音都是几个片段合成的,为了避免一段语句未播放完就播放到下一条,需要将语音模块上的状态引脚连接至Arduino的13号引脚上,当13号引脚为高电平的时候才播放下一条。整个语音模块所用到的指令分别是  
    1:播放指定目录下的文件  0x7E, 0x04, 0x44, 文件夹号, 文件号, 0xEF   
    2:设置音量大小 0x7E, 0x03, 0x31, 音量值, 0xEF   音量大小介于0-30
    为了使操作简单点我们在合成语音文件的时候需要按照一定的规律来给文件命名,例如我们从网上获取的天气信息中的天气代码1表示晴,相应的语音文件就可以命名为1,同类的文件存放到统一的文件夹中,这样操作会简单很多。

    kittenblock中小学创客名师推荐的图形化编程软件

    unsigned int  buf[7]  = {0x7E, 0x04, 0x44, 0x01, 0x00, 0xEF};
    /*播放当前室内温湿度*/
    void Voice_Class::playTemHum()
    {
      if (tem < 0)
        buf[4] = (100 - tem);
      else
        buf[4] = tem;
      buf[3] = 0x01;
      if (digitalRead(13) == 1)
      {
        for (int i = 0 ; i < 7 ; i++)
          Serial2.write(buf);
      }
      buf[4] = hum;
      buf[3] = 0x02;
      if (digitalRead(13) == 1)
      {
        for (int i = 0 ; i < 7 ; i++)
          Serial2.write(buf);
      }
    }
    
    语音部分就说到这里了。

    4.设备控制:这里的控制主要包括四大部分:1网络控制、2屏幕控制、3红外遥控器控制、4自动控制。前面两种之前简单的说过了,现在就说一说如何通过红外遥控器控制设备,红外控制首先需要我们事先知道红外遥控器每个键发射的红外信号是多少,我们需要先使用IRremote库记录下每个键的键值,然后当我们的红外接收器接收到相应的红外信号后就执行设定好的操作。

    kittenblock中小学创客名师推荐的图形化编程软件

    int Infrared_Class::Control()
    {
      if (irrecv.decode(&results))
      {
        if (results.value == Key1 )  //继电器1打开
          Switch1.Control(9, 1);      
        if (results.value == Key2)        //继电器1关闭
          Switch1.Control(9, 0);
        if (results.value == Key3)        //切换到温湿度界面并播放语音
        {
          Voice1.playTemHum();
          Display1.showTemHum();
        }
        if (results.value == Key4)        //切换到天气界面并播放语音
        {
          Display1.showWeather();
          Voice1.playWeather();
        }
        if (results.value == Key5)        //设置离家模式
        {
          flag1 = 1;
        }
        if (results.value == Key6)        //取消离家模式
        {
          flag1 = 0;
          Voice1.play(10, 5);
          flag2 = 1;                      //重置,让下一次开启时播放提示语音
          flag3 = 1;
          flag4 = 0;
        }
        if (results.value == Key7)        //继电器2打开
          Switch1.Control(10, 1);
        if (results.value == Key8)        //继电器2关闭
          Switch1.Control(10, 0);
        
        if (results.value == UP)        //增加音量
          Voice1.VolumeUP();
        if (results.value == Reduce)//减小音量
          Voice1.VolumeReduce();
        Serial.println(results.value);
        irrecv.resume();                    // 接收下一次数值
      }
    }
    
    提醒一下火焰传感器是通过接收红外光线来判断前方是否有明火,而红外遥控器发射的红外信号也会被火焰传感器接收到,在安装的时候火焰传感器和红外接收头尽量间隔大一点,使用的时候也不要用红外遥控器直接对着火焰传感器使用。
    另外整个装置配有红外发射器,理论上是可以通过红外发射器发射红外信号来控制一些家用电器,但是我们首先得存入需要发送的红外信号值,由于功率的原因控制距离太短了,显得有些鸡肋,这里不再过多的介绍了,有兴趣的可以自己改进改进。

    目前装置能够根据传感器的数据做一些很简单的操作,例如光线过暗的时候会自动打开灯光,光线过强会自动关闭、检测到有明火或者有可燃气的时候也会有语音报警,最后添加了防盗的功能,设置离家模式后再次检测到有人进入的时候也会发出报警铃声,并且会通过OneNET平台的触发器来给用户发送邮件信息。

    kittenblock中小学创客名师推荐的图形化编程软件

    
    /*
       根据传感器检测数据自动调节一些设备或发出报警
    */
    void autoControl()
    {
      tem = Sensor.GET_TEM(), hum = Sensor.GET_HUM();
      if (Sensor.GET_MQ2() > 150)           //可燃气体浓度读取值大于100时,播放报警语音
      {
        Voice.play(10, 0);
        delay(100);
      }
      if (Sensor.GET_FIRE() == 0)           //检测有火焰时播放报警语音
      {
        Voice.play(10, 1);
        delay(100);
      }
      if (Sensor.GET_LIGHT() > 1000)        //光照强度读取值大于1000时自动打开灯光(光线越强读取的模拟值越小)
      {
        Switch.Control(9, 1);
        Voice.play(10, 2);
        delay(100);
      }
      if (Sensor.GET_LIGHT() < 750)         //光照强度读取值小于750时自动关闭灯光
      {
        Switch.Control(9, 0);
        Voice.play(10, 3);
        delay(100);
      }
    }

    5.传感器数据读取:用到的传感器都是很常见的,这部分好像没什么需要说明的了,那么整个项目就介绍到这里吧


    最后放上实物图:

    侧面图
    20170630_155939.jpg 20170630_155849.jpg

    正面图
    20170630_155705.jpg
    内部接线图
    20170630_160117.jpg
    最后说明一下,社区的附件只能小于1M,所以串口屏幕固件和语音文件将用百度云分享。屏幕固件和语音文件都是自己一点一点做出来的,使用的时候可能会有点局限性,喜欢折腾的也可以自己制作。
    https://github.com/FanMLei/SmartHome
    演示视频




















  • TA的每日心情
    无聊
    2017-11-12 21:03
  • 签到天数: 26 天

    [LV.4]偶尔看看III

     楼主| 发表于 2017-11-18 15:48 | 显示全部楼层
    纪念衫到了,可惜冬天穿不了!!!
    20171118_154504.jpg


  • TA的每日心情
    擦汗
    2019-1-26 16:31
  • 签到天数: 446 天

    [LV.9]以坛为家II

    发表于 2017-10-19 23:05 | 显示全部楼层
    1.感谢对社区比赛的支持,演示视频开头需要添加大赛宣传海报,请补充完整。具体要求请参考:
    http://www.arduino.cn/thread-47517-1-1.html
    2.开发者积分和贡献值已发放,请点击以下链接领取纪念衫并参与抽奖~
    http://www.arduino.cn/thread-48132-1-1.html
    3.比赛结果会在11.15号前公布,请耐心等待。
    PY让世界更美好~

    该用户从未签到

    发表于 2018-1-17 18:15 | 显示全部楼层
    请问“基于Arduino的家居监控装置 ”开源吗?有学生的科技创新课需求, 盼回复!
    18923777208  方先生   csppkcs11@163.com
  • TA的每日心情
    无聊
    2017-11-12 21:03
  • 签到天数: 26 天

    [LV.4]偶尔看看III

     楼主| 发表于 2018-1-19 13:56 | 显示全部楼层
    csppkcs11 发表于 2018-1-17 18:15
    请问“基于Arduino的家居监控装置 ”开源吗?有学生的科技创新课需求, 盼回复!
    18923777208  方先生    ...

    本来就是开源的,不好意思啊从百度云迁到Github上了忘记更新地址了,你再看下链接
  • TA的每日心情
    开心
    2018-10-30 09:52
  • 签到天数: 81 天

    [LV.6]常住居民II

    发表于 2018-1-23 12:13 | 显示全部楼层
    很有学习价值。

    该用户从未签到

    发表于 2018-2-23 13:03 | 显示全部楼层
    大佬,那个屏幕是四线串口屏吗,还是tft触摸屏
  • TA的每日心情
    慵懒
    2019-7-15 09:44
  • 签到天数: 288 天

    [LV.8]以坛为家I

    发表于 2018-2-23 16:49 | 显示全部楼层
    感兴趣,开学抽空学习一下
    大家的支持是我无限的动力
  • TA的每日心情
    无聊
    2017-11-12 21:03
  • 签到天数: 26 天

    [LV.4]偶尔看看III

     楼主| 发表于 2018-2-23 17:06 | 显示全部楼层
    oliver.k 发表于 2018-2-23 13:03
    大佬,那个屏幕是四线串口屏吗,还是tft触摸屏

    串口屏   

    该用户从未签到

    发表于 2018-4-10 11:20 | 显示全部楼层
    能否加个微型? 微信手机号18923777208,  谢谢!
    或提供您的手机号或微信号?   
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表