WiFiウェザーステーションの製作


はじめに

新築祝いとして頂いたLa Crosse製Wireless Weather Station送信機が壊れたしまったため、WiFi Weather Stationとして復活させます。

ハードブロック図

風見鶏と雨量計はLa Crosse製ウェザーステーションの部品。
気圧センサはLa Crosseウェザーステーションでは屋内受信機側にあったのですが、送信機に一体化させてます。
データをはWiFi上にUDPで飛ばします。
液晶は動作確認用、E2PROMは設定保存用です。
(後でわかったことですが、ESP8266のFLASH領域にも保存できますので、省略できます。)
PIC配下は太陽電池とリチウムイオン二次電池から成る独立電源です。

主マイコン(ESP8266/ESP-WROOM-02)

非常に安価かつ簡易にWiFi/IoTを構築できる石です。
ESP8266はチップ単体でも入手できますが、FLASHとアンテナ等が組み合わさったモジュールが使いやすく、本機は定番のESP-WROOM-02を採用しました。

特徴

・安い。500円くらい
・32ビット、160MHz内部クロックと組み込み定番のPICやAVRから比べ余裕のCPUパワー、RAMも96kB大きい
・外部フラッシュも数Mとこれまた結構大きい
・処理パワーの割に消費電力も結構小さい
・開発環境が良い
 ・SDKに802.11,TCP/IP層を含んでいる
 ・Arduino環境を使うとちょっとしたコードでWebサーバなども動かせる

風見鶏(TX-23U)

La Crosse製ウェザーステーションの構成パーツ。
2年ちょっと屋外で稼働していましたので、分解メンテしました。

TX-23Uは内部にマイコンが組み込まれたインテリジェントなモジュールとなっており、プロプラエティなプロトコルのためデータ解析が課題となります。
幸い、先駆者によってプロトコル解析されており、結果を利用させてもらいました。

https://www.john.geek.nz/2012/08/la-crosse-tx23u-anemometer-communication-protocol/

風速は回転翼に組み込まれた磁石と、リードSWによって検出しています。
1回転1パルスとなっているため、風速が低いと回転検出に長い時間を要します。
つまり、時間軸の分解能は高くありません。

風向は回転するディスクとフォトインタラプタによるエンコーダ方式となっていました。
インタラプタは4セットあり、これで16方位がコードされます。
赤外LEDのようで、発光を目視できません。

電源線と信号線の3線式で、信号は双方向です。
上記の解析結果によれば、 ホスト側でLレベル500msキープするとトリガされ、シリアル化された風速・風向が出てきます。
画像では4線ありますが、1本はNCです。

雨量計(TX-26U)


La Crosse製ウェザーステーションの構成パーツです。
転倒マス式となっており、転倒によってリードSWが開閉されるもので、単なるスイッチです。
分解清掃、反応が悪かったためリードSW交換のメンテナンスをしました。
ネット情報によると、0.02inch/trip(約0.5mm)の分解能とのことです。

気圧計(LPS-331AP→後にLPS-25Hへ交換)

かなり昔に秋月で購入したまま部品箱に仕舞い込まれていたものを活用。
センサ単体ではなく、8ピンDIP下駄がついたモジュールです。
ESP8266とはI2Cで接続されています。
センサの空気穴に光りが射すと読み取りに誤差を生じたため、黒い紙で巻きました。
センサ消費電流が100uA程度なのにLEDがついて2mAとバカバカしいこと、光で読み取り誤差を生じるためLEDを外しています。
「定番」の改造のようです。

液晶(SB0802GN)

ミニI2C液晶モジュール(8x2行)、I2C接続です。
ストロベリーリナックスで購入。秋月にあるAQM0802Aも同じだと思います。

昇降圧DC/DC(TPS63000)

Li-ion電池の3.0V〜4.2Vから、主回路の安定化した3.3Vを生成します。
昇降圧の切替は自動でやってくれますので、ユーザサイドで意識することはありません。
シャットダウン端子に後述のPICを接続し、PIC側からで3.3V系を落とせるようにしています。
単品の石ではなく、 ストロベリーリナックス製の小型モジュールです。

充放電コントローラ(PIC16F1827)

PICのPWMとADCを使ったソフト制御の降圧DC/DCコンバータで、CC,CV,簡易MPPT制御をかけたLi-ion充電器として機能させます。
ESP8266とI2C接続しており、バッテリ電圧、電流、太陽電池電圧等を読み出すことができます。
また、ESP8266がI2Cアクセスを長時間しなかった場合、ハングしたとみなし3.3V系のOFF-ON再起動を行うなどの補助機能を入れています。

