ESP32でAdafruit STEMMA Soil Sensorを使って土壌水分量と温度の測定

ESP32でAdafruit STEMMA Soil Sensorを使って土壌水分量と温度の測定

この記事では、ESP32を使った「Adafruit STEMMA Soil Sensor」の土壌センサの使い方を解説いたします。「Adafruit STEMMA Soil Sensor」は静電容量型の土壌水分量を測定できるセンサです。温度センサも内蔵されており、外気温を測ることも可能です。I2C接続ですが、Adafruitさんからseesawというライブラリが公開されてますので、それを使えばカンタンに土壌水分量と温度が測れちゃいます。ぜひご参考になさってみてください。

つかうもの

この記事でつかうものをご紹介いたします。

Adafruit STEMMA Soil Sensor

Adafruit STEMMA Soil SensorはI2C接続の静電容量型土壌センサーです。土壌の水とは非接触なので錆びにくいセンサーです。またI2C接続のセンサで、温度センサのチップも内蔵されています。

スペックは以下の通りです。

項目
使用チップ ATSAMD10D14A
電源 3~5V
コネクタ JST-PH4ピン
接続 I2C(7bitアドレス0x36)

▼ 秋月電子通商電子さんからも購入できます。

JST-PH4ピンケーブル

Adafruit STEMMA Soil SensorにはJST-PHの4ピンが設置されています。それに対応するケーブルを持っている方は少ないと思いますので、別途購入する必要がります。私は下記商品を購入しました。

ESP32

WayinTopさんから販売されているESP32を使用しました。技適マークも刻印されていますので、安心して国内で使えます。GPIOの役割図は 商品ページ に詳しく掲載されていますのでご参考ください。

▼ WiFiやBluetooth接続が必要なければ、他のArduinoでも構いません。こちらの記事で色々な種類のArduinoをご紹介していますので、ご参考になさってみてください。

その他

また、ブレッドボードやジャンプワイヤもあると便利です。

ライブラリのインストール

Arduino seesawライブラリがAdafruitさんにより用意されていますのでそれを使います。下記サイトから最低限 Adafruit_seesawAdafruit_I2CDevice が必要になります。

私はPlatformIOで開発してますので、必要なソースファイルだけダウンロードして次のようなディレクトリ構造で配置しました。もちろんライブラリマネージャーを使ってインストールしてもらっても構いません。

.
├── include
│   └── README
├── lib
│   ├── Adafruit_Seesaw
│   │   ├── Adafruit_I2CDevice.cpp
│   │   ├── Adafruit_I2CDevice.h
│   │   ├── Adafruit_seesaw.cpp
│   │   ├── Adafruit_seesaw.h
│   │   └── examples
│   │       └── soil_sensor
│   │           └── soilsensor_example
│   │               └── soilsensor_example.ino
│   └── README
├── platformio.ini
├── src
│   └── main.cpp
└── test
    └── README

土壌センサとESP32の配線

土壌センサ(Adafruit STEMMA Soil Sensor)とESP32の配線は次の通りになります。JST-PH4ピンケーブルの配色が混乱しやすいので間違えないように配線しましょう。下図ではあえてJST-PH4ピンケーブルの配色に合わせ描いています。

土壌センサとESP32の配線
土壌センサとESP32の配線

▼ この土壌センサの電源は、3〜5Vの範囲で動かせるようです。Arduino Unoで配線する場合は、下記の公式サイトが参考になると思います。

動作テストプログラム(ソースコード)

次のソースコードは動作テストプログラムです。土壌センサはI2C接続ですが、ライブラリのおかげで難しいことは考えずにカンタンにデータを取得できます。温度と静電容量の値をシリアルモニタに表示します。

/**
 * @date 2022-11-24
 * @brief Adafruit STEMMA Soil Sensor Test
 *        https://learn.adafruit.com/adafruit-stemma-soil-sensor-i2c-capacitive-moisture-sensor/arduino-test
 *        Modified by Toshihiko Arai (https://101010.fun)
 */
#include "Adafruit_seesaw.h"

/**
 * @brief ESP32 <-> Adafruit STEMMA Soil Sensor 配線
 *        3V3   <->    3V3
 *        GND   <->    GND
 *        SCL   <->    IO22
 *        SDA   <->    IO21
 */
Adafruit_seesaw ss;

void setup() {
    Serial.begin(115200);

    if (!ss.begin(0x36)) {
        Serial.println("ERROR! seesaw not found");
        while (1) delay(1);
    } else {
        Serial.print("seesaw started! version: ");
        Serial.println(ss.getVersion(), HEX);
    }
}

void loop() {
    float tempC = ss.getTemp();
    uint16_t capread = ss.touchRead(0);

    Serial.print("Temperature: ");
    Serial.print(tempC);
    Serial.println("*C");
    Serial.print("Capacitive: ");
    Serial.println(capread);
    delay(1000);
}

Adafruit STEMMA Soil Sensorは下図のように、センサの緑色の部分を土壌に埋めます。温度の感知は半導体基板の部分にありますので、外気温を測ることになります。

土壌センサの設置
土壌センサの設置

土壌センサーをプランターなどで実際に運用する場合は、こちらの記事が参考になるかと思います。

さいごに

