HaLake Magazine

コワーキングスペースHaLakeの技術情報発信サイト!IoT,AR,VRなど最新技術情報をお届け!

フリスクとESP32で周囲の環境(温湿度 + 気圧)を測る【ハードウェア編】

f:id:takumishinoda:20190202130845j:plain 今回はESP32とBME280で温湿度と気圧を測る装置を、フリスクのケースに収めていこうと思います。
また、今回はESP32から温湿度と気圧の情報をBLEで送信するところまでをやります。
今回の内容は電子工作初心者には少し難しくなっていますので、この記事を読む前にESP32の仕組みと電子工作の用語を下に記述しますので確認しておくことをおすすめします。
また、プログラムも難易度が少々あって中級者向けのものとなっているので、以下のワードを学習することをおすすめします。



今回主に使用したもの

  • フリスクのケース
  • ESP32
  • 適当な大きさのESP32用ブレークアウト基盤
  • USBシリアル変換モジュール(CP2102使用)
  • レギュレータ 3.3V 1.5A
  • 電解コンデンサ お好みの容量(電力供給用)100uf~1000uf
  • セラミックコンデンサ お好みの容量(ノイズ防止用)約0.1uf
  • 薄い基盤
  • 半田付けする道具
  • プラスチック加工用のホットナイフ(必須ではない)

センサーは温湿度に加えて気圧が測れて、超小型なBME280を使用します。
*注意:似た商品でBMP280がAmazonなどで売られていますが、BMP280では気圧は測れないので注意してください。 akizukidenshi.com レギュレータは念のために1.5Aの大電流版を使用しました。 akizukidenshi.com
ブレークアウトはaitendoにてフリスクケースにピッタシなブレークアウトを使用します www.aitendo.com
電源回路をのせる基盤は秋月で売っている超薄い基盤を使用しました。 akizukidenshi.com
USBシリアル変換機はaitendoより個人的におすすめなCP2102搭載のものを使用します。 ja.aliexpress.com

加工

ESP32の回路をフリスクに入れていきますが、そのままでは使えるスペースが少ないので少し加工が必要です。
また、書き込みと充電用のUSBケーブルを挿す穴がないのでこちらも加工していきます。
加工にはホットナイフを使用しましたが、普通のカッターなどでも頑張れば加工できるかと思います。
まずは上蓋です。

f:id:takumishinoda:20190202130506j:plain
加工した上蓋

上蓋の加工部分はUSBの穴を開けるところです。
上の画像のように側面に適当な穴を開けていきます。
さらに上蓋の裏側に小さな膨らみがいくつかあると思いますが、回路とぶつかるようでしたら削り取ってしまうことをおすすめします。
次に下蓋の加工です。

f:id:takumishinoda:20190202130423j:plain
加工した下蓋

下蓋にもUSB穴の加工を上の画像のようにします。
下蓋に回路が縦方向にうまく収まらないときは上の画像のように底面を全体的に削ると少しだけスペースが増えます。
とりあえずこれでケースの加工が終わり、次は回路の作成に入ります。

回路

f:id:takumishinoda:20190202150328j:plain
回路図

* 注意:図の電解コンデンサはソフトの関係上+と-が逆になっています。

ざっくりとした回路は上の図のようになります。
電源回路も含まれているため複雑な作りになっていますが、フリスクに入れずにBME280を試したい方はまず「ESP32-DevKitC」で回路を作成することをお勧めします。
「ESP32-DevKitC」を使えば配線はBME280とのI2C接続のみとなります。
図だと分かりづらいと思うので概要を記述します。

  • USBシリアル変換機の5Vをレギュレータを通して3.3Vに変換する
  • レギュレータの出力側には電力供給量コンデンサ(100uf~1000uf)を必ず挟む
  • レギュレータの出力側にはノイズ防止コンデンサ(0.1ufくらい)を必ず挟む
  • BME280は3.3V駆動なので5Vと間違えないように注意する
  • BME280はESP32とI2C接続(CLKピンとSDAピン)をする。
  • ESP32の(IO2, IO15, IO12)ピンはプルダウンしておく
  • ESP32の(IO0, EN)ピンはプルアップしてスイッチでLOWにできるようにする。
  • ESP32とUSBシリアル変換機のUARTピン(TX, RX)は必ず交差して接続する。

この中で注意しなければいけないのは、ESP32のモードを決めるピン(IO0, EN, IO12)の配線とI2C接続(CLK, SDA)とコンデンサの重要性です。
IO0・ENピンをスイッチで切り替えられるようにしているのはIO0は書き込みモード、ENピンは起動をコントロールするための仕組みです。
IO12ピンはESP32に内蔵されているBASICの起動を操作するピンなので、ここがHIGHの状態だとBASICが起動してしまい書き込みもできませんし、プログラムも動きません。

ESP32のI2C接続はESP32側ではIO21ピンとIO22ピンを使っていきます。
IO22ピンはBME280のCLKへ、IO21ピンはBME280のSDAに接続しましょう。
* 注意:秋月で販売されているBME280モジュールはピンの名称が本来のI2Cで使用されるピンの名前と異なるので、マニュアルをみて相当するピンを接続しましょう。 akizukidenshi.com

