【ルネサス技術コラム】Arduino Uno R4 WiFiでポスト着荷検知&LCD表示システムを作ってみた

オフィスや自宅でポストを確認する際、「荷物や郵便物が届いているか」を毎回見に行かないと分からないのは意外と手間です。今回も、「エレクトロニクスを簡単に」をテーマに、ポストの蓋が開いたら“荷物が届いた”とみなし、LCDディスプレイに状態を表示する簡易システムを作ってみました。
今回はさらに、確認後にSWを押すと状態をリセットできるようにし、実際の運用を意識した構成にしています。

目次

はじめに: ポスト確認の手間を減らしたい

ポストの中身は、重要な書類や荷物が届いている可能性がある一方で、実際に見に行くまで状況が分からないことが多くあります。特に、オフィスや共有スペースのポストでは、「誰かが確認したと思っていた」「投函に気づくのが遅れた」といった運用上の課題が起こりがちです。

そこで今回は、ポストの蓋が開いたことをトリガに“荷物あり”状態へ切り替え、LCDディスプレイに「物が入っているかどうか」を表示する簡易モニタリングシステムを作ってみました。さらに、荷物を取り出した後はSW押下で状態をリセットできるようにし、日常的に使いやすい仕組みにしています。

ローカル表示の基本構成

まずは基本となる、ポストの蓋の開閉を検知し、LCDに状態を表示するシステムを構築しました。

使用した主な部品

  • Arduino Uno R4 WiFi

  • 磁気スイッチ (リードスイッチ) またはマグネットセンサー

  • 磁石

  • タクトスイッチ

  • I2C接続のLCDモジュール

  • ブレッドボード

  • ジャンパーピン

Arduino Uno R4 WiFiの特徴

今回のマイコンには Arduino Uno R4 WiFi を使用しました。公式ドキュメントによると、メインMCUには Renesas RA4M1 が採用されており、48MHz動作のArm Cortex-M4、32KB SRAM、256KB Flash を備えています。また、5V動作のGPIOを使えるため、センサーやLCDモジュールと組み合わせやすいのも扱いやすいポイントです。さらに、ESP32-S3によるWi-Fi / Bluetooth 機能も備えており、将来的な拡張もしやすい構成です。

開発環境と実装のポイント

開発環境には Visual Studio Code と PlatformIO IDE を使用しました。Arduino IDEでも実装できますが、PlatformIOを使うことでプロジェクト管理やライブラリ管理がしやすくなります。
PlatformIOでは、Arduino Uno R4 WiFi のボードIDとして uno_r4_wifi を指定し、platform = renesas-ra、framework = arduino で構成できます。

今回の状態管理の考え方

今回は、単純に「蓋が開いているか」を表示するのではなく、蓋が一度でも開いたら“荷物あり”状態にするという考え方で実装しました。
動作イメージは以下の通りです。

  • 初期状態: ポストは空として扱い、LCDには Empty を表示

  • ポストの蓋が開いたとき: 荷物が届いたとみなし、状態を Item Inside に切り替え

  • 蓋を閉じても状態は保持: 一度荷物ありになったら、その後に蓋を閉じても表示は維持

  • 確認後にSWを押下: 荷物を取り出したものとして状態をリセットし、Empty に戻す

このようにすることで、蓋の現在状態ではなく、「今ポストの中に物があるとみなすべきか」を表示できるようになります。

入力の扱い方

今回は、ポスト開閉検知用のリードスイッチと、状態リセット用のタクトスイッチの両方を INPUT_PULLUP で扱う構成にしました。これにより、外付けのプルアップ抵抗を追加しなくても、未接続時や未押下時の入力を安定させやすくなります。Arduinoのデジタル入力では、INPUT_PULLUP を使うことで内部プルアップ抵抗を有効にでき、入力ピンを通常時 HIGH、GNDへ落ちたときに LOW として扱いやすくなります。
配線としては、

  • リードスイッチ: 片側をデジタル入力ピン、もう片側をGND

  • タクトスイッチ: 片側をデジタル入力ピン、もう片側をGND

とすることで、通常時はHIGH、導通したときにLOWとして扱えます。

実装時の注意点

ポストの構造によって論理が逆になることがあります。
リードスイッチと磁石の位置関係によって、「蓋が閉まっているときにLOW」「開いたときにHIGH」という前提が逆になる場合があります。実機で確認し、必要に応じて条件式を反転させると対応しやすいです。

今回の表示は“蓋の状態”ではなく“荷物あり/なし”です。
そのため、蓋を閉じても Item Inside の表示は維持されます。状態を戻すのはリセットSW押下時だけです。

配線情報

各センサー、モジュールを以下のように配線します。

配線表

モジュール

信号

接続先

補足

リードスイッチ

片側

Arduino Uno R4 WiFi の D2

ポスト蓋検知用の入力です。

