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

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)

▼ 秋月電子通商電子さんからも購入できます。 Adafruit STEMMA Soil Sensor − I2C CapacitiveMoisture Sensor: マイコン関連 秋月電子通商-電子部品・ネット通販

JST-PH4ピンケーブル

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

ESP32

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

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

その他

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

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

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

GitHub - adafruit/Adafruit_Seesaw: Arduino library driver for seesaw multi-use chip GitHub - adafruit/Adafruit_BusIO: Arduino library for I2C & SPI abstractions

私は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で配線する場合は、下記の公式サイトが参考になります。 Adafruit Library: Adafruit_seesaw Class Reference

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

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

soilsensor_example.ino
/**
 * @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デバイスならいくつでもつなぐことができます。

温度(外気温)も測れ、「水」と「手」で触れた時の反応が違うのも良いですね💡 安物の土壌センサとここら辺が区別しずらいです。

上記の動画のソースコードは次の通りです。

with_display.ino
/**
 * @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にマウントしてスタバでも開発できるようにするホルダーをThingiverseで公開中です。ぜひご活用ください^^

▼ 土壌センサを防水加工し、ブレッドボードにさせるよう改造しました! \メルカリで販売中/

関連記事

最後までご覧いただきありがとうございます!

▼ 記事に関するご質問やお仕事のご相談は以下よりお願いいたします。
お問い合わせフォーム

スマート農業(スマートアグリ)で使えるセンサー
水耕栽培はじめよう!
関連記事