Zerynth Lamp: NeoPixel LEDでスマートIoT間接照明制御
部品と用品
| Zerynth Shield (マルチセンサーボード) | ×1 |
| Arduino Due または ST Nucleo F401RE または Particle Photon または UDOO Dual または Flip&Clip (Mikroelektronika) | ×1 |
| Adafruit NeoPixel LEDストリップ/リング | ×1 |
| Wi-Fiシールド (CC3000搭載) ※Particle Photon使用時は不要 (オンボードWi-Fi) | ×1 |
| ガラス製または3Dプリント製ランプシェード | ×1 |
アプリとオンラインサービス
- Zerynth Studio (マルチプラットフォーム/ブラウザベースPython開発環境、クラウド同期・ボード管理機能付き)
- Zerynth App (スマートオブジェクト/IoTシステム用モバイルインターフェース、スマホがディスプレイ兼リモコンに)
このプロジェクトについて
低電力無線規格、低コスト・超小型LED・センサー・通信デバイスの普及により、スマート照明はIoTとホームオートメーションの触媒となっています。本チュートリアルでは、Zerynth AppからNeoPixel LEDストリップを制御する方法を紹介します。アプリにはカラーピッカーとプリセットアニメーション選択メニューが表示されます。
ステップ1: 必要な材料
- Zerynth Studio: ダウンロード/インストール (OS問わず動作)
- Zerynth App: ダウンロード
- Zerynth Shield: 購入可能 - タッチ/赤外線/マイク/光/温度センサー搭載のマルチセンサーボード
- 対応ボード: Arduino Due、ST Nucleo F401RE、Particle Photon、UDOO、Flip&Clipなど (Zerynthはマルチボード対応、対応リスト)
- Wi-Fi接続: Particle Photon以外はWi-Fiシールド (Adafruit CC3000搭載等) 必要
- NeoPixel LED: Adafruit製
- ランプ本体: ガラス製または3Dプリント製、お好みで
ステップ2: 組み立て
- Wi-FiシールドとZerynth ShieldをArduino (または対応ボード) にピギーバック接続。Particle Photonの場合はZerynth Shieldの専用コネクタに直接装着
- NeoPixel LEDをZerynth Shieldの専用ポートに接続
- すべての基板とLEDをランプシェード内に収納

