树莓派3B和攀藤PMS5003ST


0.数据仅供学习参考,一切以官方数据为准。

archlinuxarm下安装软件:

1
2
pacman -S mysql php-fpm nginx cronie mysql-clients vi
pip install pyserial

archlinuxarm下的命令

初始化mysql并启动服务

1
2
3
mariadb-install-db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
systemctl enable mariadb
systemctl start mariadb

1.需要的设备:攀藤PMS5003ST,树莓派3B。如果直接连接电脑也可以,需要的软件http://on8vei0g9.bkt.clouddn.com/PM2.5Collector.zip。下面所有代码下载http://on8vei0g9.bkt.clouddn.com/PM25.rar

2.使用RS232USB转串口线连接攀藤,参照文档,接VCC,GND和TXD即可,PIN3可设置休眠。

3.使用python读取数据,在命令行直接显示数据,网页的话不需要这个文件

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
#encoding=utf-8
import os
import serial
import time
from struct import *
ser = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=2.0)
def read_pm_line(_port):
    rv = b''
    while True:
        ch1 = _port.read()
        if ch1 == b'\x42':
            ch2 = _port.read()
            if ch2 == b'\x4d':
                rv += ch1 + ch2
                rv += _port.read(38)
                return rv
def main():
    # conn = sqlite3.connect('pm25.db')
    # c = conn.cursor()
    recv = read_pm_line(ser)
    tmp = recv[4:36]
    datas = unpack('>hhhhhhhhhhhhhhhh', tmp)
    print('Plantower PMS5003ST,Updated:',time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
    print('PM1.0(CF=1): {}ug/m3\n'
              'PM2.5(CF=1): {}ug/m3\n'
              'PM10 (CF=1): {}ug/m3\n'
              'PM1.0 (STD): {}ug/m3\n'
              'PM2.5 (STD): {}ug/m3\n'
              'PM10  (STD): {}ug/m3\n'
              '>0.3um     : {}/0.1L\n'
              '>0.5um     : {}/0.1L\n'
              '>1.0um     : {}/0.1L\n'
              '>2.5um     : {}/0.1L\n'
              '>5.0um     : {}/0.1L\n'
              '>10um      : {}/0.1L\n'
              'HCHO       : {}mg/m3\n'
              'Temperature: {}C\n'
              'Humidity   : {}%'.format(datas[0], datas[1], datas[2],
                                       datas[3], datas[4], datas[5],
                                       datas[6], datas[7], datas[8],
                                       datas[9], datas[10], datas[11],
                                       datas[12]/1000.0, datas[13]/10.0, datas[14]/10.0))
    ser.flushInput()
    time.sleep(0.1)
if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        if ser != None:
            ser.close()

4.网站主页,单击当前数值显示完整数据

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
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>空气质量</title>
<style>
html,body{
margin:0px 0px 0px 0px;
padding:0px 0px 0px 0px;
height:100%;
}
#showLayout{
width:100%;
height:100%;
}
#showLayout p:nth-child(1){
background:#e7f7ed;
}
#showLayout p:nth-child(2){
background:#f9f5e3;
}
#showLayout p:nth-child(3){
background:#fbefe3;
}
#showLayout p:nth-child(4){
background:#fbe2e2;
}
#showLayout p:nth-child(5){
background:#f4e3f5;
}
#showLayout p:nth-child(6){
background:#ede2ed;
}
#showLayout p{
margin:0px 0px 0px 0px;
padding:10px 10px 10px 10px;
width:5%;
height:16.67%;
}
#detailLayout{
display:none;
}#detailLayout p{
margin:0px 0px 0px 0px;
padding:0px 0px 0px 0px;
}
#dataLayout{
display:none;
}
p{
font-size:40pt;
}
</style>
<script type="text/javascript" src="http://cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
</head>
<body>
<div id="showLayout">
<p></p><p></p><p></p><p></p><p></p><p></p>
</div>
<div id="detailLayout">
</div>
<div id="dataLayout">
<div id="data">
</div>
<div id="date">
</div>
</div>
</body>
</html>
<script type="text/javascript" language="JavaScript">
function getData(){
    $.ajax({
        url: "getData.php",
        dataType: "json",
        async: false,
        type: "POST",
        success: function (data){
            $('#data').html(data.pm);
            $('#date').html(data.date);
        }
    });
}
$(document).ready(function(){
    getData();
    var number = $('#data').html();
    number = number.substring(1,number.length-1);
    number = number.split(',');
    var backgroundColor = "white";
    var fontColor = "black";
    var airQuality = "无";
    var index = 0;
    if (number[4] >= 0 && number[4] <= 12){
        fontColor = "#acddc6";
        airQuality = "优";
        index = 0;
    }
    if (number[4] > 12 && number[4] <= 35){
        fontColor = "#e0b902";
        airQuality = "良";
        index = 1;
    }
    if (number[4] > 35 && number[4] <= 55){
        fontColor = "#f08008";
        airQuality = "轻度污染";
        index = 2;
    }
    if (number[4] > 55 && number[4] <= 150){
        fontColor = "#db2d01";
        airQuality = "中度污染";
        index = 3;
    }
    if (number[4] > 150 && number[4] <= 250){
        fontColor = "#c870cd";
        airQuality = "重度污染";
        index = 4;
    }
    if (number[4] > 250 && number[4] <= 1000){
        fontColor = "#8f6091";
        airQuality = "严重污染";
        index = 5;
    }
    $('#showLayout p:eq(' + index + ')').html('<span>' + airQuality + '</span><br/><span>' + number[4] + 'μg/m³</span>');
    $('#showLayout p:eq(' + index + ')').css("color",fontColor);
    $('#showLayout p:eq(' + index + ')').css("text-align","center");
    $('#showLayout p:eq(' + index + ')').css('width','100%');
    var fontSize = $(window).height() / 16;
    $('p').css('font-size',fontSize);
    $('#showLayout p:eq(' + index + ')').click(function(){
        if($('#detailLayout').css('display') == 'none'){
            $('#detailLayout').show();
            $('#detailLayout').html('<p>数据更新时间:'+$('#date').html()+'</p><p>数据测量位置:广东省广州市</p><p>标准颗粒物质量浓度(CF=1)</p><p>PM 1.0: '+number[0]+' μg/m³</p><p>PM 2.5: '+number[1]+' μg/m³</p><p>PM 10 : '+number[2]+' μg/m³</p><p>大气环境下颗粒物质量浓度</p><p>PM 1.0: '+number[3]+' μg/m³</p><p>PM 2.5: '+number[4]+' μg/m³</p><p>PM 10 : '+number[5]+' μg/m³</p><p>0.1升空气中直径大于某值的颗粒物个数</p><p>>0.3μm: '+number[6]+'/0.1L</p><p>>0.5μm: '+number[7]+'/0.1L</p><p>>1.0μm: '+number[8]+'/0.1L</p><p>>2.5μm: '+number[9]+'/0.1L</p><p>>5.0μm: '+number[10]+'/0.1L</p><p>>10 μm: '+number[11]+'/0.1L</p><p>甲醛: '+number[12]+'mg/m³</p><p>温度: '+number[13]+'℃</p><p>湿度: '+number[14]+'%</p>');
        }
        else{
            $('#detailLayout').hide();
            $('#detailLayout').html('');
        }
    });
});
</script>

