無線化した電書ページめくり機に、バッテリーモニターを付けてみました
無線マイコンモジュールのESP32-WROOM-32Eを使った電子書籍用のページめくり機を8月に作って、コードと回路図も公開しました。この1ヶ月と少し使っていて、画面フリック以外のページめくり手段があるのはいいものだ、と再確認できました。電池は1回だけ切れて充電しましたが、結構長くもっています。
ところで、前の記事ではヘッダファイルをいじってデバイス名と製造者を設定して悦に入っていたのですが、お恥ずかしいことに、この機能がライブラリに元々組み込まれていることに気が付きました。
しかしまぁ、これの修正だけでアップデートすることも無いかなと思いつつ、第3引数の電池残量が気になりました。初期化のところは起動時の残量を接続先に送る機能ですが、操作時にも電池残量をモニターして送ることができるようです。それで、この機能も付けたくなって検討しました。
まず、ESP32のADCを使ったことが無かったので先達のレポートを検索してみたところ、素の特性では入力電圧と出力値の関係(傾き・切片・直線性、まとめてリニアリティ)が相当劣悪らしいと分かりました。具体的には、入力アッテネータの設定ごとのグラフが載っているラジオペンチさんのレポートに端的に書かれています。
今回はバッテリーモニターをしたいのに、ESP32の電源電圧とADC出力値の関係について書かれたものが見当たらなかったので、ざっと実験してみた結果が次のグラフです:

ひいき目に見て0.3-2.2Vの範囲は直線だとみなして使えないこともないのかな、というところですが、正直なところそのまま使いたいとは思えない結果でした。 さらに調べていくと、ESP32は製造時にeFuseで校正値が書き込まれていること、オフセットや傾きの個体差が大きいので校正値を使った方がよく、(少しややこしいけれど)それほど難しくはないというQiitaの解説記事が目に入ったので、とりあえず試してみた結果が次のグラフです:

ここでリニアはy=xの理想です。直線補間式というのはQiitaの解説記事にある傾きcoeff_aと切片coeff_bを使った一次方程式のことで、これらの値の使い方についてはAPIのソースまで調べた記事を参考にしたのですが、今回APIで得られた値は明らかに直線補間式の結果よりも精度が良くなっています。オフセットが数10mV残っていますが、無視していいでしょう。
ここであらためてAPIリファレンスを見るとルックアップテーブルを使って補正するようなことがサラッと書かれていて、その効果が出ているのでしょうが、これ以上の詳細は分かりませんでした。 続いて、この校正出力と電源電圧変動の関係を確認した結果が次のグラフです:

APIによる校正出力はVdd=3.3Vで最適化されているものの、電源電圧変動までは十分にカバーできていません。といいつつ、0.2V〜2.2Vの範囲なら絶対値も信用してよさそうです(n=1ですが)。 以上の結果から、バッテリーモニターをするには動作電圧範囲Vdd=3.0〜3.6Vを反映したADC入力電圧が0.2〜2.2Vの範囲にくればいいので、単純に抵抗で2分圧してADCに入れることにします(なお、今回は三端子レギュレータを通しているのでVdd上限は3.3V)。分圧抵抗は動作中ずっと電源にぶら下がるので消費電流を減らすために大きめにしたいところ、ADC入力インピーダンスは10MΩ以上あるらしいので、100kΩ+100kΩにしました。既に組み上げたモノに後付けしたので不細工ですが、次のように抵抗を取り付けています:

回路図は次の通り:

回路的には分圧抵抗が付いただけです。あと、コネクタにマークを付けています。 さて動作確認… してみたところ、Androidの標準Bluetoothキーボードドライバにはバッテリーモニターの機能が無いみたいですね。ヘッドホンだと電池マークが出る機種でも、キーボードでは見えませんでした。
そこでBlueBattというアプリで、Vddを3.0Vギリギリまで下げてモニターしたところ、コンソールで得られているのと同じ値がBLE経由で送られていることが確かめられました:

(冒頭の図の再掲です。もちろん上下限±αまで確認済。) しかし、わざわざアプリを立ち上げないとならないのでは読書中に電池が切れかけても分かりません。そこで、Vddが3.0Vを切ったら電源ONやボタン押しの時にLEDを長点滅して10秒ほど動かなくなるように仕込みました。1ページを10秒で読むことは滅多にないので、ギリギリまで使えるだろうという仕様です。
その他、型宣言がいい加減だったのを直すなどリファクタリングをした上で、コードと回路図をアップしておきました。(また、最初の方に書いた理由でetw.hは削除しました。)
ここで、Arduino IDEが2.0にアップデートしてスケッチブックが使いやすくなったので、メインはグローバル宣言(でいいのかな)とsetup()とloop()だけにして、バッテリー周りをサブにファイル分割しています。これ、IDE上では見通しが良くなったのですが、素人のファイル管理上は少々面倒かもと思い、今後の運用はまた考えます。 抵抗を2つ追加した最終的なBOMは次の通りで、合計1229円でした。電線・ピンヘッダ・ハンダ・ラベルはカウントしていません:
次に電池が切れるのが楽しみです。以上、何かの参考になれば幸いです。
パドラッパ from MacBook Air (2017)
しかしまぁ、これの修正だけでアップデートすることも無いかなと思いつつ、第3引数の電池残量が気になりました。初期化のところは起動時の残量を接続先に送る機能ですが、操作時にも電池残量をモニターして送ることができるようです。それで、この機能も付けたくなって検討しました。

