分享

用树莓派DIY一个智能家居服务器 | 树莓派实验室

 共同成长888 2020-03-27

来自树莓派实验室老司机群 Pokebox 的投稿~
高考结束啦~来用树莓派DIY一下自己的智能家居吧~
其实这东西我自己已经用了一年了~现在就来写个教程~嘿嘿……
先上个图
20160626192247896-0
有点乱23333
这是我的房间书柜,也是我的工作台……书柜的侧边是树莓派搭建的物联网服务器~
来一只近图~
20160626192247673-0
这就是服务器的近照啦~
我用的是树莓派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
这是整个系统的接线图~面包板左边那一坨就是台式机电源的ATX接口。
最下面的电机是电磁锁。
音响接的是驱动板。
以及这里用了个arduino mini,这是后来加上的,用来进行AD转换一些传感器数据然后通过串口发给树莓派。
下面那些继电器我用洞洞板制作成了一个模块,方便接线用。
20160626192247488-0

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

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

这一切都是通过bash脚本写的~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/bin/bash
##2015年9月29日 23:32:22
echo "##VI  2016年4月8日 22:56:12  ## V2.2"
TDIR=/tmp
mkdir -p $TDIR
export PATH=$PATH:/usr/local/bin
gpio -g write 21 1
gpio -g mode 21 out ##电源开关  拉低开
gpio -g write 26 1
gpio -g mode 26 out ##桌面灯条  拉低开
gpio -g write 19 1
gpio -g mode 19 out ##桌面灯条  拉低开
gpio -g write 13 1
gpio -g mode 13 out ##柜子锁   拉低开
gpio -g write 6 1
gpio -g mode 6 out  ##门锁        拉低开
FI35=0
CLE_TIME=0  ##检测计数器
##你API的设备号
DEV=
##你传感器的编号
SW_POWER=
SW_DSKLED=
SW_DOOR=
SW_FORCER=
SW_CHANGE=
getdev(){
    DEVS=$1
    wget http://api./v1.0/device/${DEV}/sensor/${DEVS}/datapoints -O $TDIR/sa${DEVS} -T 5 &> /dev/null
    FTIME=`cat $TDIR/sa${DEVS} | sed 's/.*\"\:\"//g;s/\"\,\".*$//g'`
    FYMD=`echo $FTIME | sed 's/T.*$//g'`
    FHMS=`echo $FTIME | sed 's/^.*T//g'`
    VAL=`cat $TDIR/sa${DEVS} | sed 's/^.*value\"\://g;s/\}//g'`
    if [ ! -e $TDIR/savetime${DEVS} ];then
        echo "" > $TDIR/savetime${DEVS}
        if [ "$DEVS" == "$SW_POWER" ];then
            if [ "$VAL" == "1" ];then
                gpio -g write 21 0
            else
                gpio -g write 21 1
            fi
        fi
        if [ "$DEVS" == "$SW_DSKLED" ];then
            if [ "$VAL" == "1" ];then
                gpio -g write 19 0
            else
                gpio -g write 19 1
            fi
        fi
    fi
     
    echo -e "\e[31;1m$FTIME \e[34;1m# $FYMD ## $FHMS\e[32;1m $DEVS \e[33;1m $VAL\e[0m"
    if [ "$FYMD" == "`date +%Y-%m-%d`" ];then
        echo ##操作日期为当天才进行下面的操作
        if [ "$FHMS" != "`cat $TDIR/savetime${DEVS}`" ];then
            echo ##操作时间不和上次的记录相同才进行下面的操作
            if [ "`echo $FHMS | awk -F ':' '{printf $1}'`" == "`date +%H`" ];then
                A=`echo $FHMS | awk -F ':' '{printf $1}'`
                echo -e "\e[31;1m$A\e[0m"
                ##if [ "$VAL" == "1" ];then
                    if [ "$DEVS" == "$SW_DOOR" ];then   #门锁
                        gpio -g write 6 0
                        sleep 2
                        gpio -g write 6 1
                    elif [ "$DEVS" == "$SW_FORCER" ];then   #柜子锁
                        gpio -g write 13 0
                        sleep 2
                        gpio -g write 13 1
                    elif [ "$DEVS" == "$SW_POWER" ];then    #电源开关
                        if [ "$VAL" == "1" ];then
                            gpio -g write 21 0
                        else
                            gpio -g write 21 1
                        fi
                    elif [ "$DEVS" == "$SW_DSKLED" ];then   #桌面灯条
                        if [ "$VAL" == "1" ];then
                            gpio -g write 19 0
                        else
                            gpio -g write 19 1
                        fi
                    elif [ "$DEVS" == "$SW_CHANGE" ];then   #充电座
                        if [ "$VAL" == "1" ];then
                            gpio -g write 26 0
                        else
                            gpio -g write 26 1
                        fi
                    fi
                    echo "$FHMS" > $TDIR/savetime${DEVS}
                ##fi
            fi
        fi
    fi
}
##给LED点阵模块发送时间数据
ledtime(){
    if [ -e /dev/ttyUSB0 ];then
        echo "\`wr`date +%H%M`" | microcom -p /dev/ttyUSB0 -s 115200
    fi
}
##先初始化锁和充电开关
getdev $SW_DOOR
getdev $SW_FORCER
getdev $SW_CHANGE
getdev $SW_DSKLED
while :
do
    getdev $SW_POWER
    getdev $SW_DSKLED
    getdev $SW_DOOR
    getdev $SW_FORCER
    getdev $SW_CHANGE
     
    if [ "`date +%H%M`" -ge "1900" ];then   ##时间在下午5点20后
        if [ "$FI35" == "0" ];then  ##是否查找过设备233)0否不在线 1是在线
            if [ "`ping 192.168.1.233 -c 1 -S 1 &> /dev/null;echo $?`" == "0" ];then ##查找手机是否在线
                gpio -g write 21 0
                gpio -g write 19 0
                FI35=1
            fi
        elif [ "`date +%H%M`" -ge "1905" ];then ##如果手机不在线则判断时间是否在晚上7点以后
            if [ "$CLE_TIME" -le "5" ];then
                ((CLE_TIME++))
                echo "CLE_TIME $CLE_TIME"
            else
                CLE_TIME=0
                if [ "`ping 192.168.1.233 -c 1 -S 1 &> /dev/null;echo $?`" == "1" ];then ##如果不在线则清除标记
                    if [ "$CLOSE_LED" == "0" ];then
                        CLOSE_LED=1
                    else
                        CLOSE_LED=0
                        gpio -g write 21 1  ##关灯关电源
                        gpio -g write 19 1
                        FI35=0
                    fi
                fi
            fi
        fi
    elif [ "`date +%H%M`" -le "0230" ];then ##时间是否在凌晨2点半以内
        if [ "$FI35" == "0" ];then  ##如果是,则判断手机是否在线
            if [ "`ping 192.168.1.233 -c 1 -S 1 &> /dev/null;echo $?`" == "0" ];then ##如果手机在线则开灯
                gpio -g write 21 0
                gpio -g write 19 0
                FI35=1
            fi
        fi
    elif [ "$FI35" != "0" ];then    ##否则关灯
        FI35=0
        gpio -g write 19 1
        gpio -g write 21 1
    fi
         
    sleep 1
    ledtime
    gpio -g write 6 1
