M5Stackで手軽に作る観葉植物育成デバイス

第3回:各種センサの結果をインターネットに接続して共有する

こんにちは、ヨシケンです!

小型のArduino互換機のM5Stackシリーズを使って、室内の植物を見守り、水やりなどを自動化するデバイスを作る今回の連載。今回はM5Stackにさらにセンサを追加して、植物周りの明るさも測れるようにします。また、植物の環境を楽しく分かりやすいようにM5Stackの画面に表示したり、インターネットに接続して植物の状況を遠隔からでも分かるようにします。植物を面白いキャラにしたりして、楽しく植物育成できるようになるかもしれませんよ。

grow-plants-device-03-01

M5Stackシリーズを使って観葉植物育成機作り

 

今回の記事で必要な物一覧

M5Stack Core

ESP32を搭載し、ディスプレイ、センサなども入ったArduino互換機

grow-plants-device-02-02-2

 

ローム照度・近接センサ (RPR-0521RS)

赤外線を発しその反射光を測定して、光の強度や近接度を計測します。

grow-plants-device-03-02

 

DHT11温湿度センサ

温度と湿度が両方測れるデジタル温湿度センサモジュール

grow-plants-device-03-03

 

水分センサ

土中の水分量を計測

grow-plants-device-03-04

 

今回の記事の流れ

  1. 照度・近接センサの設定
  2. M5Stackを使ってLINEに通知
  3. 植物の状況、計測結果を定期的にLINEに送付
  4. まとめ

 

1. 照度・近接センサの設定

M5Stackにさらにセンサを追加して、植物の日当たりを確認したいと思います。植物周りの明るさを測るために照度センサというものがあり、今回はロームセンサ評価キットの照度・近接一体型センサモジュール(RPR-0521RS)を使ってみます。

grow-plants-device-03-05

 

このセンサは、赤外線LEDを発し、その反射光を検知することによりその明るさを測定します。このセンサを使うためにも同様に、ローム・センサのページからzipファイルをダウンロードし、Arduino IDEメニューからRPR-0521RS用のライブラリをインストールします。

grow-plants-device-03-06

 

サイト中にあるzipファイルをダウンロードし、Arduino IDEのライブラリをインクルード メニューからインストールします。

ソフトウェアがインストールできたら、M5Stackと照度・近接センサをつないでみます。照度・近接センサはI2Cという通信方式を使うので、以下、表に従ってI2C通信が可能なSDA=G21とSCL=G22と接続してください。

grow-plants-device-03-07

 

センサ側端子 (右から) M5Stack側(下部)
VDO 3.3V (オレンジ)
GND GND (青)
SDA GPIO21 (黄)
SCL GPIO22 (緑)
INT NA

センサとM5Stackをつないだら、Arduino IDEのスケッチ例のところから、先ほどインストールしたサンプルスケッチを選びます。ArduinoIDEでサンプルのPRP-0521RSを選びます。今後これをカスタマイズして使っていくので、M5Stack_Sensors.inoなどとして別名保存しておいてください。そこに以下のようなプログラムを追加します。

以下のようなスケッチが開いたら、その一番上に

#include <M5Stack.h>

の記述を追加します。その後、左上の書き込みボタン押して、このサンプルスケッチをM5Stackに流し込んでみましょう。
13、19行目の Wire.begin(21,22) は、M5StackでI2Cを使うための宣言になります。

[M5Stack_Light.ino]

#include <M5Stack.h>

#include <Wire.h>
#include <RPR-0521RS.h>

RPR0521RS rpr0521rs;

void setup() {
  byte rc;
  Serial.begin(9600);
  while (!Serial);
  
  Wire.begin(21,22);
  
  rc = rpr0521rs.init();
}

void loop() {
  Wire.begin(21,22);
  byte rc;
  unsigned short ps_val;
  float als_val;
  byte near_far;
  
  rc = rpr0521rs.get_psalsval(&ps_val, &als_val);
  if (rc == 0) {
    Serial.print(F("RPR-0521RS (Proximity)     = "));
    Serial.print(ps_val);
    Serial.print(F(" [count]"));
    near_far = rpr0521rs.check_near_far(ps_val);
    if (near_far == RPR0521RS_NEAR_VAL) {
      Serial.println(F(" Near"));
    } else {
      Serial.println(F(" Far"));
    }
    if (als_val != RPR0521RS_ERROR) {
      Serial.print(F("RPR-0521RS (Ambient Light) = "));
      Serial.print(als_val);
      Serial.println(F(" [lx]"));
      Serial.println();
    }
  }
  delay(500);
}

このプログラムをM5Stackで使う際、ひとつ変更が必要です。PRP-0521RS.cppというファイルを開いて、#include <pgmspace.h>として”avr/”を取り除きます。(通常、インストールしたライブラリは、Arduino > Libraries > RPR-0521RS 内にあります)
こうすることにより、M5Stackでpgmspace.hを正常に読み取ることができるようになります。

