WROOM-02とBME280 電池駆動で温度測定の改訂版

概要

すでに暖かい4月になってしまったが、この冬は寒かった。1月の終わりに大雪が降った後もなかなか気温が上がらなかったので、以前作ったESP-WROOM-02と温度センサーをつないだブレッドボードと、単3形のNiMH充電池直列4本を電源に使って我が家の外気温を測定し始めた。

AE-ESP-WROOM-02

測定データは自宅のWiFiルーターを経由してインターネット上のサーバーに送ってmysqlに格納し、同じサーバーに置いたhtmlをPCやスマホで開いて見えるようにした。数字だけ見えてもつまらないので、GoogleChartsを使って温度や湿度、電圧の推移をグラフ化している。
最終測定時刻と測定結果をグラフ内に数字で表示するようにしたので、測定がちゃんと継続しているかどうかを判断できる。また、朝からカメラを担いで出るようなとき、スマホでその時点の気温を見て服装を決めたりしていた。

基本的には以前にHDC1000を使った話や、中国から取り寄せたBMP280を使った話を踏襲している。電池を交換したりしながら2ヶ月以上稼働させているうちにいろいろと改良を加えてきているが、今回は基本となるプログラムや回路、その測定結果についての話と、電池のモチを延ばすために改良したことなどをまとめた。

スケッチおよび回路など

まずは、Arduino IDE 1.8.3版に”ESP8266 core for Arduino” の2.4.0版を入れた。去年(2017年)の初夏にPCを変更して以来、ESP8266 coreは入れてなかったので、 https://arduino-esp8266.readthedocs.io/en/2.4.0/ にある、Boards Manager を使う方法で取り急ぎ導入した。

スケッチ(メインスケッチと、BME/P280およびHDC1000用のクラス)は以前とほぼ同様のものを使った。サーバー側のスクリプト類は、以前やったときに使っていた仮想サーバーの基盤がダメになって消失してしまったので、ブログに載せた内容に基いて作り直した。しょうしょう長くなるので、スケッチ、SQLスクリプトおよびサーバー用PHPプログラムはこちらにまとめて掲載した。 ご興味のある方は合わせて見てください。

WROOM02-BME280-NJU7223-1

回路についても以前のものを踏襲しているが、ESP-WROOM-02
Datasheet (Version2.6) の、Figure 5-2. ESP-WROOM-02 Peripheral Schematics にならってEN端子とGND間に0.1μFのセラミックコンデンサを追加した。10KΩの抵抗と0.1μFのコンデンサにより、EN端子の電圧がHレベルに達するまでに0.5msec程度の遅延が生じるはず。このRC遅延回路には、ロジック側の電源電圧が安定するまでWROOM-02の動作を許可しないという意味がある。

定電圧レギュレータには3.3V 500mA出力のNJU7223F33を使った(秋月電子のページにあるデータシートを参照)。出力電圧が+3.3V、ドロップアウト電圧が0.4~0.6V、静止時電流が30~60μAなこと、そして秋月で買えることが選定の基準。

電源としては単3サイズのNiMH(amazon basic 公称1900mAhなど)を直列に4本接続しており、フル充電時の実測で5.8V出ていた(開放電圧)。その電圧を470Kと100Kの抵抗分圧により、開始時にほぼ1VとしてTOUT端子に接続して電圧を測っている。5.7V時には、これらの抵抗を介して常時10μA流れることになるが。

AE-ESP-WROOM-02 + GY-BME280

ふつうのブレッドボードに載せたところ。このボードと電池ボックスを小さな箱にいれ、ボード自体を露出させて野外に近い場所に置いた。

GY-BME280

中央上の四角い銀色のデバイスがBOSCH社のBME280。BME280の場合、刻印2行目の先頭が”U”になっている。データシートによれば、BMP280 (part number 0 273 300 354)ではこの位置に”K”が入ることになっている。

測定結果など