リードスイッチ

もう片側

Arduinoの GND

INPUT_PULLUP を使う前提でGNDへ接続します。

タクトスイッチ

片側

Arduino Uno R4 WiFi の D3

状態リセット用の入力です。

タクトスイッチ

もう片側

Arduino の GND

INPUT_PULLUP を使う前提でGNDへ接続します。

I2C LCDモジュール

SDA

Arduino Uno R4 WiFi の SDA端子

I2C通信用。

I2C LCDモジュール

SCL

Arduino Uno R4 WiFi の SCL端子

I2C通信用。

I2C LCDモジュール

VCC

Arduinoの 5V

LCD仕様に応じて接続します。

I2C LCDモジュール

GND

Arduino の GND

GNDは共通化します

配置のポイント

  • 磁石はポスト本体側、リードスイッチは蓋側に固定すると構成しやすいです。

  • 蓋を閉じたときに磁石とスイッチが十分近づく位置関係になるよう調整します。

  • タクトスイッチは、荷物確認後に押しやすい位置へ配置すると運用しやすくなります。

  • 金属製ポストでは、磁石の固定方法やセンサー反応距離を事前に確認しておくと安心です。

実際のプログラム

今回のローカル表示版で使用したプログラムを整理すると以下のようになります。
ポストの蓋開閉をデジタル入力で検知し、蓋が開いたら hasItem を 1 にします。 その後、リセットSWが押されたら hasItem を 0 に戻し、LCDには物が入っているかどうかを表示する構成です。
※本プログラムは、生成AIを用いて作成しております。

#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

/* I2C LCD: 0x27 / 16x2 */
LiquidCrystal_I2C lcd(0x27, 16, 2);

/* ピン定義 */
const int LID_SENSOR_PIN = 2; /* ポスト蓋検知用リードスイッチ */
const int RESET_SW_PIN = 3;   /* 状態リセット用スイッチ */

/* 状態管理 */
int hasItem = 0;

/* 入力前回状態 */
int prevLidState = LOW;
int prevResetState = HIGH;

/* 関数プロトタイプ */
void updateDisplay(void);
void handleLidEvent(int currentLidState);
void handleResetEvent(int currentResetState);

void updateDisplay(void)
{
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Post Status");
    lcd.setCursor(0, 1);
    if (hasItem) {
        lcd.print("Item Inside");
    } else {
        lcd.print("Empty");
    }
}

void handleLidEvent(int currentLidState)
{
    /*
        INPUT_PULLUP前提
        リードスイッチがGNDへ落ちる構成を想定
        磁石が近い(蓋が閉) -> LOW
        磁石が離れる(蓋が開) -> HIGH
        閉 -> 開の変化を検出したら荷物ありにする
    */
    if ((prevLidState == LOW) && (currentLidState == HIGH)) {
        if (!hasItem) {
            hasItem = 1;
            updateDisplay();
            Serial.println("Post opened -> Item detected");
        }
    }
}

void handleResetEvent(int currentResetState)
{
    /*
        タクトスイッチも INPUT_PULLUP
        未押下 -> HIGH
        押下 -> LOW
    */
    if ((prevResetState == HIGH) && (currentResetState == LOW)) {
        hasItem = 0;
        updateDisplay();
        Serial.println("Reset switch pressed -> State cleared");
        delay(50); /* 簡易デバウンス */
    }
}

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

    pinMode(LID_SENSOR_PIN, INPUT_PULLUP);
    pinMode(RESET_SW_PIN, INPUT_PULLUP);

    lcd.init();
    lcd.backlight();
    lcd.setCursor(0, 0);
    lcd.print("Post Status");
    lcd.setCursor(0, 1);
    lcd.print("Starting...");
    delay(1000);

    prevLidState = digitalRead(LID_SENSOR_PIN);
    prevResetState = digitalRead(RESET_SW_PIN);

    hasItem = 0;
    updateDisplay();

    Serial.println("System start");
    Serial.println("Initial state: Empty");
}

void loop(void)
{
    int currentLidState;
    int currentResetState;

    currentLidState = digitalRead(LID_SENSOR_PIN);
    currentResetState = digitalRead(RESET_SW_PIN);

    handleLidEvent(currentLidState);
    handleResetEvent(currentResetState);

    prevLidState = currentLidState;
    prevResetState = currentResetState;

    delay(50);
}

platformio.ini

[env:uno_r4_wifi]
platform = renesas-ra
board = uno_r4_wifi
framework = arduino
monitor_speed = 115200
lib_deps =
    marcoschwartz/LiquidCrystal_I2C

