第1回:用raspberry pi和传感器制作“可自动营造舒适空间的装置” 第一部分
	第2回:用raspberry pi和传感器制作“可自动营造舒适空间的装置” 第二部分
	第3回:用raspberry pi和传感器制作“可自动营造舒适空间的装置” 第三部分
	大家好,我是吉田!
	创作一款让家中更舒适、让在家办公更高效的设备,这个项目终于迎来了剧终篇。这次我们将会再增加一些功能,以完成这个项目。我们会添加一个根据天气预报信息和天气情况提示主人行动的功能,最终创作完成这个可以营造舒适环境的设备,让您即使在家办公也可以舒适地工作!
本部分所需部件
	raspberry pi 3 b+ 或 raspberry pi 4 model b
raspberry pi 3 b+
raspberry pi 4 model b
	raspberry pi用液晶显示器 或 触控显示器
raspberry pi用液晶显示器
触控显示器
	罗姆sensormedal(sensormedal-evk-002)
热释电红外线传感器 (sb412a)
小型扬声器
手机电池
usb设备
本部分的流程
	根据传感器的值控制硬件
	关联天气信息和互联网信息
	完成这款可以营造舒适环境的装置
	总结
	1. 根据传感器的值控制硬件
	在第二部分中,我们使用sensormedal测量了温度和湿度;在第三部分中,我们添加了人体传感器。最初,我们也是打算利用传感器的值来实现下面这些功能的,所以让我们来把它们变为现实吧。
				编号 							检测功能 							检测后希望具备的功能 		
				1 							检测房间的温度 							根据室温控制风扇等 		
				2 							检测房间的舒适度(例如湿度) 							如果湿度高,将空调设置为除湿模式 		
				5 							检测坐在椅子上的时间 							检测到坐的时间太久(久坐不动),督促主人站起来活动活动
首先是检测完温度后,如果室温高于一定水平,需要自动打开风扇保持凉爽。在raspberry pi上插入usb迷你风扇。
要想让风扇根据室温情况打开或关闭,需要使用第二部分中用过的hub-ctrl命令来控制raspberry pi的usb功能。例如,当室温超过26℃时,给usb通电让风扇转起来。
	另外,当使用人体传感器测得您在工作台周围停留超过某一时长(久坐)时,让raspberry pi发出声音来提醒您可能会很有趣。下面,我们将迷你扬声器插入raspberry pi。
获取名为“aquestalkpi”的可以朗读的语音合成软件,在programs下解压。
$ cd ~/programs$ wget http://www.a-quest.com/download/package/aquestalkpi-20130827.tgz$ sudo tar zxvf aquestalkpi-20130827.tgz$ cd aquestalkpi	 
	然后,我们尝试让它播放“该休息了”之类的声音。
$ ./aquestalkpi 休憩しましょう! | aplay	 
	要实现这些功能,需要在第三部分中使用过的ble_lcd.py程序中,添加下面的第2行、第29〜36行(温湿度控制)和第4〜6行、第12〜17行、第38〜43行(人体传感器控制)的内容。
	[ble_lcd.py]
…import oshuman_count = 0human_check = 30aquest_path = /home/pi/programs/aquestalkpi/scanner = btle.scanner()while true:…    human = gpio.input(human_pin)    if human == 1:      human_count+=1    else:      human_count=0    print('hcount:'+str(human_count))    ...    # 针对接收到的数据,对每一个ble设备进行处理    for dev in devices:    ...                '''                for key, value in sorted(sensors.items(), key=lambda x:x[0]):                    print('    ',key,'=',value)                '''                temp  = sensors['temperature']                humid = sensors['humidity']                if temp > 26 or humid > 60:                    temp_msg = hot!                    os.system(sudo hub-ctrl -b 1 -d 2 -p 2 -p 1)                else:                    temp_msg = not bad                    os.system(sudo hub-ctrl -b 1 -d 2 -p 2 -p 0)                human_msg = str(human_count)                if human_count > human_check:                    human_msg += ' take rest!'                    os.system(aquest_path+'aquestalkpi 休憩しましょう! | aplay')                else:                    human_msg += ' work hard!'
2. 关联天气信息和互联网信息
	最后,我们可以从网上获取天气预报等信息,这样会很方便。如果要下雨,最好让它大声朗读并提醒主人采取必要的行动。
				编号 							检测功能 							检测后希望具备的功能 		
				6 							确认天气 							如果天气预报有雨,提醒主人将晒在外面的衣物收回来
