M.C.P.C. (Mamesibori Creation Plus Communication)

印刷屋から五反田のWeb屋に転職したCLのブログです。

ピカリ館の単色LEDマトリクスパネルをRaspberry Piで光らす

akibaLEDピカリ館のLEDマトリクスパネルが2,380円で割とでかいのですが、

www.akiba-led.jp

これをRaspberry Piを使って光らす。(前回のArduinoでやったやつはこちら。)

使ったRaspberry Piは、Raspberry Pi B+、プログラミング環境はnode.jsです。ほら、node.jsにしておけば、サーバにしたりWebSocketで通信したりしやすいでしょ……

ハードウェア

f:id:C_L:20150823221733p:plain

注意ですが電源はしっかりアンペアの大きい5Vスイッチング電源を用意して、電源からRaspberry Piの5Vとパネルの5Vに分岐させるように。一応Raspberry PiをUSBにつないだときの5V端子からパネルにつないでもパネル1枚くらいなら光るけれども、パネル3枚全点灯でテストしたら、5V・4.6A位になったので、マジにやるなら30W級の5Vスイッチング電源を用意しましょう。パネル自体は全点灯時の消費電力は公称10Wで、パネル3枚の点灯時は5V/50Wのスイッチング電源を推奨しています。

仮配線にはこちらが便利。

akizukidenshi-ogp-injector.dtpwiki.jp

akizukidenshi-ogp-injector.dtpwiki.jp

akizukidenshi-ogp-injector.dtpwiki.jp

3.3V→5Vレベルシフトについて(後日談:このパネルではいらないことが判明)

あと、信号線がRaspberry Piから出る分は3.3V、LEDマトリクスパネルの仕様は5Vなので、途中に汎用ロジックICの74HC4050を入れて電圧を合わせてあげましょう(レベルシフタ)。ちょうど3.3Vの信号線が6本なので都合がよい。74HC4050は秋葉原に行ける人なら、鈴商とかマルツにあります。単一方向の電圧レベルシフタでいいのなら、74HC4050が便利です。(追記:鈴商の店舗が2015/11末に閉まると エルミタージュ秋葉原 – 電子部品パーツの老舗、「鈴商」が11月末に閉店)

akizukidenshi-ogp-injector.dtpwiki.jp

(後日談)パネルを入手して一度光らせてから、あらためて実装部品のラインを追っていったところ、コネクタのすぐ後に74HC245(Octal bus tranceiver; 3-state)が入っていることに気づきました。これはパネルを連結したときに信号線の電圧が下がっている場合電圧を上げてあげるためのものですが、結局低電圧→5Vへのレベルシフタとしても動作します。 データシートでは入力の電圧は最大Vccまでを入れても良いとなっているので、Raspberry Piの3.3VのGPIO出力をそのままパネルの入力に入れてみましたがちゃんと光るし、次のパネルの接続用端子の出力も5V近くまで上がっていましたので、正直74HC4050は不要でした。 74HC4050は、今回のパネルに使われていた74HC245などのバスバッファのような低電圧系→高電圧系の機能に加え、高電圧系の信号ピン出力から低電圧系の入力へ橋渡しすることができるので、単一方向レベルシフタとしては使いまわしが効く便利なICです。

ピカリ館単色LEDマトリクスパネル(HUB12規格)について

f:id:C_L:20150825013241p:plainf:id:C_L:20150825013252p:plain

このパネル、まずはA,B,LAT,CLK,DAT,OEが汎用ロジックICの74HC245(8チャンネルトランシーバ)を通ります。

コネクタABのラインが(74HC245を通った後)汎用ロジックICの74HC138(3 to 8 デコーダ)の入力につながり、出力側でソースドライバのFETを駆動するのに利用されています。また、DATラインとCLKLATが74HC595(シフトレジスタ)につながっていて、シンクドライバとして利用されています。入力データはDAT仕様書では/DATと書いてある)と負論理になっているのは、74HC595の端子が0Vになった時に、ソースドライバ側との電位差により吸い込みが発生し、LEDが点灯するからなのでした。

f:id:C_L:20150825185901p:plain

Raspberry Piで3線式シリアル通信(DAT,CLK,GND)をする場合、SPIインタフェースを利用できます。DATMOSI,CLKSCKに割り当てます。また、高級言語での実装を生かし多bitのデータ送信が一気にできる場合があります。今回利用したnode.jsのpi-spiは、node.jsの組み込みオブジェクトのBufferオブジェクトに構築したbit列をまとめて同期出力することが可能です。

パネルの表示シーケンスとしては、node.jsのpi-spiのコールバックにピン操作を固める都合上、

