アドベントカレンダー4日目

# 3つ目　来客お知らせシステム
 3つ目は、来客お知らせシステムです。

# きっかけ
　夏休み中帰省した際に、気付いたことがありました。
　私は祖母とも一緒に暮らしており、基本は1階の居間にいることが多いのですが、来客者がインターホンを鳴らしても、対応する様子がなかったことです。来客者が声を張り上げても気が付かなかったため、私が2階から降りて対応しました。前に帰省した時も、同じようなことがありました。
　祖母に聞いてみると、インターホンの音が小さい訳ではなく、低くて聞き取れない、来客者が呼んでもその声が低いと気が付かないとのことでした。夏休み期間は私が対処していたが、常にできるわけではありません。ですが、日中家にいるのは祖母だけです。
　この事態をどうにかできないかと考え、祖母でも聞こえるようにし、尚且つ来客がわかりやすいシステムを作ることにしました。
 
# 実際に作ってみる
　今回使用したのは、M5Stack、M5Core2、BUZZERセンサーです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924203/e88eb967-f5ae-f2d9-5ff7-6af5dab48cad.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924203/cd0c994b-ab80-8a87-363d-a4fc663423c1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924203/3179e236-ed99-75e6-9682-ac4a46557294.png)

# プログラム

これは、送信側(M5Stack)のプログラムです。

~~~Arduino:m5stack.ino
#include <M5Stack.h>
#include <WiFi.h>
#include <AsyncUDP.h>
#include <FS.h>
#include <SD.h>
#include <SPI.h>

const char* ssid = "WiFi_ssid";
const char* password = "WiFi_password";
AsyncUDP udp;

// 画像ファイルのパス（SDカード上のパス）
const char* imageBefore = "/before.jpg"; // ボタンを押す前の画像
const char* imageAfter = "/after.jpg";   // ボタンを押した後の画像

void setup() {
  M5.begin();
  Serial.begin(115200);

  // SDカードの初期化
  if (!SD.begin()) {
    Serial.println("SD Card Mount Failed");
    return;
  }

  // WiFi接続
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("Connected to WiFi!");

  // UDP通信のセットアップ
  if (udp.connect(IPAddress(192, 168, 1, 100), 1234)) { // 受信側のM5Core2のIPアドレスとポート番号
    Serial.println("Connected to UDP Server!");
  }

  // ボタンを押す前のメッセージと画像を表示
  M5.Lcd.clear();
  M5.Lcd.setTextSize(2);
  M5.Lcd.setCursor(50, 50);
  M5.Lcd.print("Press the middle button!");

  // ボタンを押す前の画像を表示
  showImage(imageBefore);
}

void loop() {
  M5.update();

  // ボタンB（中央ボタン）が押されたら
  if (M5.BtnB.wasPressed()) {
    Serial.println("B Button Pressed!");

    // 「呼び出ししています」のメッセージと画像を表示
    M5.Lcd.clear();
    M5.Lcd.setCursor(50, 50);
    M5.Lcd.setTextSize(2);
    M5.Lcd.print("Calling...");

    // ボタンを押した後の画像を表示
    showImage(imageAfter);

    // UDPパケットを送信
    udp.print("Alert");

    delay(1000); // 呼び出し中の表示を1秒維持
  }
}

// SDカードから画像を表示する関数
void showImage(const char* filename) {
  File file = SD.open(filename, FILE_READ);
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }

  size_t fileSize = file.size();
  uint8_t* fileData = (uint8_t*) malloc(fileSize);

  if (fileData == nullptr) {
    Serial.println("Failed to allocate memory");
    file.close();
    return;
  }

  file.read(fileData, fileSize);
  M5.Lcd.drawJpg(fileData, fileSize, 0, 0);
  
  free(fileData);
  file.close();
}
~~~

これは、受信側のプログラム(M5Core2)です。

~~~Arduino:m5core2.ino
#include <M5Core2.h>
#include <WiFi.h>
#include <AsyncUDP.h>
#include <FS.h>
#include <SD.h>

const char* ssid = "WiFi_ssid";
const char* password = "WiFi_password";
AsyncUDP udp;

void setup() {
  M5.begin();
  Serial.begin(115200);

  // WiFi接続
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("Connected to WiFi!");

  // SDカードの初期化
  if (!SD.begin()) {
    Serial.println("Failed to mount SD card");
    return;
  }

  // UDP通信の受信設定
  if (udp.listen(1234)) {
    Serial.println("Listening for incoming packets...");
    udp.onPacket([](AsyncUDPPacket packet) {
      Serial.print("Received: ");
      Serial.println((char*)packet.data()); // 受信データを表示

      // SDカードから画像を読み込み
      if (SD.exists("/visitor_alert.jpg")) {
        M5.Lcd.clear();
        M5.Lcd.drawJpgFile(SD, "/visitor_alert.jpg");
      } else {
        Serial.println("Image file not found on SD card");
      }

      // BUZZERを鳴らす処理
      pinMode(26, OUTPUT);
      digitalWrite(26, HIGH); // BUZZER ON
      delay(1000);            // 1秒待機
      digitalWrite(26, LOW);  // BUZZER OFF
    });
  }
}

void loop() {
  // メインループ
}
~~~

　色々なサイトを参考にさせていただきました。全然分からなかったためとても助かりました。どうしても問題が解決しない部分はChatGPTに頼ったりしました。

https://qiita.com/yomori/items/3e02bec35ad1262b7b94

https://github.com/espressif/arduino-esp32/tree/master/libraries/AsyncUDP

https://github.com/m5stack/M5Stack

https://chatgpt.com/

# 結果
　１，２枚目が送信側のM5Stack、3枚目が受信側のM5Core2です。送信側をM5Stackにしたのは、ボタンが立体的になっており、押す場所が分かりやすいのではないかと考えたからです。
 　送信側のボタンを押すと、受信側に繋がっているBUZZERが鳴るようになっています。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924203/69d3355b-6589-de66-8463-a3ab289436ab.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924203/43d4f496-1f9d-eae0-d46e-844db204b780.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924203/ac578b07-89b4-fd90-b971-3648392a8ac0.png)

　祖母に使ってみた感想を聞いたところ、
 ・音が高いので聞き取りやすい
 ・テレビをつけていても聞こえるので良い
 ・少し離れた位置に置いていても分かる
との意見を頂きました。

# 反省点
・画像の色をもっと工夫すればよかったと思いました。
・コンセントが近くになかったため、モバイルバッテリーで対処したが一日使うと電源が切れてしまったため、数日使い続けることはできませんでした。

# 感想
　祖母の意見からも、インターホンが聞こえないのを解決するという当初の目的を達成できたのではないかと思いました。