grow-plants-device-03-08

PRP-0521RS.cppの場所、変更前。赤枠部分から”avr/”を取り除く。

 

この変更が済んだら、M5Stack_Sensors.inoを実行します。自動的に計測を始め、室内の明るさをルクスで示してくれたと思います。

grow-plants-device-03-09

室内の明るさを計測

 

2. M5Stackを使ってLINEに通知

植物周りの明るさ、温湿度、土中の水分量が測れたので、その結果を外部からでも分かるようにしましょう。M5StackはWi-Fiが内蔵されていて、インターネットにも簡単につなぐ事ができるので、計測結果をLINEに通知するようにしてみます。

まず、M5StackとLINEを連携していきましょう。LINEにはLINE Notifyという外部から通知を送る仕組みがあり、無料で使えるのでそれとM5Stackを接続できるようにします。最初にこちらのリンクからLINE Notifyに登録をおこないます。

https://notify-bot.line.me/ja/

右上のメニューからLINEアカウントでログインします。

grow-plants-device-03-10

 

アクセストークンの発行画面があるので、「トークンを発行する」をクリックします。

grow-plants-device-03-11

 

通知の送り先、またはグループを選びます。指定したグループにLINE Notifyを招待しておきます。

grow-plants-device-03-12

 

選んでトークンを発行します。このトークンはこの時一度しか表示されないので、確実にコピーしておいてください。

grow-plants-device-03-13

grow-plants-device-03-14

 

これで、LINEで投稿する設定ができました。それではこれをM5Stackのスケッチで使ってみましょう。
まずWi-Fiとの接続と、LINEに投稿するスケッチは以下のようになっています。

M5Stack_Line.ino

#include <M5Stack.h>
#include <ssl_client.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
WiFiClient client;

const char* ssid = "YOUR SSID";
const char* password = "YOUR PASSWORD";

void send(String message) {
  const char* host = "notify-api.line.me";
  const char* token = "YOUR TOKEN";
  WiFiClientSecure client;
  Serial.println("Try");
  client.setInsecure();
  if (!client.connect(host, 443)) {
    Serial.println("Connection failed");
    return;
  }
  Serial.println("Connected");
  String query = String("message=") + message;
  String request = String("") +
                   "POST /api/notify HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" +
                   "Authorization: Bearer " + token + "\r\n" +
                   "Content-Length: " + String(query.length()) +  "\r\n" +
                   "Content-Type: application/x-www-form-urlencoded\r\n\r\n" +
                   query + "\r\n";
  client.print(request);

  while (client.connected()) {
    String line = client.readStringUntil('\n');
    Serial.println(line);
    if (line == "\r") {
      break;
    }
  }

  String line = client.readStringUntil('\n');
  Serial.println(line);
}

void setup() {
  M5.begin();
  WiFi.begin(ssid, password);
}

void loop() {
  M5.update();
  if (M5.BtnA.pressedFor(100)){
    M5.Lcd.print('L');
    send("左ボタン");
  } else if (M5.BtnB.pressedFor(100)) {
    M5.Lcd.print('C');
    send("中ボタン");
  } else if (M5.BtnC.pressedFor(100)) {
    M5.Lcd.print('R');
    send("右ボタン");
  }
}

このスケッチでは、M5StackからWi-Fiに接続するために、<WiFiClientSecure.h>のライブラリを読み込みます。スケッチ中の”YOUR SSID”と”YOUR PASSWORD”にはご自宅のWi-FiのID、パスワードを入れます。また”YOUR TOKEN”には先ほどコピーしたLINE Notifyのトークンをペーストします。このプログラムはM5Stack前面にあるボタンを押すと、特定のメッセージをLINEに送るようになっています。

これでまずLINEに結果が投稿できるかテストしてみましょう。M5StackがWi-Fiに接続できたら、左、真ん中、右側のボタンを押してみて下さい。

grow-plants-device-03-15

 

このように先ほど接続設定したLINEグループに投稿が送られたら、M5StackとLINEの連携ができたことになります。

 

3. 植物の状況、計測結果を定期的にLINEに送付

M5Stackに接続した温室度センサ、水分センサ、照度センサの結果について、ボタンを押したら送信してくれるようにしましょう。また、ある値を超えたらLINEに送って、状況を把握できるようにします。

前面左側のボタンを押したら、温度と湿度を送信します。真ん中のボタンは水分量、右側は明るさをLINEに通知します。ある値を超えた時のメッセージとして、例えば室温が30℃以上になっていたら「暑いよー!」と警告しています。水分量が少ない時(数値が300以下)には、「喉が渇いたよ!お水ください!」としたら面白いかもしれません。

grow-plants-device-03-16

 

そんなプログラムを先ほどのスケッチに追加して作ります。

[M5Stack_sensors_line.ino]

#include <M5Stack.h>
#include <DHT.h>
#include <Wire.h>
#include <RPR-0521RS.h>
RPR0521RS rpr0521rs;

