Arduino Uno R4 WiFiでタンク・容器の「残量ざっくり見える化」システムを作ってみた

日常や職場では、「中身があとどれくらい残っているのか分かりにくい」ものが意外とあります。たとえば、給水タンク、ストック容器、ペットフード容器、収納ボックスなどは、ふたを開けたり持ち上げたりしないと残量感が分からないことも少なくありません。今回も、「エレクトロニクスを簡単に」をテーマにArduino Uno R4 WiFi超音波センサー を使って、タンク・容器の残量をざっくり見える化する簡易システムを作ってみました。

超音波センサーで容器の上部から中身までの距離を測り、その値をもとに FULL / MID / LOW の3段階で表示するシンプルな構成です。まずはローカル表示から始め、将来的にはMQTTやWebダッシュボードへ広げられるようなPoCとしてまとめました。

見出し

- [はじめに:残量確認の手間]
- [ローカル表示の基本構成]
- [開発環境と実装のポイント]
- [実際のプログラム]
- [配線情報]
- [今後の展望(改善案)]
- [関連技術・参考トピック]
- [まとめ]
- [参考リンク]

はじめに:残量確認の手間

容器やタンクの残量は、「なくなりそうになったら補充したい」と思っていても、普段はなかなか確認しません。実際には、使おうと思った時に初めて「ほとんど残っていなかった」と気づくこともあります。

特に、以下のような場面では“ざっくりでも残量が見える”だけでかなり便利になります。

・ペットフードやお菓子のストック容器
・オフィスの備品ストッカー
・給水タンクや簡易タンク
・中身が見えにくい収納ケース
・ゴミ箱や回収ボックスの満杯検知

そこで今回は、超音波センサーで容器の上から中身までの距離を測り、残量を段階表示する仕組みを試作してみました。 
厳密な計量ではなく、まずは 「残りが多い / 中くらい / 少ない」 をひと目で分かるようにする ことを目的にしています。

ローカル表示の基本構成

まずは基本となる、超音波センサーで距離を測り、LCDに残量状態を表示するシステムを構築しました。

使用した主な部品

・Arduino Uno R4 WiFi
・超音波センサーモジュール
・I2C接続のLCDモジュール
・赤色LED / 黄色LED / 緑色LED
・抵抗
・ブレッドボード
・ジャンパーピン

 Arduino Uno R4 WiFiの特徴

マイコンには Arduino Uno R4 WiFi を使用しました。公式ドキュメントによると、このボードはメインMCUとして Renesas RA4M1 を採用しており、48MHz動作のArm Cortex-M4、256KB Flash、32KB SRAMを備えています。また、ESP32-S3により Wi‑Fi / Bluetooth 接続に対応しており、Arduino Cloudとも互換性があります。

今回の試作ではローカル表示が中心ですが、Uno R4 WiFi は「まずはセンサーと表示だけで小さく始める」「あとからネットワーク連携へ広げる」という段階的な開発と相性が良いと感じました。今回のテーマのように、現場の“確認の手間”をPoCで素早く形にしたい時に扱いやすいボードです。

また、Renesas RA4M1 ファミリは 48MHz Arm Cortex-M4 に加え、セグメントLCDコントローラ静電容量式タッチセンシング といったHMI向け機能を持っています。将来的に「表示するだけ」から、「本体でモード切り替えする」「しきい値を設定する」といった使い方へ発展させやすい点も魅力です。

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

今回は、容器の上部に超音波センサーを取り付け、**センサーから中身の表面までの距離** を測る方式にしました。

考え方としてはシンプルで、

距離が短い → 中身が多い
距離が長い → 中身が少ない

という関係になります。

例えば、空の時の距離を 18cm、満タン近い時の距離を 4cm としておくと、その間の値から残量率をざっくり計算できます。今回は以下のような基準で表示することにしました。

・70%以上: FULL
30%以上70%未満: MID
30%未満: LOW

しきい値設定の注意

このしきい値は容器の大きさや形状によって変わります。特に以下の点は事前確認が必要です。

・センサーの取り付け高さ
・容器の深さ
・中身の表面形状

そのため、実際に使う容器で 空の時の距離十分入っている時の距離 を測っておき、それに合わせて emptyDistancefullDistance を調整するのがポイントです。

配線表

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

配線表

| モジュール |  信号  |  接続先  |   補足   |