mysqlに格納したデータをGoogleChartsのLineチャートを使って描画したものをいくつか。

1月末に使い始めた回路/スケッチでは電源電圧の測定や送信は行っていなかった。当初の測定ボードが電池切れで停止する前に、掲載した回路とスケッチを載せた測定ボードも並行して動かし始め、2月7日の0時から新しい方のボードでのデータを残すようにした。

気温の推移

1月25日から4週間の平均、最高、最低気温の推移

インターバルチャートを使って、平均(中央)、最高(上)、最低(下)の各気温の推移を書かせたもの。平均気温は1桁台で推移し、最低気温が0℃を下回る寒い日々だった。

 

電池電圧の推移

以下のグラフは2月7日の午前0時からの23日の0時までの気温と電源電圧の推移を表している。Y軸左側が気温のスケールで青線、Y軸右側が電圧で赤線になっている。これには、2つの系列のデータをおのおののスケールに合わせて表示できる、dual-Yチャートを使っている。

2018年2月6日から17日間の気温と電圧

ほぼ14日間で終止電圧に達しいることが分かる。この間のデータ数(テーブルにINSERTされた行数)は7023件だった。実際には2月6日からこのボードを動かし、7日0時のデータから採用しているので、約15日間で停止したことになる。

2018年2月21日0時から48時間の気温と電圧

こちらは同じ測定結果のうち2月21日から48時間の推移で、22日の午前4時に電源電圧が低下して動作を停止している。最後は4.5Vを下回ったあたりで急激に電圧が落ち込んでいることが分かる。最後に送信された電源電圧は2.5Vだった。
22日朝の気温を見ようとしてデータ送信が止まっていることに気づいたので、電池を交換して11時頃から測定を再開している。

充電池の過放電を防ぐ意味では、測定電圧が4Vを下回ったあたりで負荷から切り離したほうがいいかもしれない。現状の回路構成では切り離すことができないので、電源電圧が低下した場合には負荷を小さくするような方法を採用した方がいいだろう。具体的には長時間のディープスリープに入れるとか。あるいは、サーバー側のPHPで電圧低下を検出し次第メールを出すようにしてもいいだろう。

NiMHも低温には弱いようだ

2月12日の気温と電源電圧

これは2月12日0時から48時間の気温と電圧を表しているが、気温に対応して電源電圧が敏感に変動している。約10℃の変化で0.04V変化している。この理由には二つのことが考えられる。

  1. 分圧回路の抵抗値が温度で変動する。
  2. 低温時にはNiMHの内部抵抗が高くなる

分圧抵抗説

電源電圧は、470KΩと100KΩの金属皮膜抵抗を直列につないでいることから、5.7V時に1Vの電圧がTOUTに生じることを前提としている。そして、A/D変換結果を5.7倍することで分圧前の電圧としている。なお内蔵のA/Dコンバーターは0~1Vの電圧を10ビット分解能でデジタル化するから、1ビットあたり(1V ÷ 1024 = ) 0.00098V。今回は変換結果を5.7倍して分圧前の電圧を得ているので、得られる電圧の分解能は0.0056Vということになる。

分圧回路の抵抗には金属皮膜抵抗を使っている。具体的な仕様は不明だが温度係数が±200ppm/℃とすると10℃で±2000ppmなので±0.2%変動することになる。したがって変動後の抵抗値は、マイナス側ならば469Kと99.8K(計568.8K)、プラス側なら471Kと100.2K(計571.2K)になる。例えば実際の電源電圧が5.24VだとするとTOUT端子における電圧は、0.918Vと0.919Vとなり、変換結果1ビット程度の誤差が生じることになるが、0.04Vの変動(約7ビット分の増減)にはおよばない。よってこの説は却下。

なお、秋月電子などで売っている抵抗器大手のKOA社の金属皮膜抵抗(MF 1/4シリーズ)の温度係数は±50ppm/K (MF1/4CCの場合)なので、50℃変化しても抵抗値は±0.25%しか変動しない。

