OLEDにセンサ情報を表示する

5 min read読了の目安(約4600字

https://zenn.dev/false/articles/0002-9d350ab7a2fc904aa5bb
の続き。

OLED にセンサ情報を表示する

ここまでで、CO₂濃度や気温、湿度を一分毎にデータベースに記録して、グラフを作成する機能ができました。
こうなると、リアルタイムの表示も欲しくなります。

そんなとき、こんなページに辿り着きました。

https://zenn.dev/kotaproj/books/raspberrypi-tips/viewer/250_kiso_ssd1306

4pinでブレッドボードに刺すだけで、I²Cで画面を表示することができます。欲しかったのはこれではないですか?

https://akizukidenshi.com/catalog/g/gP-12031/

色は、白と青が選べるようです。
また、RGBで出力できる商品もあるようでした。

https://akizukidenshi.com/catalog/g/gP-14435/

こちらは I²C ではなく SPI になるようです。画面も少し小さくなります。

今回は、カラーは不要と判断して単色のものにしました。
また部品一個だけで送料を払うのが嫌だったので、amazonで以下を購入しました。

https://amzn.to/3oPD6fD

結線

I²C の結線に必要なのは前回の BME280 でブレッドボードに接続済みなので、今回はブレッドボード内の配線のみです。

Pi OLED
1(3.3v) VCC
3(SDA.1) SDA
5(SCL.1) SCL
6(0v) GND

が、OLED は同じ画面を表示し続けると焼き付きが起きると聞くのと、人がいないときにずっと画面を表示し続けるのももったいないので、スイッチを追加することにします。
とりあえず単なるプッシュスイッチを想定していますが、将来的には赤外線人感センサに変えたいと思います。

https://akizukidenshi.com/catalog/g/gM-09002/
Pi スイッチ センサ
4(5v) - DC-Input
7(GPIO.7) 1 Vout
6(0v) 2 GND


配線図

※ 結線、生きたままの状態でやるとすぐに I²C のエラーが出ます。ちゃんと電源を off にしてやった方が良さそうです。

I²C アドレス

接続した上で、i2cdetect するとアドレスは 0x3c であることがわかりました。

% sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- 76 --

秋月で買っていないですが、秋月の商品ページを見ると 0x78 または 0x7a と書いてあります。
調べたところ、I²Cのアドレスには 7bit 表記と 8bit 表記があるらしく、8bit 表記の 0x78 は 7bit 表記で 0x3c になるらしいです。
最上位ビットではなく最下位ビットに0を足すってなかなか珍しい気がします。

https://bokunimo.net/ichigojam/i2c.html

ちなみに、以下の抵抗を付け替えればアドレスが変えられるので、2台同時運用も可能ですが、こんな小さな抵抗を付け替えるスキルがありません。

GPIO

プッシュスイッチや赤外線センサの入力には GPIO を使います。
Raspberry Pi で GPIO を使うにはいろいろなパッケージやモジュールがあるようですが、今回は gpiozero を使うことにしました。
Raspbian に標準でインストールされているし、他のデーモン(gpiodとか)を動かす必要もないようです。
gpiozero で GPIO のポートを指定するには、gpio readll で表示される BCM の番号を指定します。

Pin Numbering に詳しく書いてありますが、4 と書く代わりに "4", "GPIO4", "BCM4", "BOARD7", "WPI7" 等と書けるようです。

gpiozero は複数の Pin Factory から選択できるようなのですが、何も指定しないと RPi.GPIO になりました。

OLED

必要なモジュールは adafruit-circuitpython-ssd1306pillow
日本語を描画するためには日本語フォントが、pillow をインストールするには libjpeg が必要です。

sudo apt install fonts-ipafont
suto apt install libjpeg9

ipafont だと、CO₂の「₂」が出ませんでした。fonts-takao や fonts-noto-cjk を試してみましたが状況変わらず。
試しに mac でヒラギノフォントを使うと出ました.
どなたか、Raspberry Pi で日本語と「₂」が同時に出せるフォントがあったら教えてください。

実装

以下のポリシーで実装します。

  • プッシュスイッチ(人感センサ)がonになったとき
    • 画面表示フラグが False だったら画面を表示してフラグを True にする
  • プッシュスイッチ(人感センサ)がoffになったとき
    • 最終時刻を更新
  • 1分に一度のデータ更新時
    • 描画用 Image を更新
    • 画面表示フラグが True で、スイッチoff時刻から30秒以上経っていたら画面を消し、フラグを False にする
    • 画面表示フラグが True ならば画面を表示
  • 前回 I²C のアドレスをハードコードしてしまったので、ini ファイルに追い出す
    • BME280 の I²C アドレス
    • OLED の I²C アドレス
    • スイッチ/センサの pin 番号
    • 各種センサの有無はコマンドラインオプションにしているけど、iniの方が使いやすいかな?

ソースは、https://github.com/false-git/power-consumption33fdb2... のあたり。ディスプレイ関連のコードは oled_ssd1306.py です。

最終的に以下のようになりました。


結論: 0.96インチは小さすぎて、老眼には何も見えない!!

追記: Raspbian の font について

今回のソースでは参考にした記事に従って /usr/share/fonts/truetype/fonts-japanese-gothic.ttf を指定したのですが、これは /etc/alternatives/fonts-japanese-gothic.ttf へのシンボリックリンクになっています。
fonts-ipafont だけをインストールした状態では、/etc/alternatives/fonts-japanese-gothic.ttf/usr/share/fonts/opentype/ipafont-gothic/ipag.ttf へのリンクになっていますが、もし fonts-takao をインストールすると /usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf へのリンクに変わってしまいます。
そして、takao フォントは固定幅フォントではないので、期待した出力が得られなくなるかも知れません。
混乱しないためには、今回のような用途では直接 /usr/share/fonts/opentype/ipafont-gothic/ipag.ttf を指定した方が良かったかも。

この辺の仕組みについては、man update-alternatives するとわかります。

続きはこちら

https://zenn.dev/false/articles/0004-26cb248aa844e6e31e1a