まず、ESP32のADCを使ったことが無かったので先達のレポートを検索してみたところ、素の特性では入力電圧と出力値の関係(傾き・切片・直線性、まとめてリニアリティ)が相当劣悪らしいと分かりました。具体的には、入力アッテネータの設定ごとのグラフが載っているラジオペンチさんのレポートに端的に書かれています。
今回はバッテリーモニターをしたいのに、ESP32の電源電圧とADC出力値の関係について書かれたものが見当たらなかったので、ざっと実験してみた結果が次のグラフです:

ひいき目に見て0.3-2.2Vの範囲は直線だとみなして使えないこともないのかな、というところですが、正直なところそのまま使いたいとは思えない結果でした。 さらに調べていくと、ESP32は製造時にeFuseで校正値が書き込まれていること、オフセットや傾きの個体差が大きいので校正値を使った方がよく、(少しややこしいけれど)それほど難しくはないというQiitaの解説記事が目に入ったので、とりあえず試してみた結果が次のグラフです:

ここでリニアはy=xの理想です。直線補間式というのはQiitaの解説記事にある傾きcoeff_aと切片coeff_bを使った一次方程式のことで、これらの値の使い方についてはAPIのソースまで調べた記事を参考にしたのですが、今回APIで得られた値は明らかに直線補間式の結果よりも精度が良くなっています。オフセットが数10mV残っていますが、無視していいでしょう。
ここであらためてAPIリファレンスを見るとルックアップテーブルを使って補正するようなことがサラッと書かれていて、その効果が出ているのでしょうが、これ以上の詳細は分かりませんでした。 続いて、この校正出力と電源電圧変動の関係を確認した結果が次のグラフです:

APIによる校正出力はVdd=3.3Vで最適化されているものの、電源電圧変動までは十分にカバーできていません。といいつつ、0.2V〜2.2Vの範囲なら絶対値も信用してよさそうです(n=1ですが)。 以上の結果から、バッテリーモニターをするには動作電圧範囲Vdd=3.0〜3.6Vを反映したADC入力電圧が0.2〜2.2Vの範囲にくればいいので、単純に抵抗で2分圧してADCに入れることにします(なお、今回は三端子レギュレータを通しているのでVdd上限は3.3V)。分圧抵抗は動作中ずっと電源にぶら下がるので消費電流を減らすために大きめにしたいところ、ADC入力インピーダンスは10MΩ以上あるらしいので、100kΩ+100kΩにしました。既に組み上げたモノに後付けしたので不細工ですが、次のように抵抗を取り付けています:

回路図は次の通り:

回路的には分圧抵抗が付いただけです。あと、コネクタにマークを付けています。 さて動作確認… してみたところ、Androidの標準Bluetoothキーボードドライバにはバッテリーモニターの機能が無いみたいですね。ヘッドホンだと電池マークが出る機種でも、キーボードでは見えませんでした。
そこでBlueBattというアプリで、Vddを3.0Vギリギリまで下げてモニターしたところ、コンソールで得られているのと同じ値がBLE経由で送られていることが確かめられました:

(冒頭の図の再掲です。もちろん上下限±αまで確認済。) しかし、わざわざアプリを立ち上げないとならないのでは読書中に電池が切れかけても分かりません。そこで、Vddが3.0Vを切ったら電源ONやボタン押しの時にLEDを長点滅して10秒ほど動かなくなるように仕込みました。1ページを10秒で読むことは滅多にないので、ギリギリまで使えるだろうという仕様です。
その他、型宣言がいい加減だったのを直すなどリファクタリングをした上で、コードと回路図をアップしておきました。(また、最初の方に書いた理由でetw.hは削除しました。)
ここで、Arduino IDEが2.0にアップデートしてスケッチブックが使いやすくなったので、メインはグローバル宣言(でいいのかな)とsetup()とloop()だけにして、バッテリー周りをサブにファイル分割しています。これ、IDE上では見通しが良くなったのですが、素人のファイル管理上は少々面倒かもと思い、今後の運用はまた考えます。 抵抗を2つ追加した最終的なBOMは次の通りで、合計1229円でした。電線・ピンヘッダ・ハンダ・ラベルはカウントしていません:
item | detail | price | pcs | subtotal |
---|---|---|---|---|
BLE module | ESP32-WROOM-32E | 360 | 1 | 360 |
Li-ION Batt. | 1200mAh | 210 | 1 | 210 |
Charge module | TP4056 | 26 | 1 | 26 |
Regulator | NJM2845DL1-33 | 50 | 1 | 50 |
LED | OSG8HA3Z74A | 10 | 1 | 10 |
Substrate | D-type NTH | 45 | 2 | 90 |
Silent SW | TS8855SG-P2 | 22 | 4 | 88 |
Compact SW | TVBP06-B043CW-B | 10 | 2 | 20 |
Slide SW 1x2 | SS-12D00-G5 | 20 | 1 | 20 |
Slide SW 2x2 | SS-22SDP2 | 90 | 1 | 90 |
Resistor | 1/6W, 2.2kx1, 10kx2, 100kx2 | 1 | 5 | 5 |
Capacitor | MLCC 10μF | 50 | 1 | 50 |
Case | MINTIA Breeze | 210 | 1 | 210 |
最近のコメント