This article is the 25th day article of North Detail Advent Calendar 2019.
2020/04/02 postscript This article is also posted on the NorthDetail blog. https://www.northdetail.co.jp/blog/455/
Merry Christmas! The Advent calendar is Christmas on the last day, and Christmas is Raspberry Pi!
So, at the end of North Detail Advent Calendar 2019, I would like to create a mechanism to control the lights that illuminate the Christmas tree with Raspberry Pi.
Click to watch the video on YouTube.
By shaking the sensor attached to the Raspberry Pi, you can turn the light on and off, and adjust the brightness and color by tilting.
Raspberry Pi
It is OK if you can prepare something that can detect tilt etc. Use this this time.
Hue
This time, I (finally) used what I bought as a set when I purchased "Echo Show".
Use a bridge to connect Hue from your Raspberry Pi.
More precisely, since the bridge is a web server, you can control Hue by making an HTTP request from the Raspberry Pi to the bridge.
It is a common precaution for LED lights, but it is ** mainly different from incandescent bulbs in the part that has heat **.
Incandescent light bulbs have heat centered on the filament of the light emitting part, while LED lights have heat centered on the socket part. Therefore, use a stand with a structure that properly dissipates heat around the socket.
First, use the smartphone app to register the light on the bridge. Please work around here according to how to use the app.
After that, we will proceed on the assumption that the bridge, Raspberry Pi, and work PC are all on the same network.
You need to know the IP address as you will be making an HTTP request to the bridge. This can be obtained by accessing the following address if the bridge is set correctly.
https://discovery.meethue.com/
[
{
id: "XXXXXXXXXXXXXXXX",
internalipaddress: "10.xxx.xxx.xxx"
}
]
This ʻinternalipaddress` will be the IP address of the currently connected network. Let's make a note.
When operating from Raspberry Pi, a unique user ID is required on the bridge. After pressing the button (physical) on the bridge body, if you make an HTTP request in the following form, ʻusername` is included in the response. Make a note of this as it will be used in future HTTP requests.
By the way, devicetype
can be set freely by yourself.
POST http://`internalipaddress`/api
body: {"devicetype":"tacck_hue_app#raspi"}
response.json
[
{
"success": {
"username": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
}
]
Next, get the ID of the light registered in the bridge to operate the light.
GET http://`internalipaddress`/api/`username`/lights
response.json
{
"1":{"state":{"on":false,"bri":254,...}
}
A lot of information is returned, but the first " 1 "
is the ID.
Throw the HTTP request below and the light should come on.
(If you change true
to false
, it will turn off.)
Replace ʻinternalipaddress, ʻusername
, and light_id
with your own.
PUT http://`internalipaddress`/api/`username`/lights/`light_id`/state
body: {"on":true}
Raspberry Pi
Next is the setting on the Raspberry Pi side. For Raspberry Pi, it is assumed that WiFi is available with Raspbian already running. Also, it is assumed that the sensor (ADRSZGR) is already connected to the Raspberry Pi main unit.
First, check if you can get the sensor value. Here, the base source code is provided, so let's use it.
Base code https://github.com/bit-trade-one/RasPi-Zero-One-Series/tree/master/3rd/ADRSZGR_9-Axis_Gyro
Let's run it on a 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
Do not move the sensor for 10 seconds
1 second left
Calibration finished
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,
(Since it continues below, Ctrl at an appropriate place+Suspended at C.)
If the value comes out like this, it is OK because the sensor is moving.
Now let's implement it to use the sensor values to manipulate Hue lights.
The base GYRO.py
does all the control of the sensor, so you only have to think about how to use the values.
This time, we will implement it with a design that turns ON / OFF when the sensor is shaken and changes in brightness and color tone when tilted.
Copy ʻADRSZGR_Sample.py used in the previous confirmation as ʻindex.py
and use this.
Also, since I don't usually write Python, I will implement it while paying attention to the indentation valley [^ 1].
[^ 1]: My coined word. https://speakerdeck.com/tacck/phpergawen-kitaipythonfalseikutukafalsekoto-pycon-mini-sapporo-2019-number-pyconsap?slide=18
I made various adjustments and settled down with the following code.
.
├── GYRO.py
└── index.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()
#Lighting status
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:
#Read sensor values and store in required variables
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=",")
#Change the color tone from the tilt of the X axis
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
#Change the brightness from the tilt of the Y axis
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
#Turn on the lighting when the angular velocity in the Z direction exceeds the threshold/Control OFF
if gyr_z < -GYR_THRESHOLD:
light_on = not light_on
#Throw to 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 confirmation log
if prev_light_on != light_on:
print ('lignht_on:', light_on)
prev_light_on = light_on
time.sleep(0.10)
The result of the execution will be the video at the beginning. With this in mind, please take a look again.
This time, it is thrown every 0.1 seconds, but please take responsibility for the load on the network and bridge.
If you combine it in various ways, you will be able to freely control the lighting in the room. Aligning the house lights with the Hue series can be a lot of fun.