ステップ3: プログラミング
Zerynth Studioでの開発手順:
- ボードを接続して「仮想化」 (解説記事)
- 新規プロジェクト作成 (解説記事) - main.py、animation.py、template.html、project.md の4ファイル作成
- 以下のコードをコピー
- ボードにアップロード (uplink) して完了!
起動後、プリセットネットワークに自動接続。Zerynth Appを開くとネットワーク上のZerynthオブジェクトを検索、「Zerynth Lamp」を選択で操作可能。カラーピッカーとアニメーションメニューで直感制御。
コードは豊富なコメント付きでシンプル。質問・提案は Zerynthコミュニティフォーラム へ。
ステップ4: IoTをもっと明るく!
Zerynth Shieldにはタッチ検知、赤外線LED、マイク、光センサー、温度センサーなどが搭載。このシンプルな例をベースに、好みの動作を開発可能。Zerynth Shieldでランプ機能を拡張しましょう!
— Luigi F. Cerfeda (@L_F_Cerfeda) - Zerynthチーム
コード
main.py (Python)
################################################################################
# Zerynth Lamp
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################
import streams
from bcm43362 import bcm43362 as wifi_driver
from wireless import wifi
import animation
from toishield import toishield
from zerynthapp import zerynthapp
streams.serial()
# Wi-Fi接続
try:
wifi_driver.auto_init()
print("Establishing Link...")
wifi.link("SSID", wifi.WIFI_WPA2, "password")
print("Ok!")
except Exception as e:
print(e)
# template.htmlをボードフラッシュに保存
new_resource("template.html")
#### ZerynthApp Setup
# JavaScript → Python 呼び出し関数
def change_color(r, g, b):
animation.setup_color(r, g, b)
def change_animation(n):
animation.setup_anim(n)
def change_speed(n):
animation.setup_anim_speed(n)
# ZerynthApp設定: 名前、説明、テンプレートURL
vp = zerynthapp.ZerynthApp("Zerynth Lamp", "Try me!", "resource://template.html")
vp.on("change_color", change_color)
vp.on("change_animation", change_animation)
vp.on("change_speed", change_speed)
vp.run()
# バックグラウンドでLED制御継続
animation.start(D6, 24)
template.html (HTML/JavaScript)
Zerynth Lamp
Powered by Zerynth (www.zerynth.com)
animation.py (Python)
################################################################################
# Zerynth Lamp - Animation Functions
################################################################################
from neopixel import ledstrips as neo
import threading
lock = threading.Lock()
color = [0x54, 0x9a, 0x97] # デフォルト色 (Zerynthカラー)
anim = 0
anim_speed = 50
leds = None
layer0 = layer1 = layer2 = None
npins = 0
stopped = False
stopcolor = [0xff, 0xff, 0xff]
# スムーズアニメーション用係数 (半周正弦波)
animation_coefficients = [
0, 0.2588, 0.5, 0.7071, 0.8660, 0.9659,
1, 0.9659, 0.8660, 0.7071, 0.5, 0.2588
]
rainbow = [
(0xff,0x00,0x00), (0xff,0x7f,0x00), (0xff,0xff,0x00),
(0x00,0xff,0x00), (0x00,0x00,0xff), (0x4b,0x00,0x82), (0x8f,0x00,0xff)
]
def setup_anim(n):
global layer0,layer1,layer2,anim
lock.acquire()
leds.clear(); layer2.clear(); layer0.clear(); layer1.clear()
n = n % 4
if n == 0: # Little Snakes
layer0[0]=layer0[1]=layer0[2]=(100,0,0)
layer1[0]=layer1[1]=layer1[2]=(0,100,0)
elif n == 1: # Spinner
for x in range(npins//2):
layer0[x]=(100//(2*x+1),0,0)
layer1[npins-x-1]=(0,100//(2*x+1),0)
layer2.clear()
elif n == 2: # Rainbow
layer1.clear()
pstep = 0
for x in range(npins):
step = x*len(rainbow)/npins
rx = (rainbow[int(step)][0]+rainbow[int(pstep)][0])//4
gx = (rainbow[int(step)][1]+rainbow[int(pstep)][1])//4
bx = (rainbow[int(step)][2]+rainbow[int(pstep)][2])//4
layer0[x]=(rx,gx,bx)
pstep = step
elif n == 3: # Pulse
layer0.clear(); layer1.clear()
anim = n
lock.release()
def setup_anim_speed(n):
global anim_speed
anim_speed = n
def setup_color(r,g,b):
global color
color[0]=r; color[1]=g; color[2]=b
# バックグラウンドアニメーション (Pulse用)
def animate_background(delay):
global color, stopped
step = 0
while True:
if (anim==3 or anim==0) and not stopped:
lock.acquire()
layer2.setall(int(color[0]*animation_coefficients[step]/2),
int(color[1]*animation_coefficients[step]/2),
int(color[2]*animation_coefficients[step]/2))
lock.release()
step = (step + 1) % len(animation_coefficients)
else:
lock.acquire()
layer2.clear(); layer2.setall(stopcolor[0],stopcolor[1],stopcolor[2])
lock.release()
sleep(delay+500-5*anim_speed)
# フォアグラウンドアニメーション (Snakes/Spinner/Rainbow)
def animate_foreground(delay):
global stopped
while True:
if not stopped:
lock.acquire()
if anim == 0: layer0.lshift(); layer1.rshift()
elif anim == 1: layer0.rshift(); layer1.rshift()
elif anim == 2: layer0.rshift(); layer1.rshift()
elif anim == 3: layer0.lshift(); layer1.lshift()
lock.release()
else:
lock.acquire(); layer0.clear(); layer1.clear(); lock.release()
sleep(delay+100-anim_speed)
def start(pin, numpins):
global leds,layer0,layer1,layer2,npins
npins = numpins
leds = neo.LedStrip(pin, numpins)
layer0 = neo.LedStrip(pin, numpins)
layer1 = neo.LedStrip(pin, numpins)
layer2 = neo.LedStrip(pin, numpins)
setup_anim(0)
setup_anim_speed(50)
thread(animate_background, 500)
thread(animate_foreground, 50)
while True:
leds.clear()
lock.acquire()
leds.merge(layer0); leds.merge(layer1)
leds.merge(layer2, neo.first_color) # 透明部分のみ背景合成
lock.release()
leds.on()
sleep(50)
def stop(r,g,b):
global stopped, stopcolor
stopcolor[0]=r; stopcolor[1]=g; stopcolor[2]=b
stopped = True
def resume():
global stopped
stopped = False
setup_anim(anim)
回路図

製造プロセス