電力収支の概算

ESP8266はWiFi故に大飯食いで、送信電力20.5dBm(約110mW)と強力です。
RFアンプの効率は 良くわかりませんが、仮に50%としても入力200mW程度になり、ピークは3.3V/70mA程度と思われます。
今回の使い方は、5秒毎のUDPデータ送信にLight Sleepをかけ、実測では平均30mA程度になることがわかりました。

3.3V/30mA(100mW)これをDC/DC逆効率(100/80%くらい)をかけ、ちょっと余裕をもって消費電力150mWとします。 (
0.15W×24hつまり、3.6Wh/dayです。

太陽電池は夜間発電せず、昼間でも天候・季節により出力は大幅に変わります。
良好な条件では 1200kWh/1kW/年の発電が見込め、これはパネル定格の13.7%の電力が得られることになります。
仮に3Wのパネルを使うと、3W*24h*13.7% = 9.8Wh/dayとなり、 消費電力の2倍以上あるため天候のばらつきがあってもバッテリ併用で賄えるはずです。
18650の容量を3.6V/2000mAhとして7.2Whですので、フル充電されていれば太陽電池なしでも丸2日は動作します。

以上は平均では十分ということであり、実際は梅雨の時期が一番厳しいはずです。

3Wということで、太陽電池パネルは秋月のSY-M3Wを採用しています。
アルミフレームに入ったしっかりしたものですが、1200円と安価です。

太陽電池パネル仕様(SY-M3W)

最大出力電力 (Pmax) 3W
開放電圧 (Voc) 10.9V
短絡電流 (Isc) 0.37 A
最大出力時電圧 (Vmp) 8.7 V
最大負荷時電流 (Imp) 0.36A
サイズ/重量 251 x 140 x 18 mm / 0.52 kg

ESP8266ソフト開発

<開発環境>

ESP8266の開発環境を調べると、純正SDKより、Arduinoを使った作例のほうが圧倒的に多いことがわかります。
Arduinoは初心者向きで、細かなことをやるには限界があるのではと思っていましたが、全くの杞憂でした。
C++ベース故、Cと同じ粒度のことは完全にできます。
Webサーバクラスなども用意されており、数行程度で使えます。
組込み固有の、割り込みハンドリングのような細かい ことから、大雑把にWebサーバを動かすようなことまで一筋縄にできてしまうのが強みだと思いました。
Arduinoで大正解でした。

この環境(Arduino-ESP8266)の良いところ

・開発環境の構築がとても簡単(純正SDKはLinuxベースですが、こちらはWindowsクロスコンパイラが入っている)
・Cから違和感なく取り組め、細かいこともできる(上級ニーズにも完全に耐えられる)
・WiFi, Webサーバ等が抽象化されており、簡単に使える
・情報が多い

仕事で、HTTPサーバに相当するものを丸丸作ったことがあります。
SSLを含めたソケット層、HTTP層の実装、スレッドや同期オブジェクトのマネジメント機構などで コード量は軽く1万行を越えました。
ArduinoのWebサーバはスループット、セキュリティ等は全然でしょうが、デバイスの管理Webサーバなら十分と思います。
(しかし、FireWall越しでも、これをインターネットに公開するのはどうかと思います。)

<風見鶏(TX-23U)データ読出し>

https://www.john.geek.nz/2012/08/la-crosse-tx23u-anemometer-communication-protocol/

上記サイトの解析情報を参考に実装しました。
主要な部分はタイマーとIO割込みで処理し、メインループはデータ取得指示と結果リードが、ノンブロッキングで行えるようにしました。
割り込み処理の中でピンの方向性を変えています。
これはpinMode()で行いますが、実はこれが割り込みセーフではありません。
当初、これが原因でしばしばクラッシュしました。
ライブラリのpinMode()をそのままに、ICACHE_RAM_ATTR属性をつけた割り込みセーフ関数を用意して回避しました。

なお、TX-23Uの読み取り頻度は5秒/回程度です。
1秒/回程度に縮小すると、風速計が作動しないか不正な値となりました。(風向計は作動)

< 雨量計(TX-26U)データ読出し>

転倒マスのトリップにより、リードSWが開閉します。
これをESP8266のGPIO割り込みでカウントします。
カウント値はE2PROMに書き込み、積算してゆきます。
基本カウンタリセットしません。
雨量は、ある時間間隔での積算量となりますので、ひたすらカウントアップしたデータが使いやすいと思います。

< 気圧計(LPS-331AP)読出し>

出力ノイズ低減のため、1秒サンプルで読出し、0.1HzのLPFをかけました。

<液晶表示>

運用してしまえば見ることはありません。
現在値やWiFiのRSSIを表示しています。
デバッグ用、設置時の確認用です。

<I2Cデバイス一覧>

下記デバイスはI2Cスレーブとしてアクセスしています。

Addr デバイス
0x3E 液晶 (SB0802GN)
0x40 充電コントローラ (PIC16F1827)
0x50 シリアルE2PROM (24LC256)
0x5C 気圧計 (LSP-331AP)

ESP8266のI2C実装はハードウェアによるものではなく、完全にソフトI2Cのようです。

<データ出力>

UDPを使い、計測データを一定時間ごとにサーバに飛ばします。
TCPを使わないのは下記の理由です。

・送信パケット数が少なく、省電力(TCPはハンドシェイク、FINがあります)
・接続できなくても、ブロッキングされない
・そもそも、頻繁に送ってくるテレメトリーデータであり、多少取りこぼしても問題ない

2番目のブロッキングされないのは重要なポイントで、サーバやネットワークがダウンしていると送信側のconnectがブロッキングされ、ウォッチドックリセットされてしまいます。

< 管理Webサーバ>

設定と現在状態を読み出すためのWebサーバを稼働させています。
ESP8266HTTPUpdateServerクラスによる、OTAファーム更新もかんたんに実装できました。

<設定>

SELスイッチを押しながらリセットするとセキュリティなしSoft-APとして動作します。
これに接続し、ブラウザにて必要な設定を施してリブートします。
良くあるネットデバイスの設定方法です。

設定値はE2PROMに保存されます。
ESP8266のFLASH領域をE2PROMとして取り扱うライブラリが用意されています。
ハード設計時、そのようなことは知らなかったので外部E2PROMをつけました。
ESP8266のFLASH書換え回数はよくわかりませんが、雨量カウンタが都度更新しますので、外部E2PROMをつけた設計で正解のような気もします。

Arduino-ESP8266の仕様で、1回に取り扱えるI2Cデータ長上限は32バイトになっています。
設定情報は32バイトを超えているので、自前のアクセス関数内で複数のライブラリコールを行っています。

PICソフト開発

<CC/CV/簡易MPPT制御>

Li-ion電池を安全・確実に充電するための基本は定電流(CC)、定電圧(CV)充電です。
セル終止電圧をCVリミット、最大充電電流をCCリミットとします。
この充電方法は非常に一般的ですので詳細は割愛します。
目標との誤差をPWMデューティへフィードバックしますが、CC、CVともに誤差が出ます。
デューティが低くなる方を選択することで、CV/CCが切替わります。

MPPTは Maximum Power Point Tracking の略で、最大電力点追従です。
太陽電池は不安定な電源で、電池出力は0〜100%まで刻々と変化します。
充電電力<太陽電池出力であれば、最大電力追従の必要はありません。
逆の場合、CC/CV制御はかけられません。
MPPT無しだと、次のようにPWMデューティが飽和します。

・充電電力>太陽電池出力になろうとする (充電電力の増加、入射光量の低下)
・太陽電池電圧低下→CV/CCがPWMデューティ比をアップ
・ますます電池電圧低下→デューティ100%で飽和

デューティ100%飽和すると、スイッチング無しと同じなので太陽電池の電圧はバッテリ電圧と等しくなります。
この状態では太陽電池の出力を効率よく引き出せません。このために、MPPT制御が必要となります。

本格的なMPPT制御では、最大点を動的に探ります。
デューティに対する最大電力は、上に凸の関係にあり、ピークを探るのです。

本機は簡易的に固定電圧方式としました。
太陽電池パネル定格にあるVmpをそのまま設定しています。
真のピークは多少動くのですが(特に温度で)、そこは簡易的なので良しとしています。

本充電器のブロック図を示します。

誤差増幅はPI制御となっています。
ソフト処理のため、制御周期から来る制約があります。
誤差圧縮をPゲインだけでやろうとすると、制御遅れによる位相遅延で発散してしまいます。
I項は周波数に対してゲイン低下を示す(1/ω)ため、安定します。ただ、過渡応答が悪いです。
バッテリ充電器なので過渡特性は妥協しています。

Vmppの誤差増幅器の極性が、CV/CCと逆転していますがこれで正常です。

< モニタ機能>

ESP8266から電源状態(電池電圧、充電電流、太陽電池電圧、充電モード)を 読み出します。
また、ウォッチドッグのON/OFF、電源再起動を指令できます。
太陽電池パネルの変更に対応すべく、固定としたVmpはESP8266側から変更出来るようにしています。
この値はPIC側のE2PROMに保存しています。

< 過放電防止機能(LVP)>

バッテリ電圧が2.8V未満になると、3.3V生成DC-DCをシャットダウンて過放電を防止します。
ESP8266側は電源カットされて停止、3.0V以上で復帰します。

< ウォッチドッグ機能(WDT)>

IC2アクセスが長時間行われない場合、ESP8266がハングしたとして3.3V DC-DCをOFF/ON(電源再起動)します。

<I2Cレジスタ一覧>

ESP8266から見て、一般的なI2Cデバイスのように振る舞います。
デバイスアドレス:0x40

Addr 項目 R/W 備考
0 バッテリ電圧 R lsb=20mV
1 バッテリ電流 R lsb=10mA
2 PV電圧 R lsb=0.1V
3 状態・コマンド R/W 別表参照
4 Vmpp R/W lsb=0.1V (E2PROM保存)

状態・コマンド <1..0>

bit 状態 備考
00 充電停止中 Read only
01 充電中(CVモード)
10 充電中(CCモード)
11 充電中(MPPTモード)

状態・コマンド <7..2>

MASK 状態 意味 初期値
0x04 LVP 1=有効 / 0=無効 1
0x08 WDT 1=有効 / 0=無効 0
0x10 PCY(3.3V電源再起動) 1=要求 / 0=通常 0
0x20 ENA(充電有効/無効) 1=有効 / 0=無効 1
以降 未使用    

<PICリソース使用状況>

PIC16F1827のFLASH使用率58%、RAM使用率17%です。
コンパイラはMPLAB XC8 (PRO Mode) V1.36 です。

実装と設置

基板設計はいつものEagle、製造はFusion PCBです。
防水ケースのタカチBCAP101507に合わせた基板サイズとしました。

ケース左(電池横)の部品はフィルタつきのベントホールです。
気圧計があること、完全気密にすると内部負圧になった際、変なところから侵水するための対策です。
2階ベランダの南東角に一式設置しました。

ケースと、ベントホール、防水ブッシングなどはタック電子販売さんから購入しています。

ケーシング部材

品番 品名 備考
BCAP101507 防水・防塵開閉式プラボックス  
PMF-12S プロテクティブベント  
RMW8L-4B ケーブルグランド もう1サイズ大きい方が取り回しがいい
BRF-100 ルーフ 後で追加、上記画像には映っていません

 

データ蓄積サーバ開発

UDPデータを拾い、SQLITE DBに蓄積しています。
データ加工は追々考えます。

結果と検討

<バッテリ電圧推移>



約1週間稼働させた際('17/1/16〜24)のバッテリ電圧、充電電流推移。(電圧左[V]、電流右軸[A])
晴天続きなので、放電量は少ない。
朝9時頃にCVリミットに達し、昼頃には30mA(負荷電流とほぼ同じ)に落ち、充電完了している。
(CVリミット値はバッテリ長寿命化のため4.15Vとしている。I2C側の電圧分解能は8ビット20mV分解能なので、4.14V。)
 

<気圧データの温度依存性>

気圧左軸[hPa]、温度右軸[℃]
温度は気温ではありません。日射で壁が温かいのです。
近場のAMEDASと似た傾向だが、温度依存が強そう。
これがセンサ(LPS-331AP)のスペック通りなのか要検討。
15時ちょっと過ぎのヒゲはBOX開放したときのものと推測。温度なのか、光なのか。

LPS-331APのアプリケーションノート(AN4159)によれば、オンチップ温度補償は3点直線補償とのことだ。
更に良い結果を得るには2次補償のほうが良く、これは外部ソフトでやれとなっている。
必要な補償係数はレジスタに書かれているとあるが、レジスタマップには記されていない。
LPS-331APはチップのバグ、仕様書との記述不一致があると報告されており、これも仕様バグ?の一つかもしれない。
バグが原因なのかディスコンとなっており、後継のLPS-25Hに代わっている。

こちらは後継LPS-25Hのデータシートより抜粋。
ADC後に2次温度補償がオンチップ実装されている。
要するに、LPS-331APを捨ててLPS-25Hに乗り換えたほうが温度特性がよいということだ。
LPS-25Hのアプリケーションノート(AN4450)には、もはや外部温度補償について述べられていない。


秋月 LPS-25H Pinout

秋月 LPS-331AP Pinout

秋月LPS-25Hは、同LPS-331APからハード変更無く差し替え可。
(INT2を使っていなければ。これを使っている人はほとんどいないと思います。)

LPS-25Hに交換 (2017/1/28の10時頃)

温度依存性はLPS-331APより減っているように見える。
交換後、1/29 0時あたりでAMEDASとの乖離が大きくなり(温度10℃くらい)、その後は同じ温度でも乖離が小さくなる傾向に読める。
なぜ、乖離が小さくなったのかよくわからない。
MEMSの微小なストレインが、実装時の熱的・機械的ストレスを受けて内部応力を生じ、それが時間とともに解放されていくのかもしれない。
とすれば、これはしばらく「エージング」したほうがよいのかもしれない。

交換前後の気圧拡大(1/28)

LPS-25HはオンチップFIFOを有効にした。
25Hz、32移動平均したものを、LPS-331AP同様にESP8266が1秒毎に読み出し、0.1HzのLPFをかけている。
明らかにノイズが減っている。LPS-25Hは階段が見えているので、0.01hPaでデータ出力しても良さそうなくらい。

観測気圧とAMEDAS三島の比較(17/2/15)
AMEDAS気圧は現地気圧

温度と誤差(観測気圧-AMEDAS三島)のプロット

オフセットはある程度仕方ないといえ、再現性の揺らぎも0.5hPa程度ある。
風が吹いていたりすると気圧が微妙に揺らぐので、そういった影響もあるだろう。
LPS-331ほどではないが、温度依存もある。このあたりがLPS-25Hの「実力」ということだろう。
そうはいっても、1000hPaの0.5hPaなので、相当の精度なのだが。

<電力>

太陽電池充電器の起動特性は改善すべき(17/2/18)

曇天だった2/17の太陽電池電圧(PV,左軸)、充電電流(右軸)
7:37に起動し、直後の充電電流は40mAだった。
いったん起動してしまえば、13時あたりのように充電電流がほぼ0でも起動している。
つまり、寝起きが悪い。
原因はわかっており、太陽電池の供給電流が小さい間、3.3Vレギュレータが食っている。
このレギュレータはいったん起動してしまえば、さして電流を取らないということだ。
レギュレータ入力をゆっくり増圧するのは、本来はあまり良い方法ではない。

こちらは同日の太陽光発電の様子、縦軸は発電電力(kW)
6:48に起動、ウェザーステーションの充電が開始された7:37は0.5kW発電している。
雲の間から日が射すようで、発電電力の変化が激しい。

<安定性>

高温になると頻繁に再起動している。(17/06/25)

'17/01運用当初、約1ヶ月連続運転。その後ネットワークダウンにて停止。
定期再起動機能、ネットダウン再起動機能を追加。

気温上昇に伴い、日中は頻繁に再起動していることがわかってきた。


(左軸 起動後時間、右軸温度、'17/06/23〜24)

ESP8266のWDT、PICに内蔵したI2C WDTにより再起動している場合の両方があるようだ。
理由はよくわからないが、ESP-WROOM-02の問題のように思える。

<電欠発生>
(2017/10/18)

'17/10の長雨で初めて「電欠」が発生。
13日はチャージャー起動せず、全く充電できていない。
14〜16日は起動しているが、その日の電力量をまかなえていない。
丸4日経った17日に低電圧保護でシャットダウンしてしまった。
しかし、リチウムは3.6Vから急速に落ちるんですね。3.3V程度までダラ下がりと思っていました。
天候が回復した18日は昼頃にフル充電できています。
短時間にフル充電になる割に連続雨天で落ちることから、バッテリ容量不足ということになります。
元々バッテリで2日動くことがわかっているので、連続雨天4日で落ちたのは想定範囲ではあります。
18650×1では不足で、×2がちょうど良さそうです。

18日充電時のバッテリ電流時間積(mAh)×電圧
バッテリが容量抜けしているということはなさそうです。
使っているのはおそらく2200mAhのサンヨー製セルです。

<2017年台風21号>
(2017/10/24)

23日4時、最低気圧960hpを観測。

御前崎に上陸とのことだが、トレースは一旦洋上に出て見事に沼津市をかすめている。
中心気圧と見事に一致。中心気圧って結構正確なんですね。

設計データ

基板CAD(Eagle)

ESP8266スケッチ

PICソフト


[戻る]

Created: 2017/01/21 
Updated: 2017/10/24