本記事は、 North Detail Advent Calendar 2019 の25日目の記事です。
https://qiita.com/tacck/items/67701a6a24003c9021d2
Qiita にて作成した記事からの転記となります。 (2019年12月25日公開)
※本記事は、NorthDetail Advent Calendar 2019の一環として投稿しています
メリークリスマス!
アドベントカレンダーも最終日のクリスマス、そしてクリスマスと言えばラズパイですよね!
ということで、 North Detail Advent Calendar 2019 の最後はクリスマスツリーを照らすライトを制御する仕組みを Raspberry Pi で作ってみたいと思います。
2018年 / クリスマスの定番(?) Raspberry PiとAlexaで光るクリスマスツリーを作る【動画あり】
2017年 / クリスマスの定番(?) Raspberry Piで光るクリスマスリースを作る【動画あり】
クリックすると、 YouTube で動画を観ることができます。
Raspberry Pi に取り付けたセンサーを振ることでライトの ON/OFF を、傾きで明るさや色合いの調整を行なえるようにしています。
傾きなどを検出できるものが用意できればOK。今回はこちらを使用。
今回は、以前に "Echo Show" 購入時にセットで買ったものを(ようやく)活用。
ブリッジを使って、 Raspberry Pi から Hue を繋ぎます。
より正確に言えばブリッジがWebサーバになっているので、 Raspberry Pi からブリッジに HTTP のリクエストを出すことで、 Hue の制御ができるようになります。
LEDライト共通の注意事項ですが、白熱電球とは 主に熱を持つ部分が異なります 。
白熱電球は発光部分のフィラメントを中心に熱を持ちますが、LEDライトはソケット部分を中心に熱を持ちます。
そのため、ソケット周辺がきちんと放熱される構造のスタンドをご使用ください。
最初はスマホアプリを使って、ブリッジにライトを登録しておきます。
この辺りは、アプリの使用方法に沿って作業してください。
以降は、ブリッジと Raspberry Pi 、作業用のPCが全て同一のネットワークに存在する前提で進みます。
ブリッジへHTTPリクエストを出すことになるので、IPアドレスを知っておく必要があります。
これは、ブリッジが正しく設定できていれば下記アドレスへアクセスすることで取得できます。
https://discovery.meethue.com/
[
{
id: "XXXXXXXXXXXXXXXX",
internalipaddress: "10.xxx.xxx.xxx"
}
]
この internalipaddress
が、現在接続されているネットワークでのIPアドレスになります。
メモっておきましょう。
Raspberry Pi から操作する場合、ブリッジ上に一意のユーザーIDが必要になります。
ブリッジ本体にあるボタン(物理)を押した後に、下記のような形でHTTPリクエストを投げると、レスポンスの中に username
が入っています。
こちらを、今後のHTTPリクエストで使うのでこちらもメモしておいてください。
ちなみに、 devicetype
は各自で自由に設定可能です。
POST http://[internalipaddress]/api
body: {"devicetype":"tacck_hue_app#raspi"}
[
{
"success": {
"username": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
}
]
続いて、ライトの操作をするためにブリッジに登録されているライトのIDを取得します。
GET http://[internalipaddress]/api/[username]/lights
{
"1":{"state":{"on":false,"bri":254,...}
}
たくさん情報が返ってきますが、最初の "1"
がIDになります。
下記のHTTPリクエストを投げると、ライトが点灯するはずです。
(true
のところをfalse
にすれば、消灯します。)
internalipaddress
、username
、light_id
は、各自のものに置き換えてください。
PUT http://[internalipaddress]/api/[username]/lights/[light_id]/state
body: {"on":true}
続いて、 Raspberry Pi 側のセッティングです。
Raspberry Pi については、すでに Raspbian が起動できている状態で、WiFiが利用可能な前提とします。
また、センサー (ADRSZGR) も Raspberry Pi 本体と接続済みの想定です。
まずは、センサーの値を取得できるか確認です。
こちらは、ベースとなるソースコードが提供されているので、それを使ってみます。
ベースのコード
https://github.com/bit-trade-one/RasPi-Zero-One-Series/tree/master/3rd/ADRSZGR_9-Axis_Gyro
Raspberry Pi 上で実行してみましょう。
$ git clone https://github.com/bit-trade-one/RasPi-Zero-One-Series.git
$ cd RasPi-Zero-One-Series/3rd/ADRSZGR_9-Axis_Gyro
$ python3 ADRSZGR_Sample.py
10秒間、センサを動かさないでください
あと1秒
キャリブレーション終了
X:-0.045608688186813184 Y:0.7310804429945055 Z:-4.547119140625
2.7179718017578125e-05,0.01416015625,0.0185546875,1.0087890625,-0.045608688186813184,-0.12341174450549453,-0.152587890625,-14.843956043956045,6.447374847374848,-1.6493284493284492,
0.05398225784301758,0.0126953125,0.01513671875,1.00927734375,0.13749678056318682,0.059693724244505475,-0.213623046875,-16.193406593406593,6.297435897435897,-0.8996336996336997,
(以下続くので、適当なところで Ctrl+C で中断。)
このように値が出てくれば、センサーが動いているのでOKです。
では、センサーの値を使って Hue のライトを操作するように実装してみましょう。
センサーの制御はベースにある GYRO.py
が全てやってくれるので、値をどう使うか、だけを考えれば大丈夫です。
今回は、センサーを振ったら ON/OFF 、傾けたら明るさと色調の変化、という設計で実装していきます。
先ほど確認で使った ADRSZGR_Sample.py
を index.py
としてコピーし、こちらを使っていきます。
また、私は普段 Python を書かないので、インデントの谷[※]に注意しながら実装していきます。
[※] 私の造語です。
https://speakerdeck.com/tacck/phpergawen-kitaipythonfalseikutukafalsekoto-pycon-mini-sapporo-2019-number-pyconsap?slide=18
色々と調整して、下記のようなコードで落ち着きました。
.
├── GYRO.py
└── index.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import signal
import requests
import time
import GYRO
GYR_THRESHOLD = 200.0
HUE_BRI_MIN = 0
HUE_BRI_MAX = 254
HUE_BRI_HALF = round((HUE_BRI_MAX - HUE_BRI_MIN + 1) / 2)
HUE_CT_MIN = 153
HUE_CT_MAX = 454
HUE_CT_HALF = round((HUE_CT_MAX - HUE_CT_MIN + 1) / 2)
HUE_API = 'http://[internalipaddress]/api/[username]/lights'
if __name__ == "__main__":
signal.signal(signal.SIGINT, signal.SIG_DFL)
gyro = GYRO.GYRO()
time.sleep(0.1)
gyro.sensor_calib()
# 照明の点灯状態
light_on = False
prev_light_on = light_on
light_bri = HUE_BRI_MIN + HUE_BRI_HALF
light_ct = HUE_CT_MIN + HUE_CT_HALF
while True:
# センサー値の読み取りと必要な変数へ格納
values = gyro.get_sense_value()
axs_x = values[0]
axs_y = values[1]
# axs_z = values[2]
# print('{0:4.2f}'.format(axs_x), end=",")
# print('{0:4.2f}'.format(axs_y), end=",")
# print('{0:4.2f}'.format(axs_z), end=",")
# gyr_x = values[3]
# gyr_y = values[4]
gyr_z = values[5]
# print('{0:4.2f}'.format(gyr_x), end=",")
# print('{0:4.2f}'.format(gyr_y), end=",")
# print('{0:4.2f}'.format(gyr_z), end=",")
# X軸の傾きから色調を変更
light_ct += axs_x * HUE_CT_HALF
if light_ct < HUE_CT_MIN:
light_ct = HUE_CT_MIN
if light_ct > HUE_CT_MAX:
light_ct = HUE_CT_MAX
# Y軸の傾きから輝度を変更
light_bri += axs_y * HUE_CT_HALF
if light_bri < HUE_BRI_MIN:
light_bri = HUE_BRI_MIN
if light_bri > HUE_BRI_MAX:
light_bri = HUE_BRI_MAX
# Z方向の角速度が閾値を超えたら照明のON/OFFを制御
if gyr_z < -GYR_THRESHOLD:
light_on = not light_on
# Hue へ投げる
if prev_light_on != light_on or light_on:
requests.put(HUE_API + '/[light_id]/state', json = {"on": light_on, "bri": round(light_bri), "ct": round(light_ct)})
# ON/OFF 確認用ログ
if prev_light_on != light_on:
print ('lignht_on:', light_on)
prev_light_on = light_on
time.sleep(0.10)
実行した結果が、冒頭の動画となります。
これを踏まえて、ぜひもう一度ご覧ください。
今回は0.1秒ごとに投げていますが、ネットワークやブリッジの負荷は自己責任でお願いします。
色々と組み合わせれば、部屋の照明も自在に操れるようになりますね。
家のライトを Hue のシリーズで揃えると、かなり楽しいことができそうです。