電池のこと

エネループとamazon basics

NiMH充電池の代表格であるエネループの資料によると、放電時の温度範囲は -5~50℃となっている( http://dl-ctlg.panasonic.com/jp/manual/p_/p_bk3mcc248_t_201304181131_0.pdf )。冬の外気温を測るには、ちょっと無理があったのかもしれない。また、温度特性表 ( https://industrial.panasonic.com/cdbs/www-data/pdf/ACG4000/ACG4000PJ12.pdf 内の乾電池互換タイプ )を見ても、0℃では電圧、放電容量ともに低下するようだ。電池内部での電気化学的反応の活性が下がることがおもな理由と思うが、電池の世界では単純に「内部抵抗」が上がるため、ということになっている。

なお、アルカリ乾電池についてはPanasonicのリチウム電池関連のページ内に以下のように書かれている。

アルカリ乾電池の5℃~45℃という使用温度に比べ、1.5Vリチウム乾電池なら−40℃~60℃までの、温度幅100℃という幅広い温度の中でも使用可能。低温特性が優れているため、寒冷地においても機器の使用が可能で…

アルカリ乾電池は、0℃を下回ると電解液が凍ってしまう(?)のかもしれない。以前、デジカメにアルカリ乾電池を入れていてスキー場で使えずがっかりしたのを思い出した。こういうときはホッカイロに包んでおくのが定番なのだが。

外気温にさらされる状況で使うのならば、リチウムイオン電池が向いていると思うのだけど 18650や26650といった大容量のリチウムイオン充電池はちょっと使いにくい。サイズがまちまちなので電池ボックスに困ること、+3.3V出力の電圧レギュレータの入力とするためには放電電圧がちょっと半端なこと、そして扱いに間違えて燃えると怖いことなどが理由。

消費電流と電池のモチ

当初使っていた回路とスケッチでは、電池が2週間ももたなかった。その後今回掲載した回路とスケッチに変更したが、さほど改善しなかった。外に置いて使っているので低温の影響も大きいのかもしれないが、せめて充電一回で2ヶ月は動いて欲しいと思ってこの測定ボードの消費電流について考えてみた。

別のページに載せたメインスケッチは、以下のように動作する。

  1. (電源オフまたはディープスリープ状態)
  2. 開始するとセンサーを初期化しWiFiアクセスポイントに接続。
  3. 測定結果を送信しアクセスポイントから切断。
  4. 測定間隔時間をパラメータとしてディープスリープ開始。(1)に戻る。

測定間隔時間(スリープ時間)は180秒としていた。(2)に要する時間が実測で約8~10秒間、(3)は0.1~0.2秒間だった。したがって、WiFi稼働時間は平均約9秒間ということになる。

NiMH充電池の容量は公称1900mAhとなっているが、これは常時1mA消費する負荷に接続したとき、1900時間経過すると負荷に接続した状態での電圧が1V未満になるということだろう。今回は直列に4本使っているので、4V未満になった時点で電池切れということになる。

スリープ時の電流

電圧レギュレータの静止時電流(30~60μA)、分圧抵抗に流れる電流(10μA)、WROOM-02のディープスリープ中の消費電流は20μA以下ということなので、ディープスリープ期間(つまり測定間隔期間)には常に約60~90μAの電流が流れていることになる。
実際にボードのGNDと電池の-側の間にテスターを挟んで得た実測値は約60μAだった。このときの電源電圧が5.7Vだったので最大値と考えてよいだろう。この電流は稼働時もスリープ時も流れ続けると考えられるので、1時間あたりの放電容量は0.06mAhということになる。

稼働時の電流

WROOM-02を使った電子工作では、電源投入時やリセット直後の開始時に瞬間的に300mA以上の電流が流れることが知られている。このため、非力な電源では開始時にロジック側の電源電圧が+2.5Vを下回ってCPUコアが動かなかったり、フラッシュからスケッチを読みだせないから開始しなかったりする。今回の構成ではそのような症状は起きないのだが、例えば250mA出力の電圧レギュレータを使ってみたりすると、最初のうちは動くにしても安定した動作は望めなかった。

テスターでは瞬間的な消費電流は測れないものの、稼働中の平均消費電流は90mA程度と考えて以下の計算を行った。

電池寿命の算出

上記のパラメータをから電池のモチを計算してみる。

WiFi稼働時に1時間あたりに使う電流は、
  90mA × 9 sec × 20回  = 16200mA(s) ≒ 4.5mA(h)
となる。電池の容量が 1900mAh なので、
  1900 ÷ (4.5 + 0.06) = 416.7時間 ≒ 17.4日間
ということになる。

この場合、スリープ時の電流は1時間あたりの消費電流を計算する上ではほとんど寄与しない。しかしながら、電圧レギュレータとして常時800μA程度消費するTA48033Sを使うとすれば、無視できないほどの影響があるはず(1900÷5.3 ≒ 358.5時間≒14.9日間)。

上に載せたグラフから約15日間の稼働という結果がでているが、2月の低温の影響によるのか、十分に充電されていなかったのか、計算値よりも2日間ほどモチが短かった。

電池のモチをよくするには

ESP-WROOM-02でWiFiを使う以上、稼働時の電流を小さくすることはできないのだが、1時間あたりの稼働回数を減らすことはできる。また、WiFi稼働時間を短くすることができれば電池のモチはよくなるはず。

稼働回数を減らす

測定間隔を360秒とすることで1時間あたりの測定回数を10回とする。このようにした場合、単純に倍の時間(約30日間)は動くはずである。

当初3分間に一度の頻度にしたのは、最新の温度を見たかったからなのだが、2ヶ月ほど測定してみると気温の変化は比較的緩やかだった。6分に一度、あるいは10分に一度の頻度にしても、気温の変化はセンサー(BME280)の公称誤差(±1℃)の範囲内だろう。

なお、電池電圧の推移を得たグラフの元データから、3分後の気温が0.3℃以上変化した件数を得てみると83件だった。0.4℃以上にすると15件。全部で7023行あるので、おのおの1.2%と0.2%に過ぎない。件数の取得には以下のSQL文を使った。

なお、同じようなやり方で6分間で0.5℃の変化があった件数を調べると、わずか9件だった。

SQLテーブルなどについては、こちらを参照のこと。

WiFi稼働時間を減らす

掲載しているスケッチでは、毎回  WiFi.begin(ssid, password); を呼ぶことで明示的に接続しているが、ESP8266にはリセット時に自動的に前回接続したアクセスポイントに接続する機能がある。今まではフラッシュメモリ内に自宅ルーターのSSIDやパスフレーズが記憶されることを嫌ってこの機能を使わないようにしてきた(スケッチにはバッチリ書いてあるのだが…)。しかしながら、アクセスポイントへの接続に要する時間は、自動接続の方が短くなる。比べてみると半分程度(平均して4秒間程度)の時間で接続が完了する。

同じ構成のボードで接続間隔だけを60秒間として数日のあいだ動かしてみた(接続回数は6600回)。その際、setup() の先頭から wifi_send_data(); までの所要時間を millis() の差で求めてサーバーに送信させたところ、平均所要時間は3.8秒間だった。データ送信や切断のために100~200msec要するとすれば、WiFI稼働時間は約4秒間ということになる。

1測定あたりの稼働時間が4秒間になるとして計算してみると、以下のようになる。

1時間あたりに使う電池容量は、
  90mA × 4 sec × 10回  = 3600mAs ≒ 1mAh
となるので、電池のモチ時間は以下のようになる。
  1900 ÷ 1.06 ≒ 1792時間 ≒ 74.7日間

1時間に測定10回ならば2.5ヶ月間、6回ならば約4ヶ月間は稼働する計算になる。

そのためには、掲載しているスケッチの ap_connect() の一部を以下のように変更する。

上記のブロックでは、最初に WiFi.SSID() とスケッチ内のssidを比較し一致しているかどうかを調べている。この段階で WiFi.SSID() がssidと同じ値をもつということは、ESP8266のSDKの機能によりssidが記憶されていることになる。一致しているならば、明示的な接続や記憶のための処理を飛ばしてWiFi.status() が WL_CONNECTED になるのを待つ。

不一致の場合は記憶されていなかったことになる、あるいは、スケッチに書いたssidやパスフレーズを変更したことになるので、{ } ブロック内のアクセスポイントへの接続と、設定内容の記憶処理になる。
WiFi.persistent(true); としてあるときに WiFi.begin(ssid, password); が成功すると、ssidとpasswordがフラッシュメモリ内の専用の領域に保存される。また、WiFi.setAutoConnect(true); とすることで次回起動時には記憶内容を用いた接続が行われる。そして、ブロックを抜けて接続待ちになる。

ap_disconnect() についても以下のように変更する。

こちらは、WiFi.disconnect() の前に、WiFi.persistent(false); を追加する。WiFi.persistent(true);  のまま WiFi.disconnect() ; とすると、ap_connect() で記憶したssidとpasswordが消去されてしまうようである。このあたりは、ESP8266WiFiSTAClass::disconnect() の実装を参照。

WiFi._persistent 関係の挙動は、Arduino Coreのバージョンが上がると変更されるかもしれないので、注意が必要。

DHCPを使わない

DHCPアドレスではなくステーションに静的IPアドレスを設定することでも、WiFI稼働時間を短縮できた。この場合のDHCPとは、接続先のWiFiルーターがWROOM-02ステーションにIPアドレスを与える機能を意味する。したがって、WiFiルーターの性能に依存するだろう。うちのルーターでは約1.5秒間短縮できて、WiFi稼働時間は約2.5秒間となった。

静的IPアドレスを用いる場合には、自局アドレス、ゲートウェイアドレス、サブネット等を定義しておき、setup() の先頭あたりで以下のように設定する。

WiFi.config() のパラメータは、Arduino のそれとは若干順序が異なっているのだが、実装内でうまくやっているようだ。詳しくは、bool ESP8266WiFiSTAClass::config(); の実装を参照。うちの場合、第四パラメータのDNSアドレスにはゲートウェイと同じアドレスを指定している。

同じように6分間ごとの接続で1時間あたりに使う電池容量を計算してみると、
  90mA × 2.5 sec × 10回  = 2250mAs ≒ 0.625mAh
となるので、電池のモチ時間は以下のようになる。
  1900 ÷ (0.625 + 0.06)  ≒ 2774時間 ≒ 115.6日間

最初からこうやっていたら3ヶ月間は動いたわけである。もっとも、これ以上の改善策は考えなかっただろうが。

単4電池で試してみた

WiFi稼働時間を短縮した効果を確認するため、amazon basic 単4(高容量, 800mAh)を直列4本接続したものを電源とし、30秒間に一回の頻度で連続稼働させてみた。

amazon basics 単4サイズ

4月2日の14:20から8日の0:45まで稼働し、送信回数は14444回。32秒間ごとで14444回 だから、延べ時間は462208秒間 ≒ 128時間≒5.3日間稼働したことになる。サーバーに記録された接続時間の平均は2.2秒間だった。

電源電圧の推移

接続後のリクエスト送信、レスポンス受信、切断に要する時間を100msecとして、WiFi稼働時間が占める割合を求めると、2.3 / (30 + 2.3) = 0.071 なので7.1%となる。1時間のうちの7.1%にわたって90mA流れたとすると、90 × 0.071 ≒ 6.4 だから1時間で6.4mAhを消費したことになるので、電池の公称スペックから計算したモチ時間は 800 ÷ 6.4 = 125時間 = 5.2日間だから、実際には0.1日間 ( 2時間) ほど余計に動いてくれたことになる。上のグラフのように、4Vを下回ってもしばらく稼働していたことを考えると、ほぼ計算通りのモチ時間だったことになる。

1900mAhの単3形のNiMH充電池を使った場合には容量が2.375倍だから、14444 × 2.375 ≒ 34300(回)はWiFiが稼働できたことになる。6分間に1回の頻度で接続した場合、計算上は約143日間は稼働できることになる(スリープ時の消費電流を無視した場合)。

※ このテストに使ったボードは、次に示す回路図を使っており分圧抵抗の値が今までの話と違っているから、電源電圧5.545V以上は測定できない。

HDC1000とBMP280を同じボードで

WROOM-02 + HDC1000 + BMP280

最初に回路を載せたボードの他に、AE-HDC1000とGY-BMP280を両方とも載せたボードも動かしていた。回路図は以下のとおりで、i2cバスにおのおののセンサーモジュールをつないだことと、電圧測定用の分圧抵抗が1MΩと220KΩとしたことが変更点。抵抗値を大きくしたのはこの回路に流れる電流を減らすため。

GY-BMP280とAE-HDC1000。撮影する都合でAE-HDC1000はブレッドボードから抜いている。

スケッチについても、センサーインタフェース用クラスは同じで、以下のように2つの測定結果を得ることと分圧抵抗に応じて電圧計算用の係数を変更しただけである。

同じブレッドボードに載せていても、これらのセンサーから得られる温度には相違があった。

HDC1000とBMP280の温度測定結果

この図は、2月7日から2月21日までの2週間に2つのセンサーからの値を2系統のインターバルチャートとし、ツールチップにその日の気温を表示するようにしたもの。全般に青線のHDC1000の方が高めにでている。最高気温の差はあまりないものの、最低気温の差が大きい。もっとも、最高、最低、平均気温ともに1℃以上の差はないので、BMP280の測定誤差範囲には収まっている。

きょうのまとめ

  • 2月から書き始めたのだけど、いろいろと手を入れたりデータが貯まるのを待っていたりするうちに2ヶ月ほどかかってしまった。それにしても、3分間に一度という測定頻度はやりすぎだった。気温はあまり急激には変化しないから1時間に10回、あるいは6回という頻度で十分だろう。
  • 雨が降ると直撃はしないものの飛沫がかかるような場所に置いていたので、たまに停止することがあった。ブレッドボードには穴凹がたくさんあるので、その中に溜まったり、ブレッドボード用のワイヤに水滴がついて別の部分と微妙に導通したりしたようである。上の写真を見ても、若干サビが出ている。
  • 電池を使う場合、電池ボックスにも気を配る必要がある。電池ボックス内の端子と電池間が広い面積で十分に接触していないと、すぐに電流に影響する。また、電池ボックスとボードをつなぐリード線にも注意が必要だろう。
  • また、ブレッドボードの接触不良(あるいは接続不良)にも悩まされた。充電したばかりの電池を接続しても、電流が不足するのかWROOM-02が起動できなかったりした。ブレッドボードは、国内のショップで買っても中国から取り寄せても中国製であることに変わりはないと思うのだけど、お取り寄せの方が不良率が高かった。
  • 今回は、WiFi稼働時間を減らすことで電池をもたせる方法を考えたが、WiFiが有効な状態での起動回数を減らす方法も試している。WROOM-02のdeepSleep() のパラメータによって復帰時のWiFi有効/無効が制御できるので、通常の定期的な測定時はWiFi無効で開始し、送信する場合のみWiFi有効で開始という方法にした。温度変化が大きい場合にのみ送信することで、1時間あたりのWiFi稼働回数は3,4回程度にまで削減できているから、うまく動けば充電1回で1年は動くかもしれない。スケッチやその説明は、改訂版その2として掲載する予定。
  • 気温や湿度、電圧を表示するためのJava Scriptもいろいろと手をいれたので、こちらについても説明書きを作る予定です。