M5Stack用のGrove接続する土壌水分センサユニット(Earth Sensor)をM5 Atom Liteに接続して、データをBLEでブロードキャストしてみました。
ついでにラズパイでBLEを受信してみました。
土壌水分センサユニット(Earth Sensor)
こちらのセンサーはアナログ出力を持っていますので、M5側もアナログ端子に接続する必要があります。
幸いM5 Atom LiteのGrove端子はアナログ入力に対応しているようなので、Groveで接続OKです。
M5Stack用土壌水分センサユニット – SwitchScience
https://www.switch-science.com/catalog/4049/
EARTH – 公式ページ
https://docs.m5stack.com/#/en/unit/earth
M5Atom プログラム
M5Stack用のサンプルを基にIOピンを analogRead(36) から M5Atom 用に anaogRead(32) へ変更します。
LCD表示も削除しています。
setAdvData() でBLEのadvertisement packet dataにTest Manufacturer の0xffffとしてanalogReadを2バイト、digitalReadを1バイトでセットしています。
10分間隔でBLEブロードキャストします。
GitHub – github.com/tyamazoe/EarthMonitor
https://github.com/tyamazoe/EarthMonitor
BLE Advertisement packet Manufacturer specific data
項目 | バイト | 値 |
manufacture id | 2 | 0xffff テスト用 manufacturer |
device_id | 2 | 任意のID 例: 0x0101 |
analogRead_value | 2 | 0x0000 – 0x0fff 水分センサアナログ値 0 – 4095 |
digitalRead_value | 1 | 0x00 / 0x01 水分センサデジタル値 0/1 |
#include "M5Atom.h"
#include "BLEDevice.h"
#include "BLEUtils.h"
#include "BLEBeacon.h"
#include "esp_sleep.h"
#define GPIO_DEEP_SLEEP_DURATION 600 // sleep x seconds and then wake up
uint16_t analogRead_value = 0;
uint16_t digitalRead_value = 0;
uint16_t device_id = 0x0101; // your any sensor device id
BLEAdvertising *pAdvertising;
void readEarthSensor() {
analogRead_value = analogRead(32);
digitalRead_value = digitalRead(26);
Serial.printf("0x%04x, %d, %d\n", device_id, digitalRead_value, analogRead_value);
}
void setAdvData() {
BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
oAdvertisementData.setFlags(0x06); // BR_EDR_NOT_SUPPORTED | LE General Discoverable Mode
std::string strServiceData = "";
strServiceData += (char)0x08; // length
strServiceData += (char)0xff; // AD Type 0xFF: Manufacturer specific data
strServiceData += (char)0xff; // Test manufacture ID
strServiceData += (char)0xff; // Test manufacture ID
strServiceData += (char)((device_id >> 8) & 0xff);
strServiceData += (char)(device_id & 0xff);
strServiceData += (char)((analogRead_value >> 8) & 0xff);
strServiceData += (char)(analogRead_value & 0xff);
strServiceData += (char)(digitalRead_value & 0xff);
oAdvertisementData.addData(strServiceData);
pAdvertising->setAdvertisementData(oAdvertisementData);
}
void setup() {
M5.begin(true, false, true);
delay(10);
Serial.begin(115200);
M5.dis.clear();
pinMode(26, INPUT);
Serial.println("\nEarth Test");
// Create the BLE Device
BLEDevice::init("Earth_Beacon");
pAdvertising = BLEDevice::getAdvertising();
// Read earth sensor value
readEarthSensor();
// set advertizing packet data
setAdvData();
// Start advertising
pAdvertising->start();
Serial.println("Advertizing started...");
delay(1200);
pAdvertising->stop();
Serial.printf("enter deep sleep\n");
esp_deep_sleep(1000000LL * GPIO_DEEP_SLEEP_DURATION);
Serial.printf("in deep sleep\n");
}
void loop() {
}
参考:M5Stack用サンプル EARTH.ino
https://github.com/m5stack/M5Stack/blob/master/examples/Unit/EARTH/EARTH.ino
ラズパイ用 BLE 受信 python プログラム
BLEライブラリに bluepy を使用しています。
# -*- coding: utf-8 -*-
from bluepy.btle import DefaultDelegate, Scanner, BTLEException
import sys
import struct
import time
class ScanDelegate(DefaultDelegate):
def __init__(self):
DefaultDelegate.__init__(self)
def handleDiscovery(self, dev, isNewDev, isNewData):
#print("addr: {0}, addrType: {1}, rssi: {2}".format(dev.addr, dev.addrType, dev.rssi))
if isNewDev or isNewData:
for (adtype, desc, value) in dev.getScanData():
if desc == 'Manufacturer':
#print(adtype, desc, value)
if value[0:4] == 'ffff':
#print("addr: {0}, addrType: {1}, rssi: {2}".format(dev.addr, dev.addrType, dev.rssi))
self.parseManufacturerData(value[4:])
def parseManufacturerData(self, data):
(id, a_dat, d_dat) = struct.unpack('>HHb', bytes.fromhex(data[0:]))
print("deviceId: 0x{0:04x}, analogRead: {1}, digitalRead: {2}".format(id, a_dat, d_dat))
if __name__ == "__main__":
scanner = Scanner().withDelegate(ScanDelegate())
while True:
try:
scanner.scan(3.0)
except BTLEException:
print(BLEException)
実行するとBLEで受信したデータのアナログ値とデジタル値を表示します。
pi@raspi:~/earth $ sudo python3 earth_scan.py
deviceId: 0x0101, analogRead: 4095, digitalRead: 1
deviceId: 0x0101, analogRead: 4095, digitalRead: 1
deviceId: 0x0101, analogRead: 4095, digitalRead: 1
モニタリングしてみる
鉢植えにセットしてみました。
ラズパイからambientに送信してみました。水をやった直後にアナログ値が 2000 程度に低下しています。
約2日間で 1000 上昇しているので、アナログセンサー値の最大値である 4095に向けて徐々に上昇しています。水分が減ってきていることが伺えます。
なお、最初に別の観葉植物で試したところ、土がふんわりした植木だったので、水はあっというまにしみこんで12時間ほどで水分を検知しなくなりました。
まとめ
無事に水分をモニタリングすることができました。
M5AtomはLCDが無いので、水分量でLEDの色点滅で水不足を知らせてもよいかもしれません。
電源を太陽光発電でまかなって、屋外に設置して太陽光発電ラズパイカメラと連携したいですね。これは次の課題。