ESP-WROOM-02とBME280を使った温度測定に関係する基本的なソース類をまとめた。概要や回路については、こちらを参照のこと。

目次

  1. 改良前メインスケッチ(ESP_BME280-1.ino)
  2. センサーインタフェースクラス(hdc1000_bmc280.h)
  3. テーブル作成スクリプト(create_table.sql)
  4. サーバー側データベースインタフェースクラス(envdata_db.php)
  5. サーバー側データ格納スクリプト(store_data.php)

ESP_BME280-1.ino

消費電流を考慮していない当初のスケッチ。ESP8266 Arduino Core 2.4.0 を使ってビルド。

解説

このスケッチは、下に載せたセンサーインタフェース用のhdc1000_bme280.h と同じフォルダに入れておく。そうすることで、Arduino IDEを開いたときに各ファイルをタブで選択できるようになる。

定義、定数関係

スケッチを作るときはシリアルモニタにいろいろなメッセージを表示させるが、実稼働時には不要になのでSerial を使う部分は#if ~ #endifブロックに囲んだ。

#define MEASURE_INTERVAL_SECONDS 180 は、測定間隔の秒数を定義しており、1000000倍して ESP.deepSleep(); に渡す。

bme280 bmp280(0x76);  によってbme280クラスのインスタンスを作成しており、引数の0x76でi2cアドレスを指定している。このアドレスに接続されているセンサーがBME280なのかBMP280なのかの識別はbme280クラス内で行っている。このスケッチは、以前BMP280用に作ったものを流用したので変数名がbmp280になっている。

ssid, password, remote_hostは、接続先のWiFiアクセスポイントに接続するための情報と、データ送信先のリモートホストのアドレスを指定している。

void deep_sleep(int seconds)

ディープスリープする秒数を指定する。この関数内では、 ESP.deepSleep(seconds * 1000 * 1000, WAKE_RF_DEFAULT);  を呼ぶことで、スリープ時間をμ秒単位にして渡している。この関数が呼び出す EspClass::deepSleep()メソッドは、スリープ時間を 32ビットの符号なし整数で受けるから、最大で UINT_MAX μ秒まで指定可能となる。具体的には約4295秒 ≒ 71.6分まで指定可能ということになる。

なお、EspClass::deepSleep() 内では、system_deep_sleep(); というSDKのAPIに受け取った引数をそのまま渡している。SDK 側は 64ビットの符号なし整数を受け付けるので、はるかに長い時間を指定することができる。現段階では Arduino Core 2.4を利用しているのでuint32_tでディープスリープ時間を指定する必要があるが、将来的には uint64_tで指定できるようになるのかもしれない。

ESP8266 Arduino Core 2.4.1 において、ESP.deepSleep() の引数は uint64_t  に変更された。https://github.com/esp8266/Arduino/releases を参照。

bool ap_connect()

WiFiアクセスポイントに接続するための関数。以前から疑いもなく使っているが、接続が完了するまで7~10秒ほどかかってしまう。動作の開始からdeep sleepに入るまでの時間のほとんどはこの関数が費やしてしまうので、電池のモチを考えると改善すべき部分。接続時間を3秒以下に短縮する方法については本文側に掲載した。

void ap_disconnect()

WiFiアクセスポイントから切断するための関数。やはり歴史的に使い続けている。

bool wifi_send_data(float temp, float humi, float  press, float vbat)

remote_host で指定のホストのポート80にtcp接続し、パラメータの温度、相対湿度、気圧および電池電圧をHTTP 1.1のGETリクエストで送信する。リクエスト内容は、 /store_data.php?point_id=mac_addr&T=temp&H=humi&P=press&V=vbat  。

送信後、サーバーからのレスポンスを受け取りシリアルモニタに表示する。例えば、レスポンスヘッダやボディ内の文字列を解釈してボード側の動作を変更するようなこともあるので、丁寧に(?)受信している。

void setup()