init {
    OE: L       // パネル消灯
}
loop {
    SPI転送(DATとCLKを使い128個データを転送)
    OE: L       // パネル消灯
    A  :L
    B  :L       // A=0, B=0 →ライン0を指定
    LAT:H       // ラッチ解除(シフトレジスタの出力ピン電圧反映)
    OE :H       // パネル点灯
    LAT:L       // ラッチ(シフトレジスタの出力ピン電圧固定)

    SPI転送(DATとCLKを使い128個データを転送)
    OE: L       // パネル消灯
    A  :H
    B  :L       // A=1, B=0 →ライン1を指定
    LAT:H       // ラッチ解除(シフトレジスタの出力ピン電圧反映)
    OE :H       // パネル点灯
    LAT:L       // ラッチ(シフトレジスタの出力ピン電圧固定)

    SPI転送(DATとCLKを使い128個データを転送)
    OE: L       // パネル消灯
    A  :L
    B  :H       // A=0, B=1 →ライン2を指定
    LAT:H       // ラッチ解除(シフトレジスタの出力ピン電圧反映)
    OE :H       // パネル点灯
    LAT:L       // ラッチ(シフトレジスタの出力ピン電圧固定)

    SPI転送(DATとCLKを使い128個データを転送)
    OE: L       // パネル消灯
    A  :H
    B  :H       // A=1, B=1 →ライン3を指定
    LAT:H       // ラッチ解除(シフトレジスタの出力ピン電圧反映)
    OE :H       // パネル点灯
    LAT:L       // ラッチ(シフトレジスタの出力ピン電圧固定)
}

こんな感じ。

ソフトウェア

OSとしては、Raspbian(wheezy)、プログラムは、node.jsで作りましたので、事前にraspi-configでSPIが使えるkernelドライバを有効にしておくこと、node.jsをインストールすること、npmでpi-spiとonoffをインストールすること、更にrootでの実行が必要となります。

node.jsのインストールは、OSのものはv0.6なので古すぎで、最低でもv0.10が欲しいところです。node.jsのサイトでは、v0.10がパッケージされて置いてあり、nodebrewとかnodeenvとかでインストールできるわけですが、せっかくなのでnode-armから入手できるv0.12.6(node_archive_armhf.deb)を入れます。

pi@raspberrypi ~ $ curl -LO http://node-arm.herokuapp.com/node_archive_armhf.deb
pi@raspberrypi ~ $ sudo dpkg -i node_archive_armhf.deb
(データベースを読み込んでいます ... 100%
(データベースを読み込んでいます ... 現在 77859 個のファイルとディレクトリがインストールされています。)
(node_archive_armhf.deb から) node を展開しています...
node (0.12.6-1) を設定しています ...
man-db のトリガを処理しています ...
pi@raspberrypi ~ $ node -v
v0.12.6
pi@raspberrypi ~ $

ライブラリのインストールはこんな感じ。

pi@raspberrypi ~ $ mkdir test
pi@raspberrypi ~/test $ cd $_
pi@raspberrypi ~/test $ npm install onoff pi-spi
\
> pi-spi@1.0.0 install /home/pi/node_modules/pi-spi
> node-gyp rebuild

make: Entering directory '/home/pi/node_modules/pi-spi/build'
  CXX(target) Release/obj.target/spi_binding/spi_binding.o
  SOLINK_MODULE(target) Release/obj.target/spi_binding.node
  COPY Release/spi_binding.node
make: Leaving directory '/home/pi/node_modules/pi-spi/build'

> epoll@0.1.13 install /home/pi/node_modules/onoff/node_modules/epoll
> node-gyp rebuild

make: Entering directory '/home/pi/node_modules/onoff/node_modules/epoll/build'
  CXX(target) Release/obj.target/epoll/src/epoll.o
  SOLINK_MODULE(target) Release/obj.target/epoll.node
  COPY Release/epoll.node
make: Leaving directory '/home/pi/node_modules/onoff/node_modules/epoll/build'
pi-spi@1.0.0 ../node_modules/pi-spi
└── nan@1.9.0

onoff@1.0.2 ../node_modules/onoff
└── epoll@0.1.13 (bindings@1.2.1, nan@1.8.4)
pi@raspberrypi ~/test $ 

プログラムはこちら。

gist.github.com

www.youtube.com

んで、node.jsなんですが、非同期処理・シングルスレッドがウリのnode.jsで同期処理やるためにコールバックで自分自身を再帰呼び出しするように作ってみましたが、Raspberry PiのOS自身の処理とかネットワークIO処理とかに巻き込まれループが一定の間隔で動くわけがなく、4ライン毎のダイナミック点灯の間隔が一定にならないのでした。