コンデンサは今回二つ回路に組み込みましたが、特に電力供給用コンデンサを搭載しないとESP32がWiFIを利用したとき電力不足に陥り再起動してしまいます。
また、ノイズ防止用コンデンサを搭載しないとESP32に流れる電気が不安定になり動作不良を起こす可能性があり、電気の質が良くないとESP32からモスキート音がする場合もあります。

f:id:takumishinoda:20190202173012j:plain
実装、合体!

実際に実装してフリスクケースに収めたものが上の画像になります。
BME280は軽くグルーガンで底面に接着しています。
BME280はフリスクケース内につけているので、ESP32の熱で温度が周りより高くなるのでプログラム時は少し工夫がいります。

プログラム

今回はハードウェア回なのでサクッとプログラムの説明をします。
BME280から値をとるために使用したライブラリを下に載せておきます。 github.com
このライブラリを使用して最低限、値をとる関数は以下のようになります。

void getBME280Data(float *buff){
  float temp(NAN), hum(NAN), pres(NAN);
  BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
  BME280::PresUnit presUnit(BME280::PresUnit_Pa);

  bme.read(pres, temp, hum, tempUnit, presUnit);

  if(!std::isnan(temp)){
    *(buff) = temp;
    *(buff + 1) = hum;
    *(buff + 2) = pres;
  }else{
    *(buff) = std::numeric_limits<float>::quiet_NaN();
    *(buff + 1) = std::numeric_limits<float>::quiet_NaN();
    *(buff + 2) = std::numeric_limits<float>::quiet_NaN();
  }
}

使い方は、第一引数にfloat型の要素数3の配列ポインタを渡すと配列に温度、湿度、気圧の順で格納されます。
もし値が取れなかった場合、配列には「NaN(Not a Number)」が格納されます。
* 注意:この関数はこのままでは動作せず、BME280の初期化プログラムの後に処理させることで動作します。

次にBLEの最低限のプログラムです。

#include <Wire.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

#define DEVICE_NAME "BLE_TEST"
#define SERVICE_UUID "11111110-535d-450f-badb-10b0e18d608d"
#define CHARACTERISTIC_UUID "22222220-d562-48f3-9fbc-d11d605e3258"

bool deviceConnected = false;
BLECharacteristic *pCharacteristic;

class MyServerCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
  }

  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
  }
};

void setup(){
  BLEDevice::init(DEVICE_NAME);
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);

  pServer->setCallbacks(new MyServerCallbacks());
  pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);

  pService->start();
  pServer->getAdvertising()->start();
}

void loop(){
  uint8_t sendBuff[4] = {0x68, 0x6f, 0x67, 0x65};

  pCharacteristic->setValue(sendBuff, 4);
  pCharacteristic->notify();
  
  delay(500);
}

loop関数内でキャラクタリスティックオブジェクトのsetValue関数で送信する値をセットできます。
setValue関数は第一引数がuint8_t型の配列で、第二引数でその長さを渡します。
ここで注意すべきは第一引数はuint8_t型の配列なので、ArduinoString型やchar型配列では渡せないので、別途変換が必要になります。

ESP32でBLEを使うプログラムの簡単な説明ができましたが、ここでもう一つ大きな注意点があります。
それはコンパイルするとESP32のプログラムできる領域の約1MBを超えてしまい、コンパイルエラーがおきます。
おそらく頑張って最低限のプログラムにしても9割近くの領域はBLEのライブラリに持って行かれます。
そんな時は、ESP32の外付けROMのパーティションを変更してプログラム領域を広げます。
なお筆者はPlatformIoを使って開発していますので、以下の方法は「PlatformIo for VSCode」でのみ有効です。
今回はハードウェア回なので、細かい説明は次回以降にしますので今は以下の設定をplatform.iniに追記してください。

board_build.partitions = no_ota.csv

これによりパーティションが変更されプログラム領域が2倍の2MBに増やすことができます。
Arduino IDEで開発される方はこちらを参考にしてパーティションを変更できますが、この作業によるESP32および周辺機器の破損に関して責任は取れないので自己責任でよろしくお願いいたします。 www.mgo-tec.com
筆者が以上の知識を使ってBME280から取った値をBLEで飛ばすプログラムを作成してみたので、動作保証はできませんが参考にしたい方は下のURLからご覧ください。
*注意:プログラムした環境はPlatformIoです。 github.com

動作確認

f:id:takumishinoda:20190202171934j:plain
動作確認中
それではリポジトリのプログラムを動かしてみます。
下の図はAndroidでBLEをデバッグできる「BLE Scanner」でデバッグしている画像です。

f:id:takumishinoda:20190202171920p:plain

画像中央部にそれらしい値が送信されているのがわかります。

まとめ

  • BME280は少し高価だが小さくて温湿度気圧が簡単に取得できる
  • ESP32の電源はコンデンサをこだわるなど工夫が必要
  • ESP32でBLEを使うとプログラム領域が一気に持ってかれる
  • ESP32の外付けROMはパーティションを変更できる