| 超音波センサー | TRIG | Arduino Uno R4 WiFi の D9 | 距離測定のトリガ信号を出力します。 |

| 超音波センサー | ECHO | Arduino Uno R4 WiFi の D10 | 反射時間を読み取ります。 |

| 超音波センサー | VCC | Arduino の 5V | モジュール仕様に応じて給電します。 |

| 超音波センサー | GND | Arduino の GND | GNDはLCDやLEDと共通化します。 |

| I2C LCDモジュール | SDA | Arduino Uno R4 WiFi の SDA | Wire.hLiquidCrystal_I2C で制御します。 |

| I2C LCDモジュール | SCL | Arduino Uno R4 WiFi の SCL | I2Cアドレスは 0x27 を想定しています。 |

| I2C LCDモジュール | VCC / GND | Arduino の 5V / GND | LCDモジュールの仕様に応じて配線します。 |

| 緑色LED | アノード側 | Arduino の D6 | 残量多め(FULL)表示用。抵抗を直列に入れます。 |

| 黄色LED | アノード側 | Arduino の D7 | 中間(MID)表示用。抵抗を直列に入れます。 |

| 赤色LED | アノード側 | Arduino の D8 | 残量少なめ(LOW)表示用。抵抗を直列に入れます。 |

| 各LED | カソード側 | Arduino の GND | 220Ω程度の抵抗を挟んで配線します。 |

実際のプログラム

今回のローカル表示版で使用したプログラムは以下の通りです。 
超音波センサーで距離を測定し、あらかじめ設定した「空」と「満タン」の距離をもとに残量率を計算し、LCDとLEDで状態を表示します。
※本プログラムは、生成AIを用いて作成しております。

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

LiquidCrystal_I2C lcd(0x27, 16, 2);

const int trigPin = 9;
const int echoPin = 10;

const int greenLedPin = 6;
const int yellowLedPin = 7;
const int redLedPin = 8;

// 容器に合わせて調整する値
const float emptyDistance = 18.0; // 空のときの距離(cm)
const float fullDistance  = 4.0;  // 満タン近いときの距離(cm)

float measureDistanceCm() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);

  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  long duration = pulseIn(echoPin, HIGH, 30000); // 30ms timeout
  if (duration == 0) {
    return -1.0;
  }

  float distance = duration * 0.0343 / 2.0;
  return distance;
}

int calcPercent(float distance) {
  if (distance < 0) return -1;

  float percent = (emptyDistance - distance) / (emptyDistance - fullDistance) * 100.0;

  if (percent > 100.0) percent = 100.0;
  if (percent < 0.0) percent = 0.0;

  return (int)(percent + 0.5);
}

void updateLeds(int percent) {
  digitalWrite(greenLedPin, LOW);
  digitalWrite(yellowLedPin, LOW);
  digitalWrite(redLedPin, LOW);

  if (percent >= 70) {
    digitalWrite(greenLedPin, HIGH);
  } else if (percent >= 30) {
    digitalWrite(yellowLedPin, HIGH);
  } else {
    digitalWrite(redLedPin, HIGH);
  }
}

void updateDisplay(int percent, float distance) {
  lcd.setCursor(0, 0);

  if (percent < 0) {
    lcd.print("Level: ERROR   ");
    lcd.setCursor(0, 1);
    lcd.print("Check sensor   ");
    return;
  }

  if (percent >= 70) {
    lcd.print("Level: FULL    ");
  } else if (percent >= 30) {
    lcd.print("Level: MID     ");
  } else {
    lcd.print("Level: LOW     ");
  }

  lcd.setCursor(0, 1);
  lcd.print("Dist:");
  lcd.print(distance, 1);
  lcd.print("cm ");
  lcd.print(percent);
  lcd.print("%   ");
}

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

  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);

  pinMode(greenLedPin, OUTPUT);
  pinMode(yellowLedPin, OUTPUT);
  pinMode(redLedPin, OUTPUT);

  lcd.init();
  lcd.backlight();
  lcd.clear();
}

void loop() {
  float distance = measureDistanceCm();
  int percent = calcPercent(distance);

  if (percent >= 0) {
    Serial.print("Distance: ");
    Serial.print(distance);
    Serial.print(" cm, Percent: ");
    Serial.print(percent);
    Serial.println("%");
    updateLeds(percent);
  } else {
    Serial.println("Sensor read error");
    digitalWrite(greenLedPin, LOW);
    digitalWrite(yellowLedPin, LOW);
    digitalWrite(redLedPin, LOW);
  }

  updateDisplay(percent, distance);
  delay(1000);
}

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