首先,我们需要使用名为“openweathermap”的服务来获取天气预报。如下图所示,该网站是英文的,但是从上面可以轻松获取日本国内天气,所以我们将使用这里提供的api。
	https://openweathermap.org/api
从该页面的右上方创建一个帐户并登录。
	然后进入称为“api keys”的页面,确认key(秘钥)并复制此密钥。
接下来,我们需要创建一个可以获取天气预报的程序。首先,要安装以下库文件。
$ sudo pip3 install pytz requests	 
	创建一个名为“forecast.py”的示例程序。将刚刚复制的密钥输入api_key部分。另外,需要在zip部分输入您的邮政编码,并添加国家代码“jp”。下面,我们让刚刚的aquestalk软件也能够播报天气吧。
	[forecast.py]
#! /usr/bin/python3# -*- coding: utf-8 -*-import jsonimport datetimeimport osimport requestsimport sysfrom pytz import timezoneapi_key = xxxzip = 123-4567,jpapi_url = http://api.openweathermap.org/data/2.5/forecast?zip={0}&units=metric&lang=ja&appid={1}def getweatherforecast():    url = api_url.format(zip, api_key)    response = requests.get(url)    forecastdata = json.loads(response.text)    if not ('list' in forecastdata):            print('error')            return    for item in forecastdata['list']:        forecastdatetime = timezone(            'asia/tokyo').localize(datetime.datetime.fromtimestamp(item['dt']))        weatherdescription = item['weather'][0]['description']        temperature = item['main']['temp']        rainfall = 0        if 'rain' in item and '3h' in item['rain']:            rainfall = item['rain']['3h']        break    print('date:{0} weather:{1} temp:{2} c rain:{3}mm'.format(        forecastdatetime, weatherdescription, temperature, rainfall)) return forecastdatetime, weatherdescription, temperature, rainfallforecastdatetime, weatherdescription, temperature, rainfall = getweatherforecast()os.system(“/home/pi/aquestalkpi/aquestalkpi “ + weatherdescription + “ | aplay”)	 
	如下所示,运行该程序时,将会返回指定地区的天气预报。于是,raspberry pi就会向您播报今天的天气预报了,比如“多云”。
$ python3 forecast.py date:2020-06-05 00:00:00+09:00 weather:多云 temp:23.29 c rain:0mm	 
	3. 完成这款可以营造舒适环境的装置
	下面,我们将液晶显示器、扬声器、人体传感器和usb设备都连接到raspberry pi,以完成该设备。
	sensormedal可以放置在ble范围内的任何位置,因此可以将其放置在您桌子周围或窗户附近。当然,您也可以将它放在电脑附近或挂在墙上。
下面是该设备的最终程序,可以让设备根据sensormedal、人体传感器和天气预报等信息执行任务。程序仅供参考。
	[ble_lcd.py]
