blinking-led-on-reterminal

reTerminal で L チカしてみた

先日 elchika AWARD 2022 | elchika を受賞しました。賞品として reTerminal をいただいたので、本格的な製作に使う前にとりあえずセットアップと L チカ1をやってみました。

ソフトウェアのアップデートは Skip する

elchika 運営元のエイミーさんから reTerminal が届く前に、予習として使い方の動画を見ました。reTerminal の開発元である Seeed 社の松岡さんによる 「reTerminal キーポイント解説」という動画です。

松岡さんのお話は要点がまとまっていて良かったです。Raspberry Pi 4 Model B と同じ部分と違う部分や、Raspberry Pi 4 互換のピンヘッダに関する注意事項などが簡潔にまとまっています。I2C バスにいくつかの内蔵機器が接続されているので、外部に他の機器を接続する場合はアドレスが重複しないようにしましょう、という話は聞いておかないと後で悩みそうです。

reTerminal を使い始める時の特記すべき注意事項としては、初回起動時に出てくるセットアップウィザードで、ソフトウェアをアップデートするか聞かれたら必ず「Skip」を選択する必要がある点です。ここでアップデートしてしまうと LCD が表示されなくなってしまうのだそうです。この記事を書いている時点で、Seeed 社の Wiki ページ「Getting Started with reTerminal - Seeed Wiki」にも「Skip」をせよという指示がありました。従っておくのがよさそうです。

ただ、ソフトウェアをアップデートせず使う(特に、インターネットに接続された状態で使う)のはセキュリティ上良くないと思います。ということで、先の Wiki ページからリンクされている「How to upgrade Raspberry Pi OS and the installed packages」を読んで、後でアップデートすると良いでしょう。

L チカ

3 User Programmable LEDs によれば /sys/class/leds/usr_led0/brightness に 0~255 の数値を書き込むとその明るさで LED0 が光るようです。同様に LED1、LED2 も操作できるようです。ということでやってみました。

reTerminalでLチカしてみた - YouTube

ドキュメントには "You can enter values from 1 - 255 to adjust the brightness levels" と書いてあるので明るさを調整できると思ったのですが、試したところ光るか消えるかの 2 値でしか制御できませんでした。

動画では次のようなシェルスクリプトで光らせています。

for led in 0 1 2; do for i in $(seq 1 255) 0; do echo $i | sudo tee /sys/class/leds/usr_led${led}/brightness; done; done

原理的には echo $i > /sys/class/leds/usr_led${led}/brightness ということなんですけども、リダイレクトする代わりにパイプで tee コマンドに繋げています。これは何故かというと、brightness というファイルは root 権限でしか書き込めないからです。sudo echo $i > ... というふうに sudo を付ければ良いと思うかもしれませんが、それでは上手く行かないのです。echo 自体は root 権限で動きますが、リダイレクトは一般ユーザー権限で処理されるからですね。

何らかのプログラムの中から自動操作する場合は /sys/class/leds/usr_led*/brightness を書き込みモードで開き、0~255 を文字列として書き込めば良いはずです。普通はそれで満足ですが、ここでは一歩踏み込んだ LED の制御をしてみたいと思います。

L チカ信号の解析

sysfs で露出したファイルに輝度を書き込むというのはなんとも手軽なので、普通はそのやり方を使うのが良いと思います。が、何となくもっと低レイヤの制御をしたくなり、色々調べてみました。

Getting Started with reTerminal - Seeed Wiki の Resources にある回路図「reTerminal Schematics v1.6」によれば、ユーザー LED は PCA9554A という I/O エクスパンダに繋がっているようです。PCA9554A は I2C バスに接続されていて、I2C から指令を受けて 8 ビットのパラレル信号を出力してくれるようです。IO_0~IO_3 にはスイッチが、IO_4~IO_6 には LED が、IO_7 にはブザーが接続されています。

reTerminal schematic v1.6 IO expander
I/O エクスパンダ周辺の回路

上図は先ほどの回路図から I/O エクスパンダとその周辺を抜粋したものです。これによれば I/O エクスパンダには I2C アドレス 0x38 が割り当てられているようです。Gettig Started with reTerminal ページの先頭にあるブロック図には 0x20 I/O Expander MCP23008 とあって、ちょっと情報が古いですね。reTerminal の製造時期によって搭載されている I/O エキスパンダのチップ、および割り当てられているアドレスが異なるようです。手元の reTerminal にどちらのチップが搭載されているかは、i2cdetect -y 1 コマンドの実行結果を見て 0x20 と 0x38 のどちらが認識されるかで判断できると思います。

