はじめに
オムロンの非接触温度センサ「D6T」がGroveコネクタで使えるようになったようです。
Githubでサンプルコードも公開されているので、これを参考にして簡単な人感システム?のようなものを作ってみようと思います。
開発環境
- macOS Sierra
- Arduino IDE 1.8.8
概要
- 計測
D6Tで温度を計測してGroveコネクタ経由でM5Stackへ送る - 判定
受け取った温度を元に人がいるか判定 - 通知
IFTTTでWebhookを作成しスマホのLINEへ通知
用意するもの
- M5Stack
- Grove 4ピンケーブル
- 非接触温度センサD6T 変換基板
- 非接触温度センサD6T 本体
- IFTTT アカウント
- LINE アカウント
実装
1. 計測
まずハードウェア側の準備ですが、D6Tの変換基盤とM5StackはどちらもGroveに対応しているので、4ピンケーブルでコネクタを繋ぐだけでOKです。
ソフトウェア側はGithubでライブラリが公開されていますので、これを使います。
まず、Clone of download
ボタンからDownload ZIP
を選択し、ソースコードをダウンロードします。
次にArduino IDE
を起動しスケッチ
→ライブラリをインクルード
→.ZIP形式のライブラリをインストール
を選んでダウンロードしたzipを指定します。
ライブラリの取り込みに成功すればファイル
→スケッチ例
からOmron D6T-Grove-M5Stack
が選択できるようになっているはずです。
サンプルは2種類用意されていて、value_sample
は計測値をLCDディスプレイに出力するシンプルなもの、coolwarm_sample
は計測値をサーモグラフのように可視化したものです。
温度の計測はサンプルコードを動かすだけで実現できました。
次はcoolwarm_sample
をベースにして、計測値の判定と通知の実装をやってみます。
2. 判定
ひとまず、coolwarm_sample
を読んでみます。
表示する色を7段階に分けて定義しているようです。
int color[7];
int range_min = 25;
int range_max = 35;
uint16_t rgbToColor(uint8_t red, uint8_t green, uint8_t blue){
return ((red>>3)<<11) | ((green>>2)<<5) | (blue>>3);
}
void initColormap() {
color[0] = rgbToColor(76,134,228);
color[1] = rgbToColor(127,178,248);
color[2] = rgbToColor(177,208,245);
color[3] = rgbToColor(221,220,219);
color[4] = rgbToColor(252,194,173);
color[5] = rgbToColor(255,151,125);
color[6] = rgbToColor(234,94,78);
}
int getRangeColor(float temperature) {
float range = range_max - range_min;
float block = range / 7;
if (temperature < range_min) {
return 0;
} else if (temperature < (range_min + block)) {
return 1;
} else if (temperature < (range_min + (block * 2))) {
return 2;
} else if (temperature < (range_min + (block * 3))) {
return 3;
} else if (temperature < (range_min + (block * 4))) {
return 4;
} else if (temperature < (range_min + (block * 5))) {
return 5;
} else {
return 6;
}
}
通知を飛ばすための判定基準として、16個の計測値のいずれか3つ以上が7段階のうち下から2番目以上になった場合に、人を検知したと判断するようにしてみようと思います。
coolwarm_sample
のメインループを改修します。
struct tm detect_time; // 検知時刻を格納するtm構造体
char format_time[20]; // 出力文字格納用
~中略
void loop() {
int upsell = 0; // セル
int detect_flg = 0; // 検知フラグ
sensor.scanTemp();
int16_t rectw = (M5.Lcd.width() / 4);
int16_t recth = (M5.Lcd.height() / 4);
Serial.println("-------------------------");
int x, y;
for (y = 0; y < 4; y++) {
for (x = 0; x < 4; x++) {
float temperature = sensor.temp[x][y];
int rangecolor = getRangeColor(temperature);
Serial.print("temperature:");
Serial.print(sensor.temp[x][y]);
Serial.print(" rangecolor:");
Serial.println(rangecolor);
// 温度を検知して変化したセルをカウント
if (rangecolor > 1) {
upsell++;
}
M5.Lcd.fillRect((rectw * x), (recth * y), rectw, recth, color[rangecolor]);
}
Serial.println("");
if (upsell > 2 && detect_flg != 1) {
// 検出フラグをたてる
detect_flg = 1;
}
}
if (detect_flg == 1) {
Serial.println("誰かいる");
// 検知した日時を取得
getLocalTime(&detect_time);
sprintf(format_time, "%04d/%02d/%02d-%02d:%02d:%02d",
detect_time.tm_year + 1900, detect_time.tm_mon + 1, detect_time.tm_mday,
detect_time.tm_hour, detect_time.tm_min, detect_time.tm_sec);
// IFTTTのWebhookに投げる
send_webhook("HumanDetection!!", "OwnSeat", String(format_time));
} else {
Serial.println("誰もいない");
}
delay(3000);
}
判定条件を満たした際はdetect_flg
フラグをたててsend_webhook
関数を呼び出します。
send_webhook
はIFTTTのWebhookを呼び出す関数で、次の項目で説明します。
3. 通知
LINEへ通知するにあたっては、おなじみのIFTTTを使います。
IFTTT連携するためにはネットワークにつなぐ必要がありますが、M5StackはEspressifのESP32を積んでいるのでWiFi通信やBLE通信が可能です。
今回はWiFi通信でWebhookを呼び出すようにします。
const char* wifi_ssid = "<SSID名>";
const char* wifi_pass = "<SSIDパスワード>";
~中略
void setup() {
M5.begin();
dac_output_disable(DAC_CHANNEL_1);
Serial.begin(115200);
delay(1000);
WiFi.begin(wifi_ssid, wifi_pass);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
M5.Lcd.printf(".");
}
M5.Lcd.println("\nwifi connect ok");
initColormap();
// 時間設定
configTime( JST, 0, "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");
}
WiFiのセットアップ自体はWiFi.begin
をにSSIDとパスワードを渡すだけです。
通信自体はHTTPClient
を使います。
IFTTTとLINEの連携についてはこちらの記事で非常にわかりやすく説明されていました。
IFTTT(イフト)で、Webhooksを使用した簡単に自動でLineにメッセージを送信する方法
この記事を参考にWebhookアプレットを作成し、スケッチから呼び出します。
引数を3つ渡すことができるので、イベント名と場所と時間を渡すようにします。
(POSTでやりたかったのですがうまくいかずGETににげました)
// IFTTT Webhook URL
const char* webhook_url = "https://maker.ifttt.com/trigger/<Webhook イベント>/with/key/<Webhook キー>";
~中略
void send_webhook(String event_type, String event_place, String event_time)
{
String url = String(webhook_url);
url.concat("?value1=");
url.concat(event_type);
url.concat("&value2=");
url.concat(event_place);
url.concat("&value3=");
url.concat(event_time);
Serial.print("url:");
Serial.println(url);
http.begin(url);
int httpStatusCode = http.GET();
Serial.print("httpStatusCode:");
Serial.println(httpStatusCode);
String body = http.getString();
Serial.print("Response Body: ");
Serial.println(body);
}
}
動かしてみる
見た目はこんな感じです。
M5StackにつないだD6TをTinkerboardのアルミケースにセロハンテープでくっつけただけですね...
人が横切ったりすると以下のようにスマホのLINEに通知が飛んできます。
ソースコードはこちらに置いてます。
おわり
お気づきだと思いますが、まだまだ課題がたくさんあります。。。
- センサの前にずっと立ってたら延々と通知が飛ぶよ!
- Webhookに日本語のパラメータ投げると文字化けするよ!
- そもそも人じゃなくても反応するよ!
ただ、こういった特徴的なセンサなどを活用して何か作ろうと思った時の
「これどうやって使ったらいいんだ...?」
というハードルを、Groveコネクタやサンプルコードの公開などである程度下げられているのではないかなと思います。
こちらからは以上です。
最後まで読んでいただきありがとうございました!