夏天到了,每天在办公室上班的时候尽管开着中央空调,吹着电扇,仍然感到热气袭人。但是这究竟因为办公区人多造成的心理作用,还是确实温度居高不下呢?大狗决定为大家找出答案。
具体来说,我们需要就以下几个问题进行分析:
- 如果办公室很热,那么,究竟有多热?
- 办公室全天温度都很高,还是只是一段时间很热?
- 办公室温度高的原因是什么?
三个问题,简单而直接。但是我们要如何找出答案呢?大狗觉得理想的解决方案应该符合如下几条:
- 硬件成本低廉(因为我穷啊[哭])
- 运行可靠,无需人工参与(好的解决方案应该是插上电源,就可以运行到天荒地老,每天都要重启的系统简直弱爆了好不)
- 体积小巧(在办公区使用,低调一点比较稳妥,no zuo no die)
- 独立运行,无需网络支持(因为不想被QS组请喝咖啡)
比较了几种解决方案后,大狗决定使用Arduino单片机实现一个简单的温度监测节点,每隔十秒钟记录一次温度,然后在此基础上进行数据分析。我们需要以下几种硬件:
- Arduino单片机(出于性价比考虑,选用Arduino UNO)
- SD卡存储模块
- DS18B20温度传感器(可以精确到0.5℃,对于办公区温度监测,已经足够了)
- DS1307时钟模块(因为Arduino没有内置时钟,而我们需要记录温度对应的时间)
- 面包板一块(否则就得鼓捣电烙铁)
- 4.7K欧姆电阻器一只
- 杜邦线若干
- SD卡一张
首先,我们需要设计电路,这个比较简单,在设计软件里随手画画,接线的时候心里有有谱啦。
另外,就是需要编写Arduino的控制程序,使用的是C语言,但是Arduino已经封装了很多的功能,而且可以从GitHub上找到很多开源的类库,就不用重新发明轮子啦。
大概是,这个样子的:
如果程序可以编译成功,就可以用USB线缆连接电脑和Arduino,把控制程序“烧”进去。
//Libraries for clock chip
#include
#include "DS1307.h"
DS1307 clock;//define a object of DS1307 class
//Libraries for SD writing
#include
const int cs=4;
File file;
char fileName[]="log.csv";
//Libraries for temperature reading
#include
#include
//Initialize temperature sensor
#define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
void setup() {
Serial.begin(9600);
//Initialize SD Card
Serial.println("Initializing SD card...");
if (!SD.begin(cs)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
file=SD.open(fileName, FILE_WRITE);
//Start Clock
clock.begin();
//Turn on the temperature sensor
sensors.begin();
}
void loop() {
String currentTime = getTime();
Serial.println(currentTime);
//Get temperature from sensor
sensors.requestTemperatures(); // 发送命令获取温度
float temperature = sensors.getTempCByIndex(0);
Serial.println("Temperature: " + String(temperature));
//Write data to SD card
if (file) {
file.println(currentTime + "," + String(temperature));
}
else {
// if the file didn't open, print an error:
Serial.println("Error when open file");
}
file.flush();
delay(10000);
}
String getTime()
{
String result = "";
clock.getTime();
if(clock.hour > 9){
result += String(clock.hour);
}
else{
result += ("0" + String(clock.hour));
}
result += ":";
if(clock.minute > 9){
result += String(clock.minute);
}
else{
result += ("0" + String(clock.minute));
}
result += ":";
if(clock.second > 9){
result += String(clock.second);
}
else{
result += ("0" + String(clock.second));
}
result += " ";
result += String(clock.year+2000);
result += "-";
if(clock.month > 9){
result += String(clock.month);
}
else{
result += ("0" + String(clock.month));
}
result += "-";
if(clock.dayOfMonth > 9){
result += String(clock.dayOfMonth);
}
else{
result += ("0" + String(clock.dayOfMonth));
}
return result;
}
接下来,就可以接线啦,接好后,是这个样子的:
这里,大狗偷了个懒,在Arduino上加了一块传感器扩展板。左侧是DS1307,下面是面包板,面包板上最左侧就是DS18B20温度传感器(比黄豆粒还小),中间是Arduino本体和传感器扩展板,右侧是SD卡存储模块。
把电路接好后,就可以放在一个测试点上,接上电源(其实也可以用9V的叠层电池,但是不确定可以支撑多久,所有还是用的USB线缆,从手机充电器取电,5V妥妥的),让Arduino自己忙活去。大狗该喝咖啡喝咖啡,该刷case刷case。
让Arduino哼哧哼哧忙活了几天后,大狗断开了Arduino的电源,拔下SD卡,把数据文件复制到电脑上,喏,就像这个样子(逗号前面是记录的时间,逗号后面是温度数值):
08:08:592016-05-11,27.69
08:09:102016-05-11,27.63
08:09:212016-05-11,27.56
08:09:312016-05-11,27.50
08:09:422016-05-11,27.50
08:09:532016-05-11,27.44
但是有几万条数据,一条条看下来会累死狗,于是,大狗又用python写了一个数据解析程序,把温度数值用图表呈现出来(python下有一个叫做matplotlib的类库做工精良还免费我会乱说么~),就像,这样子:
import datetime, csv, os, sys, re
import matplotlib.pyplot as mp
import matplotlib.dates as md
import numpy as np
currentPath = ''
sysPath = sys.path[0]
if os.path.isdir(sysPath):
currentPath = sysPath
elif os.path.isfile(sysPath):
currentPath = os.path.dirname(sysPath)
csvFilePath = '%s%s%s' % (currentPath, os.sep, 'log.csv')
reader = csv.reader(file(csvFilePath,'r'))
currentDate = ''
timeList = []
temperatureList = []
colors = ['Aquamarine', 'green', 'red', 'Cyan','Chartreuse', 'Orange', 'Maroon', 'Orchid', 'Salmon', 'Chartreuse']
def addCurve(colorIndex):
print '%s has %s data items.\n' % (currentDate, len(temperatureList))
datenums = md.date2num(timeList)
mp.plot_date(x=datenums, y=temperatureList, xdate=True, ydate=False, color=colors[colorIndex], alpha=0.2, label=currentDate, linewidth=0.2)
r = re.compile(r'^(?P\d+):(?P\d+):(?P\d+)\s(?P.+)$')
i = 0
for line in reader: # 08:08:59 2016-05-11,27.69
matchObject = r.match(line[0])
hour = int(matchObject.group('hour'))
minute = int(matchObject.group('minute'))
second = int(matchObject.group('second'))
date = matchObject.group('date')
if date != currentDate:
if currentDate in ('2016-05-17', '2016-05-16', '2016-05-13', '2016-05-12', '2016-05-14'):
addCurve(i)
i += 1
currentDate = date
timeList = []
temperatureList = []
dotTime = datetime.datetime(year=2000, month=1, day = 1, hour = hour, minute = minute, second = second)
timeList.append(dotTime)
temperatureList.append(float(line[1]))
#addCurve(i)
mp.xlabel('Time')
mp.ylabel('Temperature')
mp.legend(loc = 'upper left', ncol = 1, borderaxespad = 0, fontsize = 12)
mp.title('Temperature in Office')
mp.show()
在这里,大狗取了2016年5月12,13,16和17四个工作日,以及5月14日这个周末进行对比,运行的结果,是这样的:
从图表中可以得到如下结论:
- 在工作日,办公区的温度确实很高,根据国内外的实验,夏季,人们感到最舒适的气温是19—24℃,从图表中可以看出,即使是相对凉爽的5月16日,办公区测试点的全天温度仍然高于24℃,而在5月17日,最高温度甚至逼近30℃。
- 在工作日中,温度最高的时间是下午两点至六点之间,上午则相对温度减低。除去气温因素外,由于我选取的温度测试点位于28层,有部分同事上中国时间,部分同事上欧洲时间,而下午两点至六点之间是办公室人最多的时间段,开启的电脑设备也最多,从而直接拉高了办公区的温度。请大家对比一下图表中红色图线,这是5月14日(周六)的温度曲线,大家可以明显看出,周末的温度变化明显区别于工作日,所以人员和电脑设备是导致办公区温度上升的主要因素之一。
- 还有一个有趣的现象,大家可以从图表中看出,在上午九点前后,在温度曲线上会出现一个小的波峰(在5月13日和16日的图线上尤为明显)。这是由于早晨伴随阳光的射入,办公室温度逐渐上升,九点之后,陆续有同事到办公室并开启中央空调,由于空调吹入的冷空气,测试点温度随后降低。但遗憾的是,给力的中央空调也无法与一百台电脑设备和一百多个热(ku)情(bi)的同事相匹敌[坏笑]
实际上,我们还可以进一步找出其他结论,例如可以在28层部署多个温度测试点,找到28层最热的地方和最凉快的地方,或者增加一个树莓派,利用ZigBee链接多个Arduino节点,实现温度实时监测等,再或者利用Web Service获取外部实时温度,找出办公室的温度变化和外部温度的关系等等。
只有我们有好的创意,心有多大,舞台就有多大。
除了鼓捣Arduino,大狗还在运营一个专注于天津人故事的有内涵无节操的网络播客,欢迎大家通过荔枝FM,网易云音乐,喜马拉雅或苹果Podcast搜索“** 大狗汪叨叨 ”订阅收听,
欢迎大家关注我们的微信公众号“ 大狗汪叨叨 **”,我们将不定期推送节目相关内容。