#!/usr/bin/env python3# coding: utf-8import dothatimport dothat.backlight as backlightimport dothat.lcd as lcdinterval = 10 # 動作間隔from datetime import datetimefrom bluepy import btlefrom sys import argvimport getpassfrom time import sleepimport osimport rpi.gpio as gpiohuman_pin = 13gpio.setmode(gpio.bcm)gpio.setup(human_pin, gpio.in)human_count = 0human_check = 3import jsonimport requestsimport sysfrom pytz import timezoneapi_key = xxx #weathermap api keyzip = 123-4567,jp #your addressapi_url = http://api.openweathermap.org/data/2.5/forecast?zip={0}&units=metric&lang=ja&appid={1}aquest_path = /home/pi/programs/aquestalkpi/ #aquestalkpi pathdef getweatherforecast():    url = api_url.format(zip, api_key)    response = requests.get(url)    forecastdata = json.loads(response.text)    if not ('list' in forecastdata):            print('error')            return                            #print(forecastdata)    for item in forecastdata['list']:        forecastdatetime = timezone('asia/tokyo').localize(datetime.fromtimestamp(item['dt']))        weatherdescription = item['weather'][0]['description']        temperature = item['main']['temp']        rainfall = 0        if 'rain' in item and '3h' in item['rain']:            rainfall = item['rain']['3h']        break    print('date:{0} weather:{1} temp:{2} c rain:{3}mm'.format(forecastdatetime, weatherdescription, temperature, rainfall))    return forecastdatetime, weatherdescription, temperature, rainfalldef payval(num, bytes=1, sign=false):    global val    a = 0    for i in range(0, bytes):        a += (256 ** i) * int(val[(num - 2 + i) * 2 : (num - 1 + i) * 2],16)    if sign:        if a >= 2 ** (bytes * 8 - 1):            a -= 2 ** (bytes * 8)    return ascanner = btle.scanner()while true:    now = datetime.now()    d = '{0:0>4d}/{1:0>2d}/{2:0>2d}({3})'.format(now.year, now.month, now.day, now.strftime('%a'))    t = '{0:0>2d}:{1:0>2d}:{2:0>2d}'.format(now.hour, now.minute, now.second)    forecastdatetime, weatherdescription, temperature, rainfall = getweatherforecast()    lcd.clear()    lcd.set_cursor_position(0, 0)    lcd.write('{}'.format(d))    lcd.set_cursor_position(2, 1)    lcd.write('{}'.format(t))    lcd.set_cursor_position(0, 2)    lcd.write('w:{0}c {1}mm'.format(round(temperature,0), rainfall))    if rainfall > 0:          print(weatherdescription, rainfall)          os.system(aquest_path+'aquestalkpi '+weatherdescription+' | aplay')              human = gpio.input(human_pin)    if human == 1:      human_count+=1    else:      human_count=0    print('hcount:'+str(human_count))    try:        devices = scanner.scan(interval)    except exception as e:        print(error,e)        if getpass.getuser() != 'root':            print('使用方法: sudo', argv[0])            exit()        sleep(interval)        continue    # 受信データについてbleデバイス毎の処理    for dev in devices:        print(ndevice %s (%s), rssi=%d db % (dev.addr, dev.addrtype, dev.rssi))        isrohmmedal = false        sensors = dict()        for (adtype, desc, val) in dev.getscandata():            print(  %s = %s % (desc, val))            if desc == 'short local name' and val[0:10] == 'rohmmedal2':                isrohmmedal = true            if isrohmmedal and desc == 'manufacturer':                # センサ値を辞書型変数sensorsへ代入                sensors['id'] = hex(payval(2,2))                sensors['temperature'] = -45 + 175 * payval(4,2) / 65536                sensors['humidity'] = 100 * payval(6,2) / 65536                sensors['pressure'] = payval(22,3) / 2048                sensors['illuminance'] = payval(25,2) / 1.2                sensors['battery level'] = payval(30)                sensors['rssi'] = dev.rssi                # 画面へ表示                print('    id            =',sensors['id'])                print('    temperature   =',round(sensors['temperature'],2),'℃')                print('    humidity      =',round(sensors['humidity'],2),'%')                print('    pressure      =',round(sensors['pressure'],3),'hpa')                print('    illuminance   =',round(sensors['illuminance'],1),'lx')                print('    battery level =',sensors['battery level'],'%')                print('    rssi          =',sensors['rssi'],'db')                '''                for key, value in sorted(sensors.items(), key=lambda x:x[0]):                    print('    ',key,'=',value)                '''                temp  = sensors['temperature']                humid = sensors['humidity']                lcd.clear()                dothat.backlight.set_graph(0.5) # 50%                backlight.rgb(0, 0, 0)                if temp > 28 or humid > 80:                    temp_msg = hot!                    backlight.rgb(255, 0, 0) #red                else:                    temp_msg = not bad                          illum = sensors['illuminance']                if illum  human_check:                    human_msg += ' take rest!'                    backlight.rgb(0, 255, 0) #green                    os.system(aquest_path+'aquestalkpi 休憩しましょう! | aplay')                else:                    human_msg += ' work hard!'                    backlight.rgb(0, 255, 255) #lightblue                lcd.clear()                lcd.set_cursor_position(0, 0)                lcd.write('t:{0:1.0f}c {1:1.0f}% {2}'.format(temp,humid,temp_msg))                lcd.set_cursor_position(0, 1)                lcd.write('i:{0:1.0f} lx {1}'.format(illum,illum_msg))                lcd.set_cursor_position(0, 2)                lcd.write('h:{}'.format(human_msg))                sleep(interval)	 
	最后,我们让这个程序能够自动启动吧。首先,创建一个shell程序来运行python程序。需要进行服务设置,以使启动该shell程序时能够执行python程序。
	[blelcd.sh]
