はじめに
前回の記事では、BLE対応オリジナル土壌センサーのハードウェア構成について紹介した。
今回はArduino IDEを用いて、ESP32C3上で動作するソフトウェアについて紹介する。
今回実装する機能は次のとおりである。
- BLE通信
- 土壌温度の取得(DS18B20)
- 土壌水分量の取得(ADS1115)
- Deep Sleepによる低消費電力化
開発環境
開発環境は以下のとおり。
| 項目 | 内容 |
|---|---|
| IDE | Arduino IDE |
| CPU | Seeed Studio XIAO ESP32C3 |
| ライブラリ | DallasTemperature |
| ライブラリ | OneWire |
| ライブラリ | Adafruit ADS1X15 |
| ライブラリ | NimBLE-Arduino |
Arudino IDEでのESP32C3 の開発について
QiitaにはESP32C3 についての記事がたくさん投稿されている。
Arduino IDEでの開発についてはそちらの参照をお願いします。
ソースコード
ソースコード全体はGitHubに以下のURLで公開している。
ソースコードは各センサーとのアクセス部分を要点のみ解説する。
プログラム全体の流れ
センサーは常時動作するのではなく、一定時間ごとに起床し、測定が終われば再びDeep Sleepへ入る。
Deep Sleep
│
▼
起床
│
▼
DS18B20測定
│
▼
水分センサーON
│
▼
ADS1115測定
│
▼
BLE送信
│
▼
水分センサーOFF
│
▼
Deep Sleep
起床している時間は数百ms程度しかないため、電池寿命を長くすることができる。
使用ライブラリ
今回使用したライブラリは次の4つだけである。
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_ADS1X15.h>
#include <NimBLEDevice.h>
それぞれの役割は、
| ライブラリ | 用途 |
|---|---|
| OneWire | DS18B20通信 |
| DallasTemperature | 温度取得 |
| Adafruit ADS1X15 | ADS1115からA/D値をISPで取得する |
| NimBLE | BLE通信 |
である。
DS18B20で温度を取得する
まずは土壌温度を取得する。
初期化は非常に簡単で、
OneWire oneWire(PIN_TEMP);
DallasTemperature sensors(&oneWire);
void setup()
{
sensors.begin();
}
温度取得も数行で済む。
sensors.requestTemperatures();
float temp0 = sensors.getTempCByIndex(0);
float temp1 = sensors.getTempCByIndex(1);
今回は2本接続しているため、
- センサー0
- センサー1
を取得している。
ADS1115で土壌水分を取得する
次は土壌水分である。
まずADS1115を初期化する。
Adafruit_ADS1115 ads;
void setup()
{
ads.begin();
}
測定前だけGPIOからセンサーへ電源を供給する。
digitalWrite(PIN_SENSOR_POWER,HIGH);
delay(50);
int moisture0 = ads.readADC_SingleEnded(0);
int moisture1 = ads.readADC_SingleEnded(1);
digitalWrite(PIN_SENSOR_POWER,LOW);
このようにすることで、
- 電極の腐食防止
- 消費電力削減
を同時に実現している。
BLE通信
取得したデータはBLE Advertisementへ載せて送信している。
今回は接続型(GATT)ではなく、
Advertisementのみ
を利用した。
その理由は
- 消費電力が少ない
- Python側が受信しやすい
- 接続処理が不要
だからである。
送信データは以下の形式としている。
| データ | サイズ |
|---|---|
| Battery | 2Byte |
| Temperature0 | 2Byte |
| Temperature1 | 2Byte |
| Moisture0 | 2Byte |
| Moisture1 | 2Byte |
送信処理は以下のようになる。
まず、データ配列に各センサーの値をセットする。
uint8_t txData[12];
txData[0] = DEVICE_NO;
txData[1] = status;
txData[2] = battery & 0xFF;
txData[3] = battery >> 8;
// 水分量
txData[4] = moisture_ch0 & 0xFF;
txData[5] = moisture_ch0 >> 8;
txData[6] = moisture_ch1 & 0xFF;
txData[7] = moisture_ch1 >> 8;
// 温度
txData[8] = temp_ch0 & 0xFF;
txData[9] = temp_ch0 >> 8;
txData[10] = temp_ch1 & 0xFF;
txData[11] = temp_ch1 >> 8;
Advertising用のデータ構造に先ほどのデータ構造をセットする。
COMPANY_ID は、本センサーを識別するための適当な値。
// Advertisingデータ作成
NimBLEAdvertisementData advData;
advData.setFlags(BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP);
// Company ID = 0xFFFF(テスト用)
std::string mfg;
mfg.push_back(COMPANY_ID&0xff); // Company ID LSB
mfg.push_back((COMPANY_ID&0xff00)>>8); // Company ID MSB
mfg.append((char*)txData, sizeof(txData));
advData.setManufacturerData(mfg);
AdvertisingでBLE通信を開始する。
// Advertising開始
NimBLEAdvertising *adv = NimBLEDevice::getAdvertising();
adv->setAdvertisementData(advData);
adv->start();
Deep Sleep
測定が終わればESP32をDeep Sleepへ移行させる。
esp_sleep_enable_timer_wakeup(60ULL * 1000000ULL);
esp_deep_sleep_start();
今回は60秒ごとに起床している。
Deep Sleepを利用することで、待機中の消費電流を大幅に削減できる。
まとめ
今回はESP32C3を用いて、
- DS18B20
- ADS1115
- BLE
- Deep Sleep
を組み合わせた土壌センサーを作成した。
Arduinoライブラリが充実しているため、100行程度のコードで実現できた。
次回はPython側でBLEを受信するプログラムについて紹介する。
リンク
こちらは生成AIのちーちゃん(GPT5)にアドバイスをもらいながらAI/IoTを活用して家庭菜園にいそしんでいるブログです。よかったらこちらも見てやってください。