まずはGPIO15に接続したLEDを点灯させ、BME280を初期化する。初期化に失敗した場合LEDを点滅させて停止する。続いてap_connect() でWiFiアクセスポイント(うちの場合は自宅のルーター)に接続するが、稀に接続が失敗することもあるので、その場合は30秒後に最初からやり直すことにしている。

続いて、system_adc_read() によってWROOM-02のTOUT端子に接続している分圧した電池電圧を測定し、分圧比を掛けて実電圧の100倍の値を得ている。電池電圧は、NiMH直列4本なので最大5.7Vを想定しており、内蔵ADCの分解能は1024ビットなので1ビットにつき0.0056Vを表していることになる。

そして、bmp280.measure() によって温度、相対湿度、気圧を得る。BME280のオーバーサンプリングは3対象ともx1としているので、測定時間は約10msecとしている。

得られた各値をシリアルモニタに表示し、wifi_send_data() を使ってサーバーに送る。最後に ap_disconnect() で切断し、deep_sleep(MEASURE_INTERVAL_SECONDS); によって次の測定タイミングまでdeep sleepする。

void loop() では何もしない。

hdc1000_bme280.h

内容については、以前の投稿を参照

テーブル作成スクリプト

mysql (5.1)用の、データベースおよびテーブル作成用スクリプト。

テーブルenvdataにはBME280単独のボードからのデータを、envdata2には、BMP280とHDC1000を載せたボードからのデータを格納する。Tが温度、Hが相対湿度、Pが気圧、Vが電圧で、X1およびX2は拡張用(接続時間の格納など)。

サーバー側データベースインタフェースクラス(envdata_db.php)

データベース envdbに接続し測定データの追加や、テーブルに格納されているデータのクエリを行うためのクラス。Linux上のPHP 5.33で動作を確認した。

このクラスは、インスタンスが作成された時点でデータベースenvdataに接続し、デストラクト時に切断する。

public function insert_array($table, $ar)

文字列$tableで指定されるテーブルに、配列$arの内容にしたがってリクエストパラメータの読み取りや初期値の設定を行った後INSERTを行う。$arのキー名は$_GET[]からリクエストパラメータを得るときのパラメータ名とINSERT時のカラム名を兼ねている。所定のパラメータが存在しない場合には、呼び出し時に$arが保持しているキー名に対応する値を設定する。

public function query_json($ar, $sql, $condition, $sel_date, $hours)

テーブルから測定データのクエリを行い、json形式にして返す。このメソッドは、GoogleChartでグラフを描画するためのデータを得るために作成したもの。

$arにはカラム名(または別名)に一致したキー名の配列を与え、$sqlにはテーブル名を含むクエリ用のSQL文を指定する。$conditionはクエリの種別(単純なクエリ、インターバル表示用のクエリ、測定日を得るためのクエリ), $sel_date, $hoursにはクエリ条件を指定する。

以前作ったときはPHP5.5で動かしていたが、今回はPHP5.33を使っているため、json_encode(); のoptions に JSON_UNESCAPED_SLASHES を指定できない。そのため、データ内(この場合は日付)の”/”が”\/” とエスケープされてしまうため、str_replace(‘\\/’, ‘/’, $r); によって除去している。

測定データ格納用スクリプト(store_data.php)

envdata テーブルに測定データを格納するためのPHPスクリプト。測定ボード内のスケッチは、このスクリプトにGETリクエストを送る。

リクエストパラメータ(T, P, H, V, X1, X2)と同じ名前のカラムにデータを格納する。配列$arは、リクエストパラメータのキー名とカラム名、それらに対応した省略値を保持する。

※ リクエストパラメータのpoint_id (現状はMACアドレス)には “:” が含まれているが、特に問題ないのでエスケープしていない。

わざわざarray() を作ったりテーブル名を引数にしているのは、カラム構成や名前の異なるテーブルを複数個作り、測定ボードごとに専用のテーブルを用いるようにしたため。例えばenvdata2テーブルに格納するための store_data2.phpは以下のようになる。

envdata_dbクラスのクエリ関係の使い方やGoogleChartを使った描画用JavaScriptについては、より省電力化を図ったスケッチと共に掲載する予定。