PCA9554A にどんな信号を送って LED の輝度を変えているのかを調べてみます。I2C バスは Raspberry Pi ヘッダとして外部に露出しているので、そこにロジックアナライザを接続して通信を解析します。検証用に次のスクリプトを用意しました。

#!/bin/sh
echo 1 > /sys/class/leds/usr_led0/brightness; sleep 1
echo 0 > /sys/class/leds/usr_led0/brightness; sleep 1

echo 1 > /sys/class/leds/usr_led1/brightness; sleep 0.5
echo 1 > /sys/class/leds/usr_led2/brightness; sleep 0.5
echo 0 > /sys/class/leds/usr_led1/brightness; sleep 0.5
echo 0 > /sys/class/leds/usr_led2/brightness

このスクリプトを実行し、ロジックアナライザで観測しました。観測された波形の 1 つは次のようになっていました。

reTerminalのLEDを点滅させるときにI2Cバス上のIOエクスパンダに対して出る書き込み信号の例
LED 点滅時の I2C 信号

0x38 というアドレスを持つ機器に対して 0x01 0x7F という 2 バイトの書き込みを行っています。0x38 はまさに I/O エクスパンダ PCA9554A のアドレスです。PCA9554A のデータシートを見てみると、最初の 1 バイト(0x01)はレジスタアドレスを指定する部分、次の 1 バイト(0x7F)はそのレジスタへ書き込む値だそうです。今回は出力レジスタに対して 0x7F を書いています。出力レジスタは PCA9554A の出力端子を表しており、ここに書き込んだ値が 8 つの端子から電圧として出力されます。

LED は IO_4~IO_6 ですから、0x7F のうちの 0x7 が該当します。ロジックアナライザで観測された波形のうち、アドレス 0x38 のレジスタ 0x01 に対する書き込みデータは全部で次の 6 つでした。

順序 書き込みデータ ビット 6:4
1 0x6F 110
2 0x7F 111
3 0x5F 101
4 0x1F 001
5 0x3F 011
6 0x7F 111

回路図によれば LED の点灯回路は負論理になっており、0 で点灯、1 で消灯します。したがって 110 は IO_4 だけ点灯、111 は全て消灯です。この表をじっくり見ると、検証スクリプトで書き込んだ値が素直に出力されていることが分かりました。

試しに 1 ではなく 127 を brightness に書き込む実験もしてみましたが、何も差がありませんでした。

I2C で L チカ

brightness ファイルに値を書き込むのではなく、I2C バスに信号を直接出すのでも制御できるでしょうか。

pigpio ライブラリの i2c_open を使った制御は出来ませんでした。この関数を呼び出したところエラーになりました。おそらく、OS 上で既に PCA9554A が使用中となっていて、pigpio が制御を奪えなかったのだと思います。i2cset コマンドでも試しましたが "Device or resource busy" と言われてしまいました。

であれば reTerminal の外部から I2C バスに信号を流してやろうということで、Analog Discovery 2 を使って I2C 信号を発生させてみました。その信号を 40 ピンの Raspberry Pi 互換ヘッダの SDA/SCL に流し込みます。

reTerminalのLEDを外部I2C端子から制御 - YouTube

目論見は当たり、I2C 信号によって LED を制御できました。この動画では ON と OFF を等間隔に高速に繰り返しています。繰り返し速度がちょっと遅くて点滅が見えてしまっていますが、なんとなく半分くらいの輝度で光らせることが出来たのではないでしょうか?

ときどき誤動作して STA が光ったりブザーが鳴ったりするのが面白いですね。STA もブザーも PCA9554A に接続されているため、それらが USR LED につられて誤動作するのは何となく理解できますね。きっと I2C 信号がなまったりして、ビットの位置がちょっとずれるんだと思います。

まとめ

  • reTerminal を elchika AWARD 2022 の賞品としていただきました。elchika さんありがとうございます!
  • reTerminal の内蔵 LED を brightness ファイルに値を書く方法で光らせてみました。輝度の調整は出来なさそうですが、光らせることはできました。
  • 40 ピン Raspberry Pi ヘッダに I2C 信号を流すことで外部から LED を制御することに成功しました。

  • [1]: LED を点滅させること

作成:2022-11-30 16:36:33

最終更新:2022-11-30 16:36:33