プログラムのポイント

  • digitalRead() は、指定したデジタルピンの値を HIGH または LOW として読み取る関数です。今回のようなリードスイッチやタクトスイッチの状態判定に適しています。

  • LID_SENSOR_PIN にはリードスイッチを接続し、蓋が閉から開へ変化した瞬間を検出しています。

  • hasItem は、現在ポストに物が入っているかどうかを保持するためのフラグです。一度 hasItem = 1 になった後は、蓋を閉じてもそのまま状態を維持します。

  • RESET_SW_PIN に接続したタクトスイッチを押すことで、hasItem = 0 に戻します。

  • LCDの表示は、蓋の開閉ではなく Item Inside / Empty の2状態にしています。

  • LiquidCrystal_I2C ライブラリを使うことで、I2C接続のLCDを比較的シンプルに制御できます。

  • 関数を updateDisplay()、handleLidEvent()、handleResetEvent() に分けることで、できるだけC言語らしく処理単位を明確にしています。

プログラムをビルド・アップロードし、ポストの蓋を開けたときにLCD表示が Item Inside に変わり、その後リセットSWを押したときに Empty に戻れば成功です。

発展編:状態保持とリセットSWで運用しやすくする

今回の仕組みで重要なのは、蓋が開いたことを“着荷イベント”として扱い、その後の状態を保持する点です。
単純に「今、蓋が開いているか」を表示するだけだと、蓋を閉じた瞬間に情報が消えてしまいます。しかし実際に知りたいのは、今ポストの中に物があるかどうかです。そのため、今回のようにフラグを持って状態を保持し、確認後にリセットSWでクリアする形にすると、運用しやすさがかなり上がります。

この構成のメリット

  • 瞬間的な開閉を見逃しにくい: 一度開けば状態が保持される

  • LCD表示が分かりやすい: 蓋の状態ではなく、荷物の有無をそのまま表示できる

  • 操作が単純: 確認後はSWを押すだけでリセットできる

  • 拡張しやすい: 今後、LEDやブザーを足しやすい

今後の展望(改善案)

簡易的なシステムからスタートし、荷物あり/なしの表示とリセットまで実現できましたが、実運用を見据えるとさらなる改善が必要です。主に、以下の点を検討する必要があります。

  • 防水・防塵性の向上: 屋外ポストで使う場合、センサーや配線の保護が重要です。

  • 誤検知対策: 蓋のガタつきや磁石位置ずれによる誤検知を減らす工夫が必要です。

  • デバウンス強化: SWやセンサー入力に対するソフトウェア処理をもう少し厳密にする。

  • LEDやブザーの追加: LCD以外でも状態がひと目で分かるようにする。

  • 筐体化・小型化: ブレッドボードから専用ケースや基板に移行し、常設しやすくする。

  • 将来的な通知連携: 必要に応じて、Wi-Fi機能を活用した通知やダッシュボード連携へ発展させる。
    例)
    郵便物到着時にTeams通知やメール通知を送信
    複数拠点のポスト状況をダッシュボードで一元管理

想定用途例:

  • オフィスの郵便受け監視

  • 工場の部品受入ボックス監視

  • 宅配ボックス着荷確認

  • 共用ポストの確認効率化

関連技術・参考トピック

今回の実装そのものは比較的シンプルな構成ですが、周辺技術にも目を向けると今後の発展の方向性が見えやすくなります。
まず、Arduino Uno R4 WiFi は、5V系のセンサーや表示器と組み合わせやすく、さらにWi-Fi/Bluetooth拡張も視野に入れられる点が魅力です。今回のようなローカル表示のPoCから始めて、将来的に通知や記録機能へ広げていく土台として扱いやすいボードだと感じました。
また、開発環境として PlatformIOを使うことで、プロジェクト構成やライブラリ依存関係を管理しやすくなります。Arduino Uno R4 WiFi では uno_r4_wifi を指定して構成できるため、ボード設定も比較的分かりやすいです。

Arduino Uno R4 WiFi に搭載されている Renesas RA4M1は、今回のような簡易検知システムだけでなく、より大規模なIoT機器開発にもつながるマイコンです。
例えば、ルネサスのRA6シリーズやWi-Fi/BLE対応モジュールを活用することで、

  • 郵便物到着通知のクラウド連携

  • 遠隔監視

  • スマホ通知

  • 設備や施設の状態監視

といった用途への発展も考えられます。

まとめ

今回は、Arduino Uno R4 WiFiを使って、ポストの蓋が開いたら“荷物あり”状態にし、LCDディスプレイに物が入っているかどうかを表示する簡易システムを作ってみました。
構成はシンプルですが、

  • 蓋が開いたことを検知する

  • 荷物あり状態を保持する

  • LCDに Item Inside / Empty を表示する

  • 確認後にSWで状態をリセットする

という一連の流れを実装できるため、実際の運用イメージに近いPoCとして扱いやすい題材でした。まずは小さく動かし、そこから誤検知対策や表示改善へ広げていける点も、このテーマの面白さだと感じています。

参考リンク