BLOG ブログ


2019.12.25 TECH

クリスマスの定番(?) Raspberry Pi と Philips Hue でクリスマスツリーをライティング

本記事は、 North Detail Advent Calendar 2019 の25日目の記事です。
Qiita にて作成した記事からの転記となります。 (2019年12月25日公開)

https://qiita.com/tacck/items/67701a6a24003c9021d2

※本記事は、NorthDetail Advent Calendar 2019の一環として投稿しています

メリークリスマス!
アドベントカレンダーも最終日のクリスマス、そしてクリスマスと言えばラズパイですよね!

ということで、 North Detail Advent Calendar 2019 の最後はクリスマスツリーを照らすライトを制御する仕組みを Raspberry Pi で作ってみたいと思います。

2018年 / クリスマスの定番(?) Raspberry PiとAlexaで光るクリスマスツリーを作る【動画あり】

2017年 / クリスマスの定番(?) Raspberry Piで光るクリスマスリースを作る【動画あり】

動画

クリックすると、 YouTube で動画を観ることができます。

Raspberry Pi に取り付けたセンサーを振ることでライトの ON/OFF を、傾きで明るさや色合いの調整を行なえるようにしています。

揃えるもの

Raspberry Pi

センサー

傾きなどを検出できるものが用意できればOK。今回はこちらを使用。

Hue

ライト

今回は、以前に "Echo Show" 購入時にセットで買ったものを(ようやく)活用。

ブリッジ

ブリッジを使って、 Raspberry Pi から Hue を繋ぎます。

より正確に言えばブリッジがWebサーバになっているので、 Raspberry Pi からブリッジに HTTP のリクエストを出すことで、 Hue の制御ができるようになります。

その他

  • ライトスタンド (LEDライトつけて大丈夫なもの)
  • ツリーなどの飾り

LEDライト共通の注意事項ですが、白熱電球とは 主に熱を持つ部分が異なります

白熱電球は発光部分のフィラメントを中心に熱を持ちますが、LEDライトはソケット部分を中心に熱を持ちます。
そのため、ソケット周辺がきちんと放熱される構造のスタンドをご使用ください。

Hue の設定

最初はスマホアプリを使って、ブリッジにライトを登録しておきます。
この辺りは、アプリの使用方法に沿って作業してください。

以降は、ブリッジと Raspberry Pi 、作業用のPCが全て同一のネットワークに存在する前提で進みます。

ブリッジのIPアドレス確認

ブリッジへ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取得

続いて、ライトの操作をするためにブリッジに登録されているライトのIDを取得します。

GET http://[internalipaddress]/api/[username]/lights
{
  "1":{"state":{"on":false,"bri":254,...}
}

たくさん情報が返ってきますが、最初の "1" がIDになります。

下記のHTTPリクエストを投げると、ライトが点灯するはずです。
(trueのところをfalseにすれば、消灯します。)

internalipaddressusernamelight_idは、各自のものに置き換えてください。

PUT http://[internalipaddress]/api/[username]/lights/[light_id]/state

body: {"on":true}

Raspberry Pi

続いて、 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.pyindex.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 のシリーズで揃えると、かなり楽しいことができそうです。


tacck
ライター名:tacck
元 技術推進Group Group Leader

現在は株式会社ノースディテールを離れて、
エバンジェリストとして技術啓蒙や勉強会の開催、各種プロジェクトに参画しています。
機会があれば、ノースディテールでのプロジェクトに参加できればと思っています。

言語は問わずに対応しますが、心はPHPer。
フロントエンド・バックエンド・インフラ・スマホアプリなどを、
「垣根を超えて」どう作るか、を考えるのが好きです。

好きなフィギュアスケートの技はスプレッド・イーグル。

主な記事一覧へ

一覧に戻る


LATEST ARTICLE 最新の記事

CATEGORY カテゴリー