done

然后,是数据上传的程序。通过检测环境数据然后上传到yeellink上,然后yeellink可以自动记录并绘制图表,可以很直观的看到最近的气象温度变化以及树莓派的状态。
20160626192247985-0
额……好像光敏传感器有点问题……不管啦…然后可能由于室外18B20被太阳直接照射的原因……最近温度一直很高……
然后晚上的温度还是比较正常的……(广西真的好热!)
20160626192247377-0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/bin/bash
##连接物联网发送CPU温度
##BY PokeBox
##创建于:2014年9月27日
##最后修改:2014年9月30日 02:04:38
echo "  ##Start YeeLink_Temp......"
APIKEY=''   ##APIKEY
TMPDIR=/tmp/my      ##临时数据目录
TTYFIFO=/run/ttyAMA0.fifo   ##/tmp/ttyAMA0.fifo
sudo modprobe w1-gpio
sudo modprobe w1-therm
gettime(){
    YY=`date +%Y`;MO=`date +%m`;DD=`date +%d`
    HH=`date +%H`;MM=`date +%M`;SS=`date +%S`
}
getCPUMHZ(){
    deviceid=你的设备号
    sensorid=你的传感器号
    VAL=`cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq | awk '{print $1/1000}'`
    echo -e "\e[36;1mCPU_MHz : ${VAL}\e[0m"
}
getCPUdata(){       ##获取CPU数据
    deviceid=你的设备号                  ##设备号
    sensorid=                   ##传感器号
    VAL=`cat /sys/class/thermal/thermal_zone0/temp | awk '{print $1/1000}'`
}
getCPULoad(){       ##获取CPU使用率
    deviceid=你的设备号
    sensorid=
    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)
    echo -e "\e[36;1mCPU_USER : ${VAL}\e[0m"
}
## 删除数据点 http://api./v1.0/device/你的设备号/sensor/传感器号/datapoint/时间点
getbdata(){     ##获取18b20温度数据室内
    deviceid=你的设备号                  ##设备号
    sensorid=                   ##传感器号
    VAL=`cat /sys/bus/w1/devices/28-000005823549/w1_slave | grep 't=' | sed 's/^.*t=//g' | awk '{print $1/1000}'`
    echo -e "\e[36;1m18B20_IN : ${VAL}\e[0m"
}
getboutdata(){      ##获取18b20温度数据室外
    deviceid=你的设备号                  ##设备号
    sensorid=                   ##传感器号
    VAL=`cat /sys/bus/w1/devices/28-00000581ea9e/w1_slave | grep 't=' | sed 's/^.*t=//g' | awk '{print $1/1000}'`
    echo -e "\e[36;1m18B20_Out : ${VAL}\e[0m"
}
GetPowerTempData(){
    sensorid=
    VAL=`cat /sys/bus/w1/devices/28-031604d2d0ff/w1_slave | grep 't=' | sed 's/^.*t=//g' | awk '{print $1/1000}'`
        echo -e "\e[36;1m18B20_Power : ${VAL}\e[0m"
}
getlight(){
    sensorid=
    VALa=`tac ${TTYFIFO} | grep -a 'AD0' | sed -n '2p' | awk '{print $3}' | sed 's/\r//'`
    VAL=`echo "1024 - ${VALa}" | bc`
    echo -e  "\e[36;1mLux : ${VAL}\e[0m"
}
senddata(){     ##发送数据
    gettime
    echo "{
  \"timestamp\":\"${YY}-${MO}-${DD}T${HH}:${MM}:${SS}\",
  \"value\":${VAL}
}" > $TMPDIR/datafile.txt
    URL="http://api./v1.0/device/${deviceid}/sensor/${sensorid}/datapoints"  ##物联网地址
    curl --request POST --header "U-ApiKey: ${APIKEY}" --data-binary @$TMPDIR/datafile.txt ${URL}
}
oraynewph status &
while :
do
    getCPUMHZ;senddata  ##CPU频率
    getCPUdata;senddata ##CPU温度
    getCPULoad;senddata ##CPU使用率
    getlight; senddata  ##室外亮度
    getbdata
    TMPVAL=$(echo ${VAL%.*})
    if [ "$TMPVAL" -le "0" ];then
        echo 1 &> /dev/null
    else
        senddata    ##室内温度
    fi
    getboutdata
    TMPVAL=$(echo ${VAL%.*})
    if [ "$TMPVAL" -le "0" ];then
        echo 1 &> /dev/null
    else
        senddata    ##室外温度
    fi
    GetPowerTempData
    TMPVAL=$(echo ${VAL%.*})
        if [ "$TMPVAL" -le "0" ];then
                echo 1 &> /dev/null
        else
                senddata        ##电源温度
        fi
    sleep 2m    ##间隔2分钟发送一次
done

上面是发送传感器数据到yeellink的bash代码,大家如果需要的话……自己去yeellink注册然后创建设备和传感器,然后把你的APIKEY和设备传感器号填到那些对应的变量上就可以用了……然后,上面那三个18B20的设备号是我的18B20的设备号,每一个18B20都有唯一的设备号,大家自己去修改。

除此之外,大家还可以通过树莓派上的crontab来创建任务,比如在指定时间打开音响播放音乐来做闹钟~
20160626192247312-0
20160626192247665-0
这是我用饮料罐自己DIY的音响,配合那个驱动板使用,这样的低音炮,妈妈再也不用担心我起不来床了~

然后,仔细看的话,大家也许发现第一段代码里有一条发送时间给LED点阵的函数,是的,那个函数是用来驱动这货的……
20160626192247526-0
因为我房间里没有钟,甚至……我家里都没有钟!所以就自己DIY吧……下面是其他时间段的效果
20160626192247301-0
20160626205550888-0
有没有觉得很6?!赶紧拿起你手中的树莓派DIY一个吧!更多创意,等你来创造!大家记得把自己的作品跟帖哦!

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多