電子ペーパーを使った情報表示装置


はじめに

天気予報や為替情報などを毎日表示する情報表示装置を作成しました.画面更新時以外は電力が不要な電子ペーパーを使いESP32を無線通信時以外はスリープさせることで,乾電池で動作してどこにでも設置できるようにしました.

使用中の装置
電池の残量が少ない場合
表示例
ケースに入れる前
ケースに入れた後

ハードウェア

2.7インチの赤と黒2色を表示できる電子ペーパーを使いました.この電子ペーパーにはDC-DCコンバータ用のFETやコイルが実装された専用のコントロール基板がありますが,今回は使用しませんでした.その代わりにHW-520という+12Vと-12Vを同時に出力できるDC-DCモジュールを改造して+16Vと-16Vを出力するようにして直接電子ペーパーに電圧を与えました.そのため電子ペーパー内蔵のDC-DC駆動機能は無効にしています.HW-520ではPH01というDC-DC用のICが使われていますが,これはTPS61040DBVRと互換性があるようだったので,そのデータシートを参考にして改造しました.具体的には,Vout=1.233V * (1 + R1/R2)と出力電圧は計算できて,R1は220kΩ(224)でR2は24kΩ(243)となっていたので,R1=1MΩおよびR2=82kΩとしました.その結果2.4Vを入力した場合に+16.21と-15.82Vが出力されて,無負荷時の消費電流は19.7mAとなりました.改造前は2.4V入力で+12.48Vと-12.07Vで無負荷時消費電流は11.32mAでした.電子ペーパーは動作時だけ電源供給が必要なので,DC-DCモジュールの電源はESP32のIOピン(1ポートあたり最大40mA)から供給しています.この電子ペーパーには3-wire SPIモードと4-wire SPIモードがありますが,3-wireは9ビットの転送になるので,Arduinoで扱いやすい4-wire SPIモードを使いました.

電池で動作させるため,一時的な消費電流の増加に対応するため1000uFという大きめのコンデンサを付けました. それにより電池を入れ直してもESP32がリセットされないため,書き込み時などはコンデンサを放電させて確実にリセットする必要があります. ESP32の動作電圧は2.2-3.6Vとなっていますが,2.5Vを切ると動作しませんでした. これはBrown out detectorが2.5Vに設定されているためで,多少電圧が下がっても動作が不安定にならないようにArduino中ではこれを無効にしています. 電源ON時に電圧を測定して2.7V未満であれば電力不足の画面を表示して永久にdeep sleepに入ります. 電源電圧の測定については,電圧検出用の回路は追加せずに後述する内部電圧検出用の隠し関数を使用します. 測定されたバッテリー電圧は画面右上の16x16の領域に下2桁を表示します.

上に動作中の写真がありますが,赤色のコントラストが低いので描画パラメータをチューニングする必要があるかもしれません.ディープスリープ時の消費電流は5.3uAでした.新品の単三アルカリ電池2本で3ヵ月程動かしていますが,電圧は3.33Vから3.05Vまで低下しました.
(2021-11-21追加) 1.5年間連続して動かしていますが,現在の電圧は2.94Vでいつになったら動作停止する(2.7V以下になる)のか分かりません.(2021-12-05追加)とうとう停止しましたが,結局19ヶ月間電池がもちました.

回路図

ESP32の隠し関数(rom_phy_get_vdd33)による電源電圧の測定

(2022-02-27更新) ESP8266ではESP.getVcc()という関数により電源電圧を測定することができますが,ESP32には同様な関数はドキュメントには存在しません. しかしながら,rom_phy_get_vdd33()という似たような機能を持つ隠し関数が存在します. ただしこの関数はBluetoothかWiFiをオンにした状態でしか使用することができず,また電圧値を直接出力しないので出力値を電圧に変換する必要があります. 関数の出力値と実際の電圧を測定すると次のグラフのようになりました.

rom_phy_get_vdd33()関数の値と実際の電圧

きれいな線形の関係になっているため,以下のような電源電圧を返す関数を用意しました.

extern "C" int rom_phy_get_vdd33();
#define ADJUST 1.00f
float getVoltage() {
  btStart();
  int v = 0;
  for (int i = 0; i < 20; i++) v += rom_phy_get_vdd33();
  v /= 20;
  btStop();
  const float vdd =  (0.0005045f * v + 0.3368f) * ADJUST;
  return vdd;
}

使用するESP32に依存して関数の返す値がやや異なるので,ADJUSTという定数を設定して補正を行います.

この隠し関数は挙動が不明確で,btStart()を実行してから直後に関数を実行した場合と1秒ほど待ってから実行した場合では結果が大きく異なります. さらにこの関数を連続して何度も呼び出すと結果が変わったりします. とりあえず,BluetoothやWiFiを有効にしてすぐに一度だけ呼び出した場合の結果は比較的安定しているようです.

ソフトウエア

自宅のLinuxサーバー(httpサーバー)が毎日5:00にこの装置で出力するための画像を用意するので,それをESP32で取得して表示します.画像は赤色部分と黒色部分をそれぞれPBMファイルで用意します.PBMは非圧縮の画像ファイルフォーマットですが,この電子ペーパーのプロトコルに近いためほとんど変換せずに描画できます.Linuxサーバー側ではPythonを使い,Pillowライブラリで描画しています(スクリプト).

この装置を使うには,ESP32で使うアクセスポイントのSSIDや画像が置いてあるURL等の情報を設定する必要がありますが,ソースファイルに直書きすると設定を変更するたびにコンパイルして書き込む必要があり手間がかかります.そこでESP32に内蔵されたホールセンサーを使い,磁石を十分近づけて起動するとSoftAPモードでWWWサーバーを立ち上げるようにして,タブレットなどからアクセスすることで容易に設定を変更できるようにしました.

旧バージョンのソフトウェア

現在のソフトウェアは二世代目のバージョンで,最初に作成したものはスタンドアローンで動作し,ESP32で直接必要な情報を外部サイトからスクレーピングして表示するものでした.別途Linuxサーバーを必要とせずこの装置自体で完結している点は素晴らしいのですが,フォントを内蔵する必要があり,一部のSSL通信にESP32のライブラリが対応しておらず,大きいHTMLをスクレーピングするとメモリが不足し,XMLやJSONを処理するのが大変で,多くの処理をする必要があるため電池の消耗が大きくなる,など欠点が多いためあきらめました.なお表示する内容を変えたい場合や,情報取得元のサーバーの仕様が変わった場合はソフトウェアの修正が必要になりますが,その都度ファームウェアを書き換えるのは大変なので,スクレーピングして情報を取り出して画面にレンダリングするためのスタックベースの独自言語を用意するという大掛かりなことを行いました.


[戻る]
2020-05 制作
2020-08-23 ページ作成
T. Nakagawa