爱板网论坛

查看: 638|回复: 0

[教程] 用树莓派DIY一个智能家居服务器

[复制链接]

182

主题

11

好友

6068

积分

状元

Rank: 6Rank: 6

  • TA的每日心情
    奋斗
    2016-8-15 09:28
  • 签到天数: 222 天

    连续签到: 1 天

    [LV.7]常住居民III

    爱板会员勋章

    发表于 2017-11-22 11:11:35 |显示全部楼层
    树莓派实验室的好文章
    高考结束啦~来用树莓派DIY一下自己的智能家居吧~
    其实这东西我自己已经用了一年了~现在就来写个教程~嘿嘿……
    先上个图
    20160626192247896-0.jpg


    有点乱23333
    这是我的房间书柜,也是我的工作台……书柜的侧边是树莓派搭建的物联网服务器~
    来一只近图~
    20160626192247673-0.jpg


    这就是服务器的近照啦~
    我用的是树莓派A+作为服务器的主控,所有的工作都由它完成。
    树莓派A+是单核的处理器,RAM仅256MB,不过如果不是作为复杂工作的话……也足够了~
    这里,它的主要工作就是收集房间和室外的环境数据并上传至yeellink,同时获取yeellink上的开关数据控制房间里的灯,门,音响等设备的开关。
    以及,在晚上下晚修我回到家的时候,自动打开灯~睡着了后自动关灯~


    先来简单介绍一下,这里需要用到一些什么东西。如上面那张图,树莓派是肯定要有的~当然,什么版本都可以……因为实际上这里也没用多少GPIO,以前的A,B版本都可以……

    然后,树莓派左下角那个蓝色的是声卡和音响的集成驱动,用来推动喇叭的~使用5V的电源,当然大家可以直接找个小音箱来代替~~
    然后下面那一堆线是面包板,用来分配电源和继电器控制,以及……比较方便接线吧23333.各种传感器可以直接插面包板上,这样就省去了焊线的麻烦。
    另外,由于我用的是树莓派A+,没有网络接口,所以用了一个8口的带电源HUB连接无线网卡和其他的比如USB串口等设备。HUB贴在树莓派上面点,没拍到。

    再下面是电源盒,这里我用的是台式机电脑的电源~为什么用台式机电源呢?这有很大的好处。
    台式机电源有12V,5V和3.3V,并带有一路5V VSB电源,以及还可以用GPIO控制电源整体开关。这就非常适合用来做服务器了,因为我的LED灯条是12V的,电磁锁也是12V的,而树莓派和USB设备都需要5V,一些传感器则需要3.3V,正好一个电源全部搞定它。同时在一些需要耗电的东西不需要用的时候,比如LED灯条,那我还可以把整个电源系统关掉省电~而在关掉总电源的时候,5V VSB是一直保持输出的,就可以用这一路电源给树莓派持续供电~ 是不是觉得很方便?

    简单介绍完整个系统了,来看看接线
    20160626192247323-0.jpg


    这是整个系统的接线图~面包板左边那一坨就是台式机电源的ATX接口。
    最下面的电机是电磁锁。
    音响接的是驱动板。
    以及这里用了个arduino mini,这是后来加上的,用来进行AD转换一些传感器数据然后通过串口发给树莓派。
    下面那些继电器我用洞洞板制作成了一个模块,方便接线用。

    20160626192247488-0.jpg


    20160626192247208-0.jpg


    正面和背面。和我最终做出来的成品稍微有点点出入,因为我在制作时根据实际优化了一下布局。但是大致电路是没什么变化的,大家可以参考制作。
    这个继电器模块主要是用来控制12V设备的, 比如打开LED灯条,开锁等,都是用树莓派GPIO驱动三极管让继电器吸合导通12V的电源让设备工作。
    这里我要特别强调!继电器和电磁锁都为磁感设备,在吸合和释放时因为磁生电效应会产生很强的反向电动势,这个电动势如果不采取措施很容易造成三极管甚至树莓派软击穿!导致树莓派停止工作甚至损坏!所以在每个继电器和电磁锁的线圈两端我都接有一个反向安装的二极管,用来吸收线圈在释放时产生的反向电动势,以保护设备。

    好了~硬件大概就介绍到这。剩下的是软件……
    先是介绍一下,通过yeellink控制LED灯和门锁等设备的控制方案,这个程序还包含了指定时间内检测我是否在家,比如在晚上,如果我回来了则自动开灯。这个是通过ping我手机的IP地址是否有回应来完成判断的。毕竟……出门肯定带手机吧……所以,当ping手机不通的时候,说明我不在家了,就关掉房间里的设备省电。当我回到家时,手机自动连接wifi后,ping通,说明我回来了,然后自动打开灯~

    这一切都是通过bash脚本写的~
    1. #!/bin/bash
    2. ##2015年9月29日 23:32:22
    3. echo "##VI  2016年4月8日 22:56:12  ## V2.2"
    4. TDIR=/tmp
    5. mkdir -p $TDIR
    6. export PATH=$PATH:/usr/local/bin
    7. gpio -g write 21 1
    8. gpio -g mode 21 out ##电源开关  拉低开
    9. gpio -g write 26 1
    10. gpio -g mode 26 out ##桌面灯条  拉低开
    11. gpio -g write 19 1
    12. gpio -g mode 19 out ##桌面灯条  拉低开
    13. gpio -g write 13 1
    14. gpio -g mode 13 out ##柜子锁   拉低开
    15. gpio -g write 6 1
    16. gpio -g mode 6 out  ##门锁        拉低开

    17. FI35=0
    18. CLE_TIME=0  ##检测计数器
    19. ##你API的设备号
    20. DEV=
    21. ##你传感器的编号
    22. SW_POWER=
    23. SW_DSKLED=
    24. SW_DOOR=
    25. SW_FORCER=
    26. SW_CHANGE=

    27. getdev(){
    28.     DEVS=$1
    29.     wget http://api.yeelink.net/v1.0/device/${DEV}/sensor/${DEVS}/datapoints -O $TDIR/sa${DEVS} -T 5 &> /dev/null
    30.     FTIME=`cat $TDIR/sa${DEVS} | sed 's/.*\"\:\"//g;s/\"\,\".*$//g'`
    31.     FYMD=`echo $FTIME | sed 's/T.*$//g'`
    32.     FHMS=`echo $FTIME | sed 's/^.*T//g'`
    33.     VAL=`cat $TDIR/sa${DEVS} | sed 's/^.*value\"\://g;s/\}//g'`
    34.     if [ ! -e $TDIR/savetime${DEVS} ];then
    35.         echo "" > $TDIR/savetime${DEVS}
    36.         if [ "$DEVS" == "$SW_POWER" ];then
    37.             if [ "$VAL" == "1" ];then
    38.                 gpio -g write 21 0
    39.             else
    40.                 gpio -g write 21 1
    41.             fi
    42.         fi
    43.         if [ "$DEVS" == "$SW_DSKLED" ];then
    44.             if [ "$VAL" == "1" ];then
    45.                 gpio -g write 19 0
    46.             else
    47.                 gpio -g write 19 1
    48.             fi
    49.         fi
    50.     fi

    51.      
    52.     echo -e "\e[31;1m$FTIME \e[34;1m# $FYMD ## $FHMS\e[32;1m $DEVS \e[33;1m $VAL\e[0m"
    53.     if [ "$FYMD" == "`date +%Y-%m-%d`" ];then
    54.         echo ##操作日期为当天才进行下面的操作
    55.         if [ "$FHMS" != "`cat $TDIR/savetime${DEVS}`" ];then
    56.             echo ##操作时间不和上次的记录相同才进行下面的操作
    57.             if [ "`echo $FHMS | awk -F ':' '{printf $1}'`" == "`date +%H`" ];then
    58.                 A=`echo $FHMS | awk -F ':' '{printf $1}'`
    59.                 echo -e "\e[31;1m$A\e[0m"
    60.                 ##if [ "$VAL" == "1" ];then
    61.                     if [ "$DEVS" == "$SW_DOOR" ];then   #门锁
    62.                         gpio -g write 6 0
    63.                         sleep 2
    64.                         gpio -g write 6 1
    65.                     elif [ "$DEVS" == "$SW_FORCER" ];then   #柜子锁
    66.                         gpio -g write 13 0
    67.                         sleep 2
    68.                         gpio -g write 13 1
    69.                     elif [ "$DEVS" == "$SW_POWER" ];then    #电源开关
    70.                         if [ "$VAL" == "1" ];then
    71.                             gpio -g write 21 0
    72.                         else
    73.                             gpio -g write 21 1
    74.                         fi
    75.                     elif [ "$DEVS" == "$SW_DSKLED" ];then   #桌面灯条
    76.                         if [ "$VAL" == "1" ];then
    77.                             gpio -g write 19 0
    78.                         else
    79.                             gpio -g write 19 1
    80.                         fi
    81.                     elif [ "$DEVS" == "$SW_CHANGE" ];then   #充电座
    82.                         if [ "$VAL" == "1" ];then
    83.                             gpio -g write 26 0
    84.                         else
    85.                             gpio -g write 26 1
    86.                         fi
    87.                     fi
    88.                     echo "$FHMS" > $TDIR/savetime${DEVS}
    89.                 ##fi
    90.             fi
    91.         fi
    92.     fi
    93. }

    94. ##给LED点阵模块发送时间数据
    95. ledtime(){
    96.     if [ -e /dev/ttyUSB0 ];then
    97.         echo "\`wr`date +%H%M`" | microcom -p /dev/ttyUSB0 -s 115200
    98.     fi
    99. }

    100. ##先初始化锁和充电开关
    101. getdev $SW_DOOR
    102. getdev $SW_FORCER
    103. getdev $SW_CHANGE
    104. getdev $SW_DSKLED

    105. while :
    106. do
    107.     getdev $SW_POWER
    108.     getdev $SW_DSKLED
    109.     getdev $SW_DOOR
    110.     getdev $SW_FORCER
    111.     getdev $SW_CHANGE
    112.      
    113.     if [ "`date +%H%M`" -ge "1900" ];then   ##时间在下午5点20后
    114.         if [ "$FI35" == "0" ];then  ##是否查找过设备233)0否不在线 1是在线
    115.             if [ "`ping 192.168.1.233 -c 1 -S 1 &> /dev/null;echo $?`" == "0" ];then ##查找手机是否在线
    116.                 gpio -g write 21 0
    117.                 gpio -g write 19 0
    118.                 FI35=1
    119.             fi
    120.         elif [ "`date +%H%M`" -ge "1905" ];then ##如果手机不在线则判断时间是否在晚上7点以后
    121.             if [ "$CLE_TIME" -le "5" ];then
    122.                 ((CLE_TIME++))
    123.                 echo "CLE_TIME $CLE_TIME"
    124.             else
    125.                 CLE_TIME=0
    126.                 if [ "`ping 192.168.1.233 -c 1 -S 1 &> /dev/null;echo $?`" == "1" ];then ##如果不在线则清除标记
    127.                     if [ "$CLOSE_LED" == "0" ];then
    128.                         CLOSE_LED=1
    129.                     else
    130.                         CLOSE_LED=0
    131.                         gpio -g write 21 1  ##关灯关电源
    132.                         gpio -g write 19 1
    133.                         FI35=0
    134.                     fi
    135.                 fi
    136.             fi
    137.         fi
    138.     elif [ "`date +%H%M`" -le "0230" ];then ##时间是否在凌晨2点半以内
    139.         if [ "$FI35" == "0" ];then  ##如果是,则判断手机是否在线
    140.             if [ "`ping 192.168.1.233 -c 1 -S 1 &> /dev/null;echo $?`" == "0" ];then ##如果手机在线则开灯
    141.                 gpio -g write 21 0
    142.                 gpio -g write 19 0
    143.                 FI35=1
    144.             fi
    145.         fi
    146.     elif [ "$FI35" != "0" ];then    ##否则关灯
    147.         FI35=0
    148.         gpio -g write 19 1
    149.         gpio -g write 21 1
    150.     fi
    151.          
    152.     sleep 1
    153.     ledtime
    154.     gpio -g write 6 1
    155. done
    复制代码
    然后,是数据上传的程序。通过检测环境数据然后上传到yeellink上,然后yeellink可以自动记录并绘制图表,可以很直观的看到最近的气象温度变化以及树莓派的状态。
    20160626192247985-0.jpg


    额……好像光敏传感器有点问题……不管啦…然后可能由于室外18B20被太阳直接照射的原因……最近温度一直很高……
    然后晚上的温度还是比较正常的……(广西真的好热!)
    20160626192247377-0.jpg
    1. #!/bin/bash
    2. ##连接物联网发送CPU温度
    3. ##BY PokeBox
    4. ##创建于:2014年9月27日
    5. ##最后修改:2014年9月30日 02:04:38
    6. echo "  ##Start YeeLink_Temp......"
    7. APIKEY=''   ##APIKEY
    8. TMPDIR=/tmp/my      ##临时数据目录
    9. TTYFIFO=/run/ttyAMA0.fifo   ##/tmp/ttyAMA0.fifo
    10. sudo modprobe w1-gpio
    11. sudo modprobe w1-therm
    12. gettime(){
    13.     YY=`date +%Y`;MO=`date +%m`;DD=`date +%d`
    14.     HH=`date +%H`;MM=`date +%M`;SS=`date +%S`
    15. }
    16. getCPUMHZ(){
    17.     deviceid=你的设备号
    18.     sensorid=你的传感器号
    19.     VAL=`cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq | awk '{print $1/1000}'`
    20.     echo -e "\e[36;1mCPU_MHz : ${VAL}\e[0m"
    21. }

    22. getCPUdata(){       ##获取CPU数据
    23.     deviceid=你的设备号                  ##设备号
    24.     sensorid=                   ##传感器号
    25.     VAL=`cat /sys/class/thermal/thermal_zone0/temp | awk '{print $1/1000}'`
    26. }
    27. getCPULoad(){       ##获取CPU使用率
    28.     deviceid=你的设备号
    29.     sensorid=
    30.     VAL=$(top -b -n 2 | grep ^%Cpu | sed -n "2p" | sed -e 's/^.*://g;s/..,//g;s/st//g' | awk '{print "scale=1; 100-" $4 }' | bc)
    31.     echo -e "\e[36;1mCPU_USER : ${VAL}\e[0m"
    32. }

    33. ## 删除数据点 http://api.yeelink.net/v1.0/device/你的设备号/sensor/传感器号/datapoint/时间点
    34. getbdata(){     ##获取18b20温度数据室内
    35.     deviceid=你的设备号                  ##设备号
    36.     sensorid=                   ##传感器号
    37.     VAL=`cat /sys/bus/w1/devices/28-000005823549/w1_slave | grep 't=' | sed 's/^.*t=//g' | awk '{print $1/1000}'`
    38.     echo -e "\e[36;1m18B20_IN : ${VAL}\e[0m"
    39. }
    40. getboutdata(){      ##获取18b20温度数据室外
    41.     deviceid=你的设备号                  ##设备号
    42.     sensorid=                   ##传感器号
    43.     VAL=`cat /sys/bus/w1/devices/28-00000581ea9e/w1_slave | grep 't=' | sed 's/^.*t=//g' | awk '{print $1/1000}'`
    44.     echo -e "\e[36;1m18B20_Out : ${VAL}\e[0m"
    45. }
    46. GetPowerTempData(){
    47.     sensorid=
    48.     VAL=`cat /sys/bus/w1/devices/28-031604d2d0ff/w1_slave | grep 't=' | sed 's/^.*t=//g' | awk '{print $1/1000}'`
    49.         echo -e "\e[36;1m18B20_Power : ${VAL}\e[0m"
    50. }
    51. getlight(){
    52.     sensorid=
    53.     VALa=`tac ${TTYFIFO} | grep -a 'AD0' | sed -n '2p' | awk '{print $3}' | sed 's/\r//'`
    54.     VAL=`echo "1024 - ${VALa}" | bc`
    55.     echo -e  "\e[36;1mLux : ${VAL}\e[0m"
    56. }

    57. senddata(){     ##发送数据
    58.     gettime
    59.     echo "{
    60.   \"timestamp\":\"${YY}-${MO}-${DD}T${HH}:${MM}:${SS}\",
    61.   \"value\":${VAL}
    62. }" > $TMPDIR/datafile.txt
    63.     URL="http://api.yeelink.net/v1.0/device/${deviceid}/sensor/${sensorid}/datapoints"  ##物联网地址
    64.     curl --request POST --header "U-ApiKey: ${APIKEY}" --data-binary @$TMPDIR/datafile.txt ${URL}
    65. }
    66. oraynewph status &
    67. while :
    68. do
    69.     getCPUMHZ;senddata  ##CPU频率
    70.     getCPUdata;senddata ##CPU温度
    71.     getCPULoad;senddata ##CPU使用率
    72.     getlight; senddata  ##室外亮度
    73.     getbdata
    74.     TMPVAL=$(echo ${VAL%.*})
    75.     if [ "$TMPVAL" -le "0" ];then
    76.         echo 1 &> /dev/null
    77.     else
    78.         senddata    ##室内温度
    79.     fi
    80.     getboutdata
    81.     TMPVAL=$(echo ${VAL%.*})
    82.     if [ "$TMPVAL" -le "0" ];then
    83.         echo 1 &> /dev/null
    84.     else
    85.         senddata    ##室外温度
    86.     fi
    87.     GetPowerTempData
    88.     TMPVAL=$(echo ${VAL%.*})
    89.         if [ "$TMPVAL" -le "0" ];then
    90.                 echo 1 &> /dev/null
    91.         else
    92.                 senddata        ##电源温度
    93.         fi

    94.     sleep 2m    ##间隔2分钟发送一次
    95. done
    复制代码
    上面是发送传感器数据到yeellink的bash代码,大家如果需要的话……自己去yeellink注册然后创建设备和传感器,然后把你的APIKEY和设备传感器号填到那些对应的变量上就可以用了……然后,上面那三个18B20的设备号是我的18B20的设备号,每一个18B20都有唯一的设备号,大家自己去修改。
    除此之外,大家还可以通过树莓派上的crontab来创建任务,比如在指定时间打开音响播放音乐来做闹钟~
    20160626192247312-0.jpg


    20160626192247665-0.jpg


    这是我用饮料罐自己DIY的音响,配合那个驱动板使用,这样的低音炮,妈妈再也不用担心我起不来床了~
    然后,仔细看的话,大家也许发现第一段代码里有一条发送时间给LED点阵的函数,是的,那个函数是用来驱动这货的……
    20160626192247526-0.jpg


    因为我房间里没有钟,甚至……我家里都没有钟!所以就自己DIY吧……下面是其他时间段的效果
    20160626192247301-0.jpg


    20160626205550888-0.jpg


    有没有觉得很6?!赶紧拿起你手中的树莓派DIY一个吧!更多创意,等你来创造!

    最后截几个有趣的评论
    TIM截图20171122113138.png
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    手机版|爱板网 |网站地图  

    GMT+8, 2017-12-13 07:41 , Processed in 0.265447 second(s), 13 queries , Memcache On.

    苏公网安备 32059002001056号

    Powered by Discuz!

    回顶部