#include <ssl_client.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
WiFiClient client;

const char* ssid = "YOUR SSID";
const char* password = "YOUR PASSWORD";

void send(String message) {
  const char* host = "notify-api.line.me";
  const char* token ="YOUR TOKEN";
  WiFiClientSecure client;
  Serial.println("Try");
  client.setInsecure();
  if (!client.connect(host, 443)) {
    Serial.println("Connection failed");
    return;
  }
  Serial.println("Connected");
  String query = String("message=") + message;
  String request = String("") +
                   "POST /api/notify HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" +
                   "Authorization: Bearer " + token + "\r\n" +
                   "Content-Length: " + String(query.length()) +  "\r\n" +
                   "Content-Type: application/x-www-form-urlencoded\r\n\r\n" +
                   query + "\r\n";
  client.print(request);

  while (client.connected()) {
    String line = client.readStringUntil('\n');
    Serial.println(line);
    if (line == "\r") {
      break;
    }
  }

  String line = client.readStringUntil('\n');
  Serial.println(line);
}


// 使用するピン
const int PIN_DHT = 5;
DHT dht(PIN_DHT,DHT11);

void setup() {
  M5.begin();
  
  WiFi.begin(ssid, password);

  dht.begin();
  byte rc; 
  rc = rpr0521rs.init();
}

uint16_t analogRead_value = 0;

void loop() {
  M5.update();
  delay(3000);
  // 湿度を取得
  float humidity = dht.readHumidity();
  // 温度を取得
  float temperature = dht.readTemperature();

  analogRead_value = analogRead(36);

  Wire.begin(21,22);
  byte rc;
  unsigned short ps_val;
  float als_val;
  rc = rpr0521rs.get_psalsval(&ps_val, &als_val);

    if (als_val != RPR0521RS_ERROR) {
      Serial.print(F("RPR-0521RS (Ambient Light) = "));
      Serial.print(als_val);
      Serial.println(F(" [lx]"));
      Serial.println();
    }

  M5.Lcd.clear(BLACK);

  if ( (temperature > 30) or (analogRead_value < 300) ) {
    M5.Lcd.fillScreen(TFT_RED);
    send("暑いよ〜、温度"+String(temperature,1)+"Cが高すぎるか、水分不足です!");
  }  else if ( (temperature < 10) ) {
    M5.Lcd.fillScreen(TFT_BLUE);
    send("寒すぎ!温度"+String(temperature,1)+"Cが低いです!");
  }

  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.drawString("M5STACK SENSORS",0,0,4);
  
  M5.Lcd.setTextColor(YELLOW);
  M5.Lcd.drawString("Humidity:",0,30,4);
  M5.Lcd.drawFloat(humidity, 0, 0, 50, 4); 
  M5.Lcd.drawString("%",50,50,4); 

  M5.Lcd.setTextColor(GREEN);
  M5.Lcd.drawString("Temperature:",0,80,4);
  M5.Lcd.drawFloat(temperature, 0, 0, 100, 4);
  M5.Lcd.drawString("C",50,100,4);
  
  M5.Lcd.setTextColor(BLUE);
  M5.Lcd.drawString("Moisture:",0,130,4);
  M5.Lcd.drawFloat(analogRead_value, 0, 0, 150, 4);

  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.drawString("Light:",0,180,4);
  M5.Lcd.drawFloat(als_val, 0, 0, 200, 4);

  if (M5.BtnA.pressedFor(100)){
    send("温度は"+String(temperature,1)+"C、湿度は"+String(humidity,1)+"%です!");
  } else if (M5.BtnB.pressedFor(100)){
    send("水分は"+String(analogRead_value)+"です!");
  } else if (M5.BtnC.pressedFor(100)){
    send("明るさは”+String(als_val,1)+”Lxです!"); 
  }
}

このスケッチを流し込み、植物周りにセットして、使ってみましょう。まず左、真ん中、右側のボタンを押します。そうすると以下のように計測結果をLINEに通知してくれます。

grow-plants-device-03-17

grow-plants-device-03-18

 

また室温が30℃以上になった時などは、このようなメッセージで警告してくれます。

grow-plants-device-03-19

 

4. まとめ

今回はM5Stackに、ロームの照度センサを接続して、明るさを計測しました。これで、明るさ、温度、湿度、土中の水分量が計測できたので、これをLINEに送信して、外からでも植物の状況を見えるようにしました。他にもWi-Fiでインターネットに接続できることを活かして、遠隔から操作したり、Twitterなどにも投稿できますね。

次回はいよいよ自動で水をあげる機構を作って、植物の状況により自動で水やりしたり、外部からコントロールできるようにしたいと思います。お楽しみに!

電子工作マニュアル Vol.3
ヨシケン(吉田 顕一)

普通の会社に勤めるサラリーマンですが、モノ作りが好きな週末メイカーで、電子書籍MESHBOOKを出したり、ブログを書いたりしています!

http://blog.ktrips.net