5.getData.php,上面的index.html需要

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
$dsn = 'mysql:dbname=pm;host=127.0.0.1;port=3306';
$username = 'root';
$password = '';
try {
$db = new PDO($dsn, $username, $password);
} catch(PDOException $e) {
die('Could not connect to the database:
' . $e);
}
$db->query('set names utf8');
$sql = "select * from pm order by time desc limit 1";
$obj = $db->prepare($sql);
$obj->execute();
$arr = $obj->fetchAll(PDO::FETCH_ASSOC);
$data = array("pm"=>$arr[0]['data'],"date"=>$arr[0]['time']);
echo json_encode($data);
//print_r($arr[0][time]);
?>

6.sendPM2.5.py

需要安装requests模块
pip install requests

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
# encoding=utf-8
import os
import serial
import time
import requests
import json
from struct import *

# pip install requests

ser = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=2.0)


def read_pm_line(_port):
rv = b''
while True:
ch1 = _port.read()
if ch1 == b'\x42':
ch2 = _port.read()
if ch2 == b'\x4d':
rv += ch1 + ch2
rv += _port.read(38)
return rv

def writefile(filereadlines):
#write file
newfile = open('data.json', mode='w', encoding='UTF-8')
newfile.writelines(filereadlines)
newfile.close()

def main():
recv = read_pm_line(ser)

tmp = recv[4:36]
datas = unpack('>hhhhhhhhhhhhhhhh', tmp)
sendData = datas[0], datas[1], datas[2], datas[3], datas[4], datas[5], datas[6], datas[
7], datas[8], datas[9], datas[10], datas[11], datas[12]/1000.0, datas[13]/10.0, datas[14]/10.0
sendData = str(tuple(sendData))
tmp = sendData.split(' ')
sendData = ''.join(tmp)
url = 'http://127.0.0.1/pm25/receivePM2.5.php?pm=' + sendData[1:-1]
se = requests.Session()
response = requests.get(url)
ser.flushInput()
time.sleep(0.1)

outputData = {'temperature':datas[13]/10,'humidity':datas[14]/10,'pm25':datas[4]}

writefile(json.dumps(outputData))


if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
if ser != None:
ser.close()

7.定时发送数据

启动服务

1
2
systemctl enable cronie
systemctl start cronie

crontab -e,每10分钟获取一次数据

*/10 * * * * /usr/bin/python /root/sendPM2.5.py

8.sql表结构

如果需要修改mysql的root密码
运行mysql -u root -p后
运行set password for root@localhost = password(‘12332144’);

1
2
3
4
5
6
7
8
create database pm;

use pm;

CREATE TABLE `pm` (
`data` varchar(60) NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=MyISAM DEFAULT CHARSET=gbk;