ゆるい空き室モニタをつくる1(M5StickC+PIR編)

最終更新日

なんとなくその辺りに人がいるかいないかをモニタリングして、会議室の空き室チェックをしよう。

とりあえず、ハードウェア。
人感センサと、マイコンは以下。

部材

M5StickC


M5StickCは、USB-C接続か、バッテリー駆動で取り回しが便利。

PIR Hat

PIR Hat(AS312)は、秒単位の遅延はあるものの、赤外線で人など熱をはっするものを検知できる。
ちなみに30cmまで近ずけば猫でもOK。
人間なら、4から6人くらいの会議室がちょうどいい感じ。

ただし!歩いて緯度動いてないと、センサが値が揺れない背か、検知されない。つまり、昼寝中の猫は検知されない。

サンプル実装

オフラインで試す。

開発環境は、PlatformIO。

PlatformIO で開発環境を作る

PlatformIO で開発環境を作る

2021.06.27

センサがなにか検知すると、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);
}

次回はサーバ側。

ゆるい空き室モニタをつくる2(RPi MQTT Broker編)

ゆるい空き室モニタをつくる2(RPi MQTT Broker編)

2022.03.13

シェアする