ゆるい空き室モニタをつくる1(M5StickC+PIR編)
なんとなくその辺りに人がいるかいないかをモニタリングして、会議室の空き室チェックをしよう。
とりあえず、ハードウェア。
人感センサと、マイコンは以下。
部材
M5StickC
M5StickCは、USB-C接続か、バッテリー駆動で取り回しが便利。
PIR Hat
PIR Hat(AS312)は、秒単位の遅延はあるものの、赤外線で人など熱をはっするものを検知できる。
ちなみに30cmまで近ずけば猫でもOK。
人間なら、4から6人くらいの会議室がちょうどいい感じ。
ただし!歩いて緯度動いてないと、センサが値が揺れない背か、検知されない。つまり、昼寝中の猫は検知されない。
サンプル実装
オフラインで試す。
開発環境は、PlatformIO。
センサがなにか検知すると、M5Stickの赤いLEDが点灯する。
platformio.ini
[env:m5stick-c]
platform = espressif32
board = m5stick-c
framework = arduino
lib_deps =
m5stack/M5StickC @ ^0.2.5
upload_port=/dev/tty.usbserial-xxxxxxxx
main.c
#include <M5StickC.h>
#define WAIT_TIME 100
#define PIR_HAT_PIN 36
void setup()
{
M5.begin();
// LED
pinMode(GPIO_NUM_10, OUTPUT);
// PIR Hat
pinMode(PIR_HAT_PIN, INPUT_PULLUP);
}
void loop()
{
M5.update();
// PIR HAT(AS312)
int pir = digitalRead(PIR_HAT_PIN);
if (pir)
{
// LED ON
digitalWrite(GPIO_NUM_10, 0);
}
else
{
// LEF OFF
digitalWrite(GPIO_NUM_10, 1);
}
delay(WAIT_TIME);
}
Wifi でネット接続
検知データは、Wifi経由でどっかのサーバにとばしたい。
とりあえず、GETだけやってみよう。
自宅のアクセスポイントに接続して、正しい時間を表示させてみる。
仕様
- Wifi 接続(retry中は、
.
を繰り返し表示) - NTPサーバに接続して正しい時間を取得
- 3秒毎に日時表示(1秒でもいいけど、不要)
- センサに反応があれば、赤いLEDを点灯
ディスプレイ表示
これで、ネット経由でなにかする準備は、OK。
時間はMQTTサーバのsetup。
program
#include <M5StickC.h>
#include <WiFi.h>
#include <HTTPClient.h>
//
// wifi
//
const char *ssid = "APのSSID";
const char *password = "APのパスワード";
WiFiClient wClient;
int Last_sec = -1;
#define WAIT_TIME 100
#define PIR_HAT_PIN 36
//
// setup RTC by NTP
//
void setup_rtc()
{
struct tm timeinfo;
uint8_t hh, mm, ss;
RTC_TimeTypeDef TimeStruct;
// connect NTP server
configTime(9 * 3600, 0, "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");
if (!getLocalTime(&timeinfo))
{
M5.Lcd.println("Failed to obtain time");
return;
}
//
// set localtime to RTC
//
hh = timeinfo.tm_hour;
mm = timeinfo.tm_min;
ss = timeinfo.tm_sec;
TimeStruct.Hours = hh;
TimeStruct.Minutes = mm;
TimeStruct.Seconds = ss;
M5.Rtc.SetTime(&TimeStruct);
}
//
// connect wifi
//
int setup_wifi()
{
M5.Lcd.setTextSize(1);
M5.Lcd.setCursor(0, 0);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextColor(DARKGREY);
WiFi.disconnect(true);
WiFi.begin(ssid, password); // connect to wifi
int ntry = 100;
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
M5.Lcd.print(".");
ntry -= 1;
if (ntry == 0)
{
// Serial.println("max try failed");
M5.Lcd.setTextSize(2);
M5.Lcd.setTextColor(RED);
M5.Lcd.setCursor(0, 0);
M5.Lcd.println("fail wifi connect");
return -1;
}
}
M5.Lcd.println("");
M5.Lcd.println("WiFi connected.");
M5.Lcd.print("IP address: ");
M5.Lcd.println(WiFi.localIP());
M5.Lcd.println();
return 0;
}
void setup()
{
M5.begin();
M5.Axp.ScreenBreath(10);
M5.Lcd.setRotation(3); // 左を上にす
M5.Lcd.setTextSize(1);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextColor(DARKGREY);
delay(500);
pinMode(GPIO_NUM_10, OUTPUT);
pinMode(PIR_HAT_PIN, INPUT_PULLUP);
//
// Wifi
//
setup_wifi();
//
// setup RTC time
//
setup_rtc();
}
void loop()
{
RTC_TimeTypeDef RTC_TimeStruct;
M5.update();
// PIR HAT(AS312)
int pir = digitalRead(PIR_HAT_PIN);
if (pir)
{
digitalWrite(GPIO_NUM_10, 0);
}
else
{
digitalWrite(GPIO_NUM_10, 1);
}
M5.Rtc.GetTime(&RTC_TimeStruct);
int diff = Last_sec - RTC_TimeStruct.Seconds;
if (abs(diff) > 3)
{
M5.Lcd.setTextSize(1);
M5.Lcd.setCursor(32, 9 * 8);
M5.Lcd.setTextColor(DARKGREEN);
M5.Lcd.fillRect(0, 9 * 8, 256, 12, BLACK);
M5.Lcd.printf("Time: %02d : %02d : %02d\n",
RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds);
Last_sec = RTC_TimeStruct.Seconds;
}
delay(WAIT_TIME);
}
次回はサーバ側。