サイトロゴ

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

著者画像
Toshihiko Arai

はじめに

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

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

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ピンケーブルの配色に合わせ描いてます。

▼ この土壌センサの電源は、3〜5Vの範囲で動かせるようです。Arduino Unoで配線する場合は、下記の公式サイトが参考になります。 https://adafruit.github.io/Adafruit_Seesaw/html/class_adafruit__seesaw.html

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

次のソースコードは動作テストプログラムです。土壌センサは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);
}

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

ちなみに、ESP32をMacbookにマウントしてスタバでも開発できるようにするホルダーをThingiverseで公開中です。ぜひご活用ください^^ https://www.thingiverse.com/thing:5424812

関連記事