複数LEDをパッケージ化した部品を使う:3D RGB Xmas Tree for Raspberry Pi
ここでは、The Pi Hut社の3D RGB Xmas Tree for Raspberry Piを使い方を説明します。これは小さなクリスマス・ツリーで、25個のLEDをひとつにまとめた部品です(以下写真参照)。The Pi Hut社はイギリスの会社で、イギリスから国際便で発送すると5〜10ドルの送料だと思います。アメリカ国内では PiShop.us、カナダではPiShop.caで売られています。「Pre-soldered Kit」と「Soldering Kit」というバージョンがありますが、前者の方が手軽に使えます(おすすめです)。後者を買うと、自分で半田づけをする作業があります。
この部品は、「複数LEDをパッケージ化した部品を使う:Christmas Tree Programmable Kit」で紹介したもののアップブレード版です。LEDの数が倍以上になっていて、各LEDの色を自由に変更できるようになっています。
組み立てと接続
購入したばかりの段階では、この部品は以下の写真のような状態になっています。
ここから、クリスマスツリーの3つの部分を切り出します(以下の写真参照)。ニッパー(plier)などを使ってください。頑丈なハサミでも切れます。
そして、7本のピンを7つのピン穴に差し込んで、以下のようにツリーを組み立ててください。
ツリーの下の部分には合計40個の穴があいています。これをラズパイのGPIOのピン40本に差し込みます。差し込む向きが重要です。以下の写真の赤く囲った部分に注意しながら、差し込んでください。
テスト
まずは、このクリスマスツリーが正常に動作するかどうかテストします。tree.pyをラズパイにコピー、保存してください。GitHubに置いてあるプログラムをラズパイにコピーするには、IoTワークショップの1日目にやった方法でやってください。
次に、all-on.pyをラズパイにコピーし、tree.pyと同じフォルダに保存してください。これを実行すると、ツリーに付いているすべてのLEDが白色で点灯するはずです(3秒間点灯して、その後消えます)。これが確認できたらテストは成功です。
ツリーを使う時には、以下のように関数RGBXmasTree()を呼んで(callして)クリスマスツリーを初期化します(LEDを点滅できるように準備します)。
tree = RGBXmasTree()
関数RGBXmasTree()は、ツリーとやり取りする通信口(LEDの点滅に関する命令をツリーに送るための通信口)を返し、ここではそれを変数treeに入れています。
そして、この通信口を使って関数on()を以下のように呼ぶと、すべてのLEDが点灯します。デフォルトの色は白です。特に色の指定をしないと自動的に白が使われます。
tree.on()
また、すべてのLEDを消灯するには、以下のようにします。
tree.off()
基本プログラミング
次に、all-on-blue.pyを実行してください。これは白ではなく青を使ってすべてのLEDを点灯させます。ツリーに付いているすべてのLEDの色を変えるには以下のようにします。
tree.color = Color("blue")
“blue”の部分を他の色の名前に変えると、LEDの色が変わります。光の三原色(red、green、blue)、色の三原色(cyan、magenta、yellow)、黒(black)、白(white)に加え、数多くの色を指定できます。他にどの色を使えるかは、こちらを参照して下さい。「Color name」の列にある色の名前はすべて使えます。自分の好きな色に変えて、その通りにLEDが光ることを確認してください。
all-on-off.pyは、すべてのLEDが同時に点滅をくり返すプログラムです。2秒間点灯し、2秒間消灯するのをくり返します。このプログラムは、無限ループ(infinite loop)を使ってLEDをずっと(無限回)点滅させ続けます。点滅を止める(プログラムの実行を止める)にはThonnyの中で「Control-C」してください。無限ループ、Control-Cについては、ワークショップの2日目に習っているので、その時の資料を参照してください。
star-on-off.pyは、ツリー頂上の星の部分にあるLEDだけ点滅させます。以下のようにすると、ツリーの中から星の部分のLEDだけを取り出すことができます。
starLight = tree.star()
そして、以下のようにして、星の部分のLEDを点灯させます。
starLight.on()
ここでは色の指定をしていないので、デフォルトの白色でLEDは光ります。この行を以下の行に置きかえると、白でなく黄色で光るようになります。
starLight.color = Color("yellow")
自分で好きな色に変えて、その通りにLEDが光ることを確認してください。
次にnonstar-lights-on-off.pyを実行してください。これは、ツリー頂上の(星の部分の)LEDを黄色、他のすべてのLEDを赤で点滅させるプログラムです。このプログラムは、以下のように関数tree.nonStarLights()
を使って、ツリーの中から頂上部分以外の(24個の)LEDを取り出し、forループを使って各LEDを赤く点灯させます。
for light in tree.nonStarLights():
light.color = Color("red")
関数tree.nonStarLights()
は、頂上部分以外のLEDを「リスト」として返します。リストとは、複数のデータを順番に並べたもので、ここでは、
[1番目のLED, 2番目のLED, 3番目のLED, ・・・, 24番目のLED]
という風に、LEDが24個並んでいます。この24個のLEDそれぞれを赤く点灯させるためにforループを使っています。リストに関する基本的なことは「リストとは」というページにまとめてあるので参照してください。
上記forループの先頭行は「tree.nonStarLights()が返すリストの各データ(各LED)を変数lightで表す」と理解します。そしてループは次のように実行されていきます。
- ループを最初に実行するときには、tree.nonStarLights()が返すリストの最初のデータ(1番目のLED)を変数lightに入れて、ループ内のプログラムを実行する。つまり、
light.color = Color("red")
の部分では、1番目のLEDを赤く点灯させる。
- ループを2回目に実行する時には、tree.nonStarLights()が返すリストの2番目のデータ(2番目のLED)を変数lightに入れて、ループ内のプログラムを実行する。つまり、
light.color = Color("red")
の部分では、2番目のLEDを赤く点灯させる。
同様に、ループの3回目、4回目の実行時には、3番目のLED、4番目のLEDが点灯します。tree.nonStarLights()が返すリストには24個のデータ(LED)が入っているので、ループは24回実行されます。
ループが24回実行されたら、次の行に移り、以下の部分が実行されます。
time.sleep(interval)
tree.off()
ここでは、プログラムの実行が2秒間止まり(つまりLEDが点灯しているのが2秒続く)、その後すベてのLEDが消えます。
光の色と明るさを変える
次のプログラムがrandom-colors-brightness.pyです。これは、LEDの色と明るさをランダムに変え続けます。まずは以下のようにして、赤、緑、白、金の4色をリストにしておいて、これをLEDの色の候補として使います。
colors = [Color("red"), Color("green"),
Color("white"), Color("gold")]
そして、以下のようにして、4色の候補の中からひとつをランダムに選んで、その色でLEDを点灯させます。
for light in tree.nonStarLights():
light.color = random.choice(colors)
関数random.choice()
は、与えられたリストの中からランダムにデータをひとつ選んで返します。ここでは、変数colors
に入っているリストからランダムにデータ(色)をひとつ選んでいます。
以下の部分では、LEDの明るさを変えています。変数tree.brightness
は、ツリーに付いているLEDの明るさを表す数字が入っています。0から1の間の小数が使われ、デフォルトでは0.5が使われています。この数字を変えるとLEDの明るさが変化します。大きい数字ほど明るく、小さい数字ほど暗くなります。1にすると最大の明るさになり、0にすると光が消えます。
tree.brightness = random.random()
ここでは関数random.random()
を使って明るさを決めています。これは0と1の間の小数をランダムに作って返す関数です。
ロウソクの炎のように光らせる
最後に、ロウソクの炎がゆらめいているようにLEDを光らせます。ロウソクの炎がゆらめいているとき、その明るさの変化は「1/fゆらぎ」(f分の1ゆらぎ)という特徴を持っていることが知られています。英語では1/f fructuation(1-over-f fructuation)といいます。1/fゆらぎは、時間が経つにつれて明るくなったり暗くなったりをくり返すのですが、サインやコサインの曲線のように「きれいな」(smoothな)変化ではなく、もっとランダムっぽい変化になります。例えば以下のような変化です。
横軸が時間、縦軸が明るさを表しています。このように、時間が経つにつれて基本的には明るくなって暗くなるというのをくり返しますが、ノイズが入ってギザギザした形状をしながらのくり返しになります。こういうノイズのことを1/fノイズ(f分の1ノイズ)といいます。英語では1/f noise(1-over-f noise)とかpink noiseといいます。
1/fゆらぎに似たものを人工的に作るには以下のようにします。現在の明るさがx
だとして、
もしx
が0.5未満だったら:
もしx
が0.5以上だったら:
というふうに明るさを変化させ、これをくり返し続けます。この方法を使ってLEDの明るさを変化させているのがrandom-colors-flickers.pyです。以下の部分が上記の式を表しています。
if tree.brightness < 0.5:
newBrightness = tree.brightness + 2 * tree.brightness ** 2
else:
newBrightness = tree.brightness - 2 * (1 - tree.brightness) ** 2
Pythonで**
はべき乗を表していて、a ** 2
は「aの2乗」を意味します。
以下の部分では、明るさの数字が大きくなりすぎたり(1に近くなりすぎたり)小さくなりすぎたら(0に近くなりすぎたら)そこから強制的に大きく値を変化させています。上記の明るさ調節の方法では、明るさが1や0に近くなりすぎると、そこから値がなかなか変化しないことがあるので、そのための予防策です。
if newBrightness >= 0.95 or newBrightness <= 0.05:
tree.brightness = random.random()
else:
tree.brightness = newBrightness