#!/bin/shsudo /usr/bin/python3 /home/pi/programs/ble_lcd.py	 
	[blelcd.service]
description=rohm medal ble to lcd[service]execstart=/bin/bash /home/pi/programs/blelcd.shworkingdirectory=/home/pi/programsuser=pi[install]wantedby=multi-user.target	 
	现在,当您重新启动它时,raspberry pi将会显示传感器的值,指示灯开始闪烁。
4. 总结
	在这个连载系列中,我们针对在家办公时间增加的情况,创作了一个可以检测办公环境并改善环境的设备。
	在第一部分中,我们思考并列举了希望实现的目标,也了解了用罗姆的sensormedal可以测得多种值。
	在第二部分中,我们创建了实际通过raspberry pi和ble连接sensormedal用的程序。
	在第三部分中,我们使用人体传感器,实现了检测是否有人(是否久坐不动)的功能。此外,还用液晶显示器成功显示了温湿度和亮度等信息。
	在第四部分,也就是本文中,我们增加了天气预报等功能,完成了这个用起来非常方便的设备。当您打开raspberry pi的电源时,它会自动启动并执行自动检测和提醒等任务。
	事实上,它现在每天都在我家工作,它会告诉我周围的亮度,并提醒我别忘了收回晒在外面的衣服!
	鼓励大家也尝试制作方便您居家生活和在家办公的设备!
	相关连载一览
	第1部分:用raspberry pi和传感器制作“可自动营造舒适空间的装置” 第一部分
	第2部分:用raspberry pi和传感器制作“可自动营造舒适空间的装置” 第二部分
	第3部分:用raspberry pi和传感器制作“可自动营造舒适空间的装置” 第三部分
	第4部分:用raspberry pi和传感器制作“可自动营造舒适空间的装置” 第四部分•剧终篇(本章)
			
			
       	 	
    	数字显示器的工作原理_数字显示器电路图
         	 	
    	英特尔正在与台积电接洽,将芯片制造外包出去
         	 	
    	突破美国禁令封锁!华为海思自研OLED驱动芯片试产
         	 	
    	微软让第七代小冰成为了全球最大的跨学科人工智能系统之一
         	 	
    	高通发力5G WiFi 推满足802.11ac需求的StreamBoost路由器
         	 	
    	用Raspberry Pi和传感器制作“可自动营造舒适空间的装置” 第四部分•剧终篇
         	 	
    	虹科AR技术助力泰雷兹进军服务领域
         	 	
    	关于大数据的作用分析和介绍
         	 	
    	如何使用NVIDIA RTX软件增强工作空间功能
         	 	
    	华为30W无线快充技术研发成功
         
       	 	
    	DSP芯片诞生开始究竟带来了什么?
         	 	
    	5G让智慧医疗为患者带来福音
         	 	
    	珠海赛纬IPO:破圈现有市场,进入黄金发展期
         	 	
    	经济部积极推动国内智能机械产业发展 纺织业走向智能化的脚步
         	 	
    	小康助手产品实力如何?赋能中医药行业技术升级
         	 	
    	联发科 Helio X30 规格外洩,传採台积电 10 奈米
         	 	
    	华为云CDN加速,如何为中小企业创新发展效力?
         	 	
    	电解电容极性的判别
         	 	
    	日本VR线下体验店火爆
         	 	
    	开关电源输出可以加大电容吗