門外漢、I2Cで55個のLEDを光らせる
I2Cという言葉、Raspberry Pi関連の調べ物をしていると時折見かける言葉でした。センサーを扱うときに使うじゃないかな多分。このようにI2Cのことを全くわからない門外漢がその持ち前の野蛮さでI2Cをいじってみました。
購入
始まりは先日注文したRaspberry Pi Zeroが届いたところから。購入したところはたまたま在庫があったPimonori。本体+各種アダプタセット、ケース、出来心で追加した55個のLEDを備えたScroll pHATと送料で£22.33でした。決済時に1割引されていました。一週間でイギリスから到着。
セットアップ
今回はNOOBSを使わずmicro SDにRaspbian Jessie Liteのイメージを焼いて、HDMIでTVに繋ぎ、一つしか使えないmicro USBにはUSBハブ。そこにキーボードとWifiレシーバーを繋いでセットアップしました。ヘッドレスで行う方法もあるみたいですが、機材が部屋に転がっていたのでオーソドックスな方法で行いました。
ハンダ付け
セットについてきたGPIOヘッダーをRaspberry Pi Zeroにハンダ付けします。同じくScroll pHATにもGPIOヘッダーをハンダ付けします。ハンダ付けはなんとかやりましたね。見た目が相当アレですけど。
I2C
I2Cを扱うためにraspi-config
のAdvanced Options
からI2C
を選択して有効化します。再起動の前にi2cdetect
が使えるようにパッケージをインストールします。
sudo apt-get install i2c-tools
sudo reboot
そしてGPIOで本体とScroll pHATを合体させて認識しているか確認します。
pi@raspizero:~ $ i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: 60 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
Scroll pHATのアドレスは0x60
であることがわかります。わかったけどどうすればいいのか。
写経
Pimonoriが作成、公開しているScroll pHATのライブラリとサンプルプログラムを動かしたりソースを読んでも理解が進まないので、一部をNode.jsに書き直してxとyの座標を指定して光らせるようにしました。
var sleep = require('sleep');
var i2c = require('i2c-bus');
var i2c1 = i2c.openSync(1);
const I2C_ADDR = 0x60;
const CMD_SET_MODE = 0x00;
const CMD_SET_BRIGHTNESS = 0x19;
const MODE_5X11 = 0b00000011;
var buffer = new Buffer(12);
buffer.fill(0);
function update() {
console.log(buffer);
try {
i2c1.writeI2cBlockSync(I2C_ADDR, 0x01, buffer.byteLength, buffer);
} catch (e) {
console.log(e);
}
}
function set_mode() {
i2c1.writeByteSync(I2C_ADDR, CMD_SET_MODE, MODE_5X11);
}
function set_brightness(brightness) {
i2c1.writeByteSync(I2C_ADDR, CMD_SET_BRIGHTNESS, brightness);
}
function set_pixel(x, y, val) {
if (val) {
buffer[x] |= (1 << y);
} else {
buffer[x] &= ~(1 << y);
}
}
function clear() {
buffer = new Buffer(12);
buffer.fill(0);
update();
}
function chika(val) {
for (var x = 0; x < 11; x++) {
for (var y = 0; y < 5; y++) {
set_pixel(x, y, val);
update();
sleep.usleep(30000);
}
}
}
set_mode();
set_brightness(2);
chika(1);
chika(0);
// clear();
定数のI2C_ADDR
はi2cdetect
で取得した値なのでいいとして、CMD_SET_MODE
、CMD_SET_BRIGHTNESS
、MODE_5X11
の値は何なんだ。どこから来たんだ? という疑問はデータシートに答えが載っていました。ふーむ、ビットを束ねてライブラリ経由で送ればいいわけだな。という雑な理解を得られたので、Bufferの中身をコンソールに表示しつつLEDをひたすらピカピカさせました。
計算機
2進数、10進数、16進数の変換がパパッとできないので参るわけですが、OSXにデフォルトで入っている計算機のプログラマモード(⌘3
)がとても重宝しました。
まとめ
Pythonのコードをそのまま移植してNode.jsのBufferであるところをArrayにしていてエラーをいただいたり、データシートの読み方が全くわからずデータの桁数間違えたりして前途は暗かったのですが、雑な理解ながら最初の壁を乗り越えると次もI2Cで何かできるかも? とAmazonでセンサー探していたりするから不思議なもんです。
何となく感づいていましたが、いろいろ検索するとRaspberry PiはPythonが一級市民のようなので、Python人間になった方がいいのかもしれないなと思いました。
あと「Raspberry Piで実践! 中学校の数学が怪しい奴でもわかるI2C」なんて本があったりしたら飛びつきますね。