「Raspberry Pi」というものに興味があったのですが、敷居が高く、使い道もよく分からなかったのは事実。しかし「当ページの内容を作ってみたい!」と思ったのがきっかけで、Raspberry Piを購入しました。そういった記念すべき作品です。(2019/02/26更新)
当ページの「はじめに」
成果物は、「部屋の温度・湿度・CO2が表示できる電子ペーパー計!」です。
正直、LED系の表示モノであれば安くていろいろと手に入ると思いますので、コスパは激悪です。
ただし、アイディア次第で色々と他の用途にも使えますので、将来的には使い勝手を上げていきたいな、と。
01. 完成イメージ
目に優しい電子ペーパーをディスプレイとした、部屋の温度、湿度、CO2濃度を表示するパネル。
この作品のポイントは「電子ペーパーを使う」という点で、LED系の時計とかとは違い、まぶしくなく、かつ見やすいです。
「Netatmo」というウェザーステーションを使い、その情報を電子ペーパーに出力します。1年以上前からNetatmoを使っているのですが、閾値を超えると通知はこれど、イマイチ有効に使えていない感がありました。常時、数値が見える場所にあることで、計測が活かせるものと思います。
(ものすごく無駄な構成。。。)
処理イメージ
完成物
電子ペーパー+HAT+Raspberry Pi ZERO WH(ケース付)です。
配線は、GPIOコネクタにガツンと装着することも可能です。個別の配線にした理由は、ヒートシンクと物理的に重なって接続できなかったため 笑 と、将来の拡張性を残すため(他のGPIOコネクタを使うため)、です。
3Dプリンタで壁のレールにちょうどハマるように作りました。
製作2時間(失敗込み)、印刷10時間(失敗込み)。
後ろの配線は、内緒だよ。(面倒なので適当)
02. 必要なモノ
自分としては手持ちのものを流用しつつ、でしたが、一から全てを揃えるのはしんどいかも。。
手持ちの範囲で、お選びください。代替できるものはたくさんあります。例えば、Netatmoではなく、温湿度センサーにするとか。(当ページの内容とは変わってしまいますが。)
・Raspberry Pi ZERO WH
Raspberry Piであればなんでもよいですが、ネットワーク接続必須です。
⇒ Amazon
・電子ペーパー
自分はそれなりの大画面にしたかったので、Raspberry Piでも使えると謳っている WAVESHARE というメーカーの「3色 7.5インチ E-Inkディスプレイ HAT(B)」を購入しました。
白、黒、赤の3色表示です。ただし、ディスプレイサイズ、色数が増えると、書き換えにかかる時間が長くなります。(このモデルだと約30秒!かかります。時刻表示にはあまり向かないですね。)
小さく、白黒のみでしたら、(使ったことないですが) 3秒、とかみたいです。
ラズパイと接続できればなんでもよいと思いますが、以降のプログラムはWAVESHARE前提で進めますのでご了承ください。
⇒ Amazon / waveshare
・Netatmo
おうちのウェザーステーション、という製品。これを買えば、スマホでも今回作るようなものが見れます。笑 というか、それが正しい。
今回は、このNetatmoで集めた情報がNetatmoの自分のアカウントに貯まるので、公式APIをたたいてラズパイで情報を取得、その内容を表示する、という流れになります。
⇒ Amazon
・作品本体のケース
なんでもOKなのですが、自分は3Dプリンタでデザインし、壁にかけられるようにしました。専用のケースは売っていないので、、、どうしましょうかね。。
03. 必要ライブラリのインストール、環境設定
適当に作ったのでイマイチなのですが、、、とりあえず、個人用に動くモノを作ることが優先。
・Netatmoから情報を取得するAPIをぶったたくライブラリ lnetatmo は Python3
・電子ペーパー WAVESHARE のSPIライブラリは Python2 ※Python3のライブラリもあります
を使います。
・WAVESHARE の公式サイトに電子ペーパーを使うためのライブラリがありますので、そちらも取得します。Python用もあります。https://www.waveshare.com/wiki/File:7.5inch_e-paper_hat_b_code.7z
# 公式コードの取得
# Raspberry Pi の Pythonコード以外にも多数含まれています
# 利用する電子ペーパーにあったコードをダウンロードしてください(URLが異なります)
# 例)
wget https://www.waveshare.com/w/upload/0/01/7.5inch_e-paper_hat_b_code.7z# 7zが解凍できない場合はアプリをインストール
sudo apt install p7zip# 解凍
# 解凍後の /RaspberryPi/python2 が該当のサンプル
7zr x 7.5inch_e-paper_hat_b_code.7z
・あと、NetatmoのAPIを利用できるように、Netatmoのサイトで開発者登録し、認証コードを発行する必要があります。(無料)
NETATMO connect( https://dev.netatmo.com/ )にログインし、CREATE YOUR APP > 必須事項を入力してSAVE > ここで作成した Client id と Client secret が、自分のNetatmoにPythonからアクセスするログインキーになります。
・その他、必要パッケージ等の準備
# Python3関係の準備
pip3 install lnetatmo
# Python2関係の準備
# 日本語フォントをインストール
sudo apt install fonts-noto-cjk# PythonでSPI通信をするためのライブラリ(電子ペーパーとのやりとりで必要)
sudo apt install python-spidev# Pythonで画像処理をするためのライブラリ
sudo apt install python-pil# Pythonでタイムゾーンを管理するためのライブラリ
sudo apt install python-tz
# Raspberry PiのSPI通信を有効にする
sudo raspi-config
# Interfacing Options > SPI > はい
# で設定
11. コーディング
全体の処理の流れは以下の通り。
超適当につぎはぎで作りましたし、pathベタ打ちと最低のコーディング。。。
肝となる処理のご参考にはなると思いますので記載します。
Netatmo呼び出し(get_netatmo_co2.py) ※Python3
# -*- coding: utf-8
# lnetatmoを使用しNetatmoのAPIをたたいて、返ってきたJSONの中身で必要なものだけを出力する、だけ。
import lnetatmo
from datetime import datetimedef main():
# 変数定義
netatmo1 = “xxx” #狙ったステーションを選択
netatmo1_co2 = “0”
netatmo1_temp = “0”
netatmo1_hum = “0”# tokenを取得
# clientId と clientSecret は、上述のNETATMO Connectで取得した値をセット
# username と password は、Netatmo にログインする自身のログイン情報
authorization = lnetatmo.ClientAuth(
clientId = “xxx”,
clientSecret = “xxx”,
username = “xxx”,
password = “xxx”,
scope = “”
)# 天気情報の取得
weather_station = lnetatmo.WeatherStationData(authorization)# 辞書型への格納
mydict1 = weather_station.lastData()# 測定値を格納
netatmo1_co2 = mydict1[netatmo1][“CO2”] netatmo1_temp = mydict1[netatmo1][“Temperature”] netatmo1_hum = mydict1[netatmo1][“Humidity”]# 測定値を表示(カンマ区切り) ※シェルに戻すために強引に出力。。
print(str(netatmo1_temp) + “,” + str(netatmo1_hum) + “,” + str(netatmo1_co2))# 直接起動した場合に実行(importで呼んだ場合は起動しない)
if __name__ == ‘__main__’:
main()
電子ペーパーへの書き込み(main_show_jp.py) ※Python2
# encoding: utf-8
import sys
import epd7in5b
from PIL import Image, ImageDraw, ImageFont
import pytz
import datetimeEPD_WIDTH = 640
EPD_HEIGHT = 384def main():
# 引数取得
args = sys.argv
str1 = args[1] #温度、湿度、CO2濃度
spl1 = str1.split(‘,’)str_temp = spl1[0] str_hum = spl1[1] str_co2 = spl1[2]
# コメント設定エリア
comment1 = u”Hallo World!”# 現在時刻取得
jp_now = datetime.datetime.now(pytz.timezone(‘Asia/Tokyo’))epd = epd7in5b.EPD()
epd.init()# For simplicity, the arguments are explicit numerical coordinates
image_red = Image.new(‘1’, (EPD_WIDTH, EPD_HEIGHT), 255) # 255: clear the frame
draw_red = ImageDraw.Draw(image_red)
image_black = Image.new(‘1’, (EPD_WIDTH, EPD_HEIGHT), 255) # 255: clear the frame
draw_black = ImageDraw.Draw(image_black)
font30 = ImageFont.truetype(‘/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc’, 30)
font40 = ImageFont.truetype(‘/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc’, 40)
font45 = ImageFont.truetype(‘/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc’, 45)
font60 = ImageFont.truetype(‘/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc’, 60)# 表示設定:コメント
draw_red.text((15, 10), comment1, font = font60, fill = 0)# 表示設定:温度
draw_black.text((100, 150), u”温度: “, font = font45, fill = 0)
draw_black.text((260, 150), str_temp, font = font45, fill = 0)
draw_black.text((380, 150), u”℃”, font = font45, fill = 0)# 表示設定:湿度
draw_black.text((100, 200), u”湿度: “, font = font45, fill = 0)
if int(str_hum) < 40:
draw_red.text((260, 200), str_hum, font = font45, fill = 0)
draw_black.text((340, 200), u”%”, font = font45, fill = 0)
else:
draw_black.text((260, 200), str_hum, font = font45, fill = 0)
draw_black.text((340, 200), u”%”, font = font45, fill = 0)# 表示設定:CO2表示
draw_black.text((100, 250), u”CO2: “, font = font45, fill = 0)
if int(str_co2) > 1000:
draw_red.text((260, 250), str_co2, font = font45, fill = 0)
draw_black.text((400, 250), u”PPM”, font = font45, fill = 0)
else:
draw_black.text((260, 250), str_co2, font = font45, fill = 0)
draw_black.text((360, 250), u”PPM”, font = font45, fill = 0)
draw_black.text((380, 320), jp_now.strftime(‘%m/%d %H:%M ‘) + u”表示”, font = font30, fill = 0)# 電子ペーパーに内容変更命令
epd.display_frame(epd.get_frame_buffer(image_black),epd.get_frame_buffer(image_red))if __name__ == ‘__main__’:
main()
呼び出しシェル(run.sh)
# cron呼び出しを考慮し、PATHを指定してPythonコードの配置ディレクトリに移動
cd xxxco2=`python3 get_netatmo_co2.py`
python main_show_jp.py $co2
・cron の設定
# cronの編集
crontab -e# 15分おきにシェルが起動するように設定
*/15 * * * * /xx/run.sh
89. 今後の拡張
・湿度やCO2が閾値を超えていたら、LEDランプがつくようにしたい。
・閾値を超えた時に音を鳴らしても面白いかも。
・cronの定期実行以外にも、赤外線リモコンで情報再取得指示(リフレッシュ指示)が出せるようにしたい。
・天気情報を表示させたい。
91. 参考サイト
ほぼ全てについて、色々なサイトを参考にさせていただきました。多謝!
・こちらのサイトが電子ペーパーを操作するほぼベースになっています。
試行錯誤な日々>Raspberry Piでe-Paper(電子ペーパー)を動かして日本語を表示する方法
96. つぶやき
・cronで15分間隔で処理、2ヶ月ほど動かし続けておりますが、問題なく安定稼働しています。
・もっと大きな電子ペーパーが欲しくなります。。液晶系と違い、電子ペーパーは見やすくてよいですね。