さいごに、ツイートの動画にあるように、TFT LCDを使って温度と水分量の値をモニター表示させてみました。動画のディスプレイはST7789搭載のCS(チップセレクト)のないものです。ですから複数のSPIデバイスを接続することはできませんが、I2Cデバイスならいくつでもつなぐことができます。

上記の動画のソースコードは次の通りです。何かのご参考になさってみてください。

/**
 * @date 2022-11-24
 * @copyright https://101010.fun
 * @author Toshihiko Arai
 * @brief Adafruit STEMMA Soil Sensor with TFT LCD ST7789
 */
#include <Adafruit_GFX.h>     // Core graphics library
#include <Adafruit_ST7789.h>  // Hardware-specific library for ST7789
#include <Arduino.h>
#include <Org_01.h>
#include <SPI.h>

#include "Adafruit_seesaw.h"

/**
 * @brief ESP32 <-> Adafruit STEMMA Soil Sensor 配線
 *        3V3   <->    3V3
 *        GND   <->    GND
 *        SCL   <->    IO22
 *        SDA   <->    IO21
 */
Adafruit_seesaw ss;

/**
 * @brief TFT  <-->  ESP32
 *        GND  <-->  GND
 *        VCC  <-->  3V3
 *        SCL  <-->  18
 *        SDA  <-->  23
 *        RES  <-->  4
 *        DC   <-->  2
 *        BLK  <-->  x
 */
#define TFT_CS 10  // CS端子がないので実際には接続しない
#define TFT_RST 4
#define TFT_DC 2

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

const uint16_t TEMPERATURE_BGCOLOR = ST77XX_RED;
const uint16_t CAPACITY_BGCOLOR = ST77XX_BLUE;
const uint16_t FONT_COLOR = ST77XX_WHITE;

/**
 * @brief
 * int mode
 * 0 = 0b00
 * 1 = 0b01 上半分をクリア
 * 2 = 0b10 下半分をクリア
 * 3 = 0b11 全画面をクリア
*/
void clearDisplay(int mode) {
    if(mode & 1 == 1) {
        tft.fillRect(0, 0, tft.width(), tft.height() / 2, TEMPERATURE_BGCOLOR);
    } else if (mode >> 1 == 1) {
        tft.fillRect(0, tft.height() / 2, tft.width(), tft.height() / 2,
                 CAPACITY_BGCOLOR);
    }
}

void setup() {
    Serial.begin(115200);

    tft.init(240, 240, SPI_MODE2);  // SPI_MODE2指定しないと動かない
    delay(1000);
    tft.setRotation(3);  // 画面を回転させる
    clearDisplay(0b11);

    if (!ss.begin(0x36)) {
        Serial.println("ERROR! seesaw not found");
        while (1) delay(1);
    } else {
        Serial.print("seesaw started! version: ");
        Serial.println(ss.getVersion(), HEX);
    }
}

float lastTemperature = -999;
uint16_t lastCapacity = -999;

void loop() {
    char temperatureBuff[10];
    char capacityBuff[10];

    float temperature = ss.getTemp();
    uint16_t capacity = ss.touchRead(0);

    if (temperature != lastTemperature) {
        lastTemperature = temperature;
        clearDisplay(0b01);
    }

    if (capacity != lastCapacity) {
        lastCapacity = capacity;
        clearDisplay(0b10);
    }

    /**
     * @brief dtostrf(変換する値, 小数点や符号を含んだ変換後の文字数,
     * 小数点以下の桁数, 変換後の文字列を格納する変数)
     */
    char tempCFloatString[10];
    dtostrf(temperature, 4, 1, tempCFloatString);

    sprintf(temperatureBuff, "%s",
            tempCFloatString);  // 数字を右寄せで表示させるため
    sprintf(capacityBuff, "%2d", capacity);


    tft.setTextWrap(false);
    tft.setFont(&Org_01);
    tft.setTextColor(FONT_COLOR);


    tft.setTextSize(2);
    tft.setCursor(20, 20);
    tft.println("Temperature");
    tft.setCursor(20, 140);
    tft.println("Moisture");

    tft.setTextSize(10);
    tft.setCursor(20, 80);
    tft.println(temperatureBuff);
    tft.setCursor(20, 200);
    tft.println(capacityBuff);

    delay(500);
}

TFT LCDの使い方は、こちらの記事をご覧ください。

手で触れると静電容量の値が1000ほどになりますが、水に浸けても500程度にしかなりません。今まで使ってきた安物の土壌センサーですと、手で触っても水に浸けても同じように値が変化してしまったので、こちらのセンサーの方がより正確な土壌水分量を測定できるかもしれません。

温度と水分量のモニター表示実験
温度と水分量のモニター表示実験

水につけた時の水分量
水につけた時の水分量

手で触れた時の水分量
手で触れた時の水分量

ちなみに、ESP32をMacbookにマウントしてスタバでも開発できるようにするホルダーはこちらです。3Dプリンタをお持ちの方はThingiverseからSTLファイルをダウンロードできますので、ぜひ使ってみてください^^

「キッチンノート.fun」という料理サイトを立ち上げました!このサイトで紹介していた料理記事は、そちらへ移動しました。
記事に関するご質問などがあれば、
Twitter または お問い合わせ までご連絡ください。
関連記事