プログラムのポイント

超音波センサーの TRIGECHO を使って、容器上部から中身までの距離を測定しています。
emptyDistancefullDistance をもとに、距離から残量率をざっくり計算しています。
・LCDの1行目には FULL / MID / LOW、2行目には距離と残量率を表示しています。
・緑LED・黄LED・赤LEDで、残量状態を遠くからでも分かるようにしました。
Serial.begin(115200) を入れているため、シリアルモニタで距離や計算結果を確認しながらデバッグできます。

プログラムをビルド、アップロードして、超音波センサーと物体との距離が近い時に FULL、中間なら MID、遠い時に LOW と表示されれば成功です。

ゴミ箱に取り付けてみる

今回は簡易的に、超音波センサーをゴミ箱のふたの裏側にくっつけました。

ゴミ箱が空の状態のとき(物体との距離が遠いためLOW表示)

ゴミ箱がいっぱいの状態の時(物体との距離が近いためFULL表示)

今後の展望(改善案)

今回の試作は「残量をざっくり見える化する」ことを主目的にしたシンプルな構成ですが、実際の運用を考えると、いくつか改善したいポイントがあります。

判定精度の向上
超音波センサーだけだと、中身の表面が不安定な場合や、容器の形状によっては誤差が出ることがあります。複数回測定の平均化や、容器ごとの補正式を導入することで、表示の安定性を高められます。
容器ごとのキャリブレーション
同じプログラムでも、容器の深さや設置位置が変わると距離の意味が変わります。初期設定時に「空」と「満」の値を保存できるようにすると、実用性が上がります。
通知機能
残量が一定値を下回った時に通知する仕組みを作れば、補充漏れの防止に役立ちます。オフィスの備品、給水、ストック管理などと相性が良いです。
履歴の蓄積と可視化
時刻ごとの残量変化をログとして残し、Webダッシュボードで可視化することで、補充頻度や使用傾向の分析にもつなげられます。
専用筐体化・固定方法の改善
センサー位置がズレると測定値も変わるため、容器上部に固定しやすい筐体や治具を用意すると、安定運用しやすくなります。

関連技術・参考トピック

今回の実装は比較的シンプルですが、関連技術に目を向けると、今後の発展の方向性が見えやすくなります。

まず、Renesas RA4M1はHMI向けの要素として セグメントLCDコントローラ静電容量式タッチセンシング に対応しており、将来的に「表示するだけ」から「本体側でしきい値やモードを操作する」方向へ広げる余地があります。
Renesas RA4M1

また、Arduino Uno R4 WiFi は Arduino Cloud と互換性があるため、ローカルの電子工作から、Webダッシュボードや遠隔監視へ発展させやすいのも特徴です。今回のような「残量を見える化して運用判断につなげる」テーマとは相性が良いと感じました。
Arduino Docs

さらに、無線という観点では、Renesasは近年 Wi-Fi 6 / Bluetooth LE 対応のコンボモジュールも展開しています。今回の作例でそこまで踏み込んでいるわけではありませんが、IoT機器が「つながること」を前提に設計される流れの中で、より低消費電力・高機能な常時接続デバイスへ広げていく方向性を考える参考になります。

Wi-Fi® / Bluetooth® Module ルネサスエレクトロニクス製候補製品 RRQ61051

まとめ

今回は、Arduino Uno R4 WiFi を使って、タンク・容器の残量をざっくり見える化する簡易システムを作ってみました。

構成自体はシンプルですが、

・距離を測定する
・状態を判定する
・その場で分かる形に表示する
・将来的にはネットワーク越しに共有する

という流れを通して、現場の“確認の手間”を減らすIoT的な考え方 を小さく試せる題材でした。

まずはローカル表示の小さな仕組みから始め、そこからログ、通知、Webダッシュボード、複数容器管理へと広げていける点も、このテーマの面白さだと感じています。

参考リンク

Arduino UNO R4 WiFi 公式ドキュメント
PlatformIO: Arduino Uno R4 WiFi ボード情報
RA4M1 - 48MHz Arm Cortex-M4 / LCDコントローラ / Capacitive Touch 対応MCU | Renesas