← 回所有專案

大學專題 ‧ 硬體整合與 App 開發 · 2018

智慧衛生紙盒

大學畢業專題。在衛生紙盒蓋內裝上超音波感測器,即時量測衛生紙堆的高度並換算成剩餘百分比,再透過藍牙送到盒子前方的螢幕;螢幕上以 App Inventor 製作的 App 同時顯示剩餘量、輪播廣告與促銷活動,讓一個日常耗材變成可以感知、也能帶來曝光的小型物聯網裝置。

ArduinoHC-SR04 超音波感測器藍牙模組MIT App InventorAndroidIoT
智慧衛生紙盒

專案概述

這是我大學的畢業專題。出發點很生活化:公共場所(餐廳、辦公室、廁所)的衛生 紙盒常常要等到已經空了才被發現,補貨永遠慢一步;同時,衛生紙盒又是一個 大家每天都會盯著看幾秒的物件,本身就是一個被忽略的「廣告版位」。

於是我們做了一個智慧衛生紙盒,把兩件事合在一起:

  • 感知剩餘量:在盒蓋內側裝上超音波感測器,量測衛生紙堆的高度,換算成 「還剩幾 %」,低於門檻時主動提醒補貨
  • 前方螢幕做廣告:盒子前面放一塊螢幕,平常輪播廣告與促銷活動,並同時顯示 目前剩餘量;螢幕上的 App 以 MIT App Inventor 開發

這也是我第一次把「感測器 → 微控制器 → 無線傳輸 → 手機 App」整條鏈路自己串 起來的經驗。

系統架構

整個系統分成兩端:衛生紙盒內的硬體端負責量測與運算,前方螢幕上的 App 負責呈現與互動,兩者之間以藍牙序列埠溝通。

智慧衛生紙盒系統架構圖:超音波感測器量測衛生紙堆高度,Arduino 換算成百分比後經藍牙送到前方螢幕的 App Inventor App,App 顯示剩餘量、輪播廣告與促銷活動

  • 超音波感測器(HC-SR04):固定在盒蓋內側、朝下對準衛生紙堆,每隔固定時間 發射一次超音波並接收回波
  • Arduino:讀取回波時間、換算成距離,再換算成剩餘百分比
  • 藍牙模組:把計算好的百分比以序列埠字串送出,硬體端不需要知道螢幕上要顯示 什麼
  • App Inventor App:接收百分比,更新畫面上的剩餘量,並負責所有廣告、促銷與 提醒的呈現邏輯

把「量測」和「呈現」切開的好處是兩邊可以各自修改:要換廣告素材、調整促銷活 動,只需要改 App;要換感測器或校正數值,只需要改 Arduino 程式。

剩餘量量測:從超音波到百分比

這個專題的核心問題是:怎麼知道盒子裡還剩多少衛生紙? 我們選擇量「高度」 而不是「重量」,因為衛生紙很輕,秤重感測器在這個重量區間的誤差反而大;而超音波 感測器便宜、非接觸,裝在盒蓋上也不影響抽取。

超音波量測示意圖:感測器在盒蓋往下量到衛生紙堆頂面的距離 d,再依滿盒與空盒的距離換算成剩餘百分比

換算分成兩步:

  1. 回波時間 → 距離:超音波從發射到接收的時間 t 是「來回」的時間,音速約 每微秒 0.0343 公分,所以距離 d = t × 0.0343 ÷ 2
  2. 距離 → 剩餘百分比:事先校正兩個基準值——滿盒時感測器到頂面的距離 D_full、空盒時感測器到盒底的距離 D_empty——目前的剩餘量就是 d 落在這 兩者之間的比例
cpp
const int TRIG_PIN = 9;
const int ECHO_PIN = 10;
const float D_FULL = 3.0;   // 滿盒時到頂面的距離(cm),實際依盒子校正
const float D_EMPTY = 12.0; // 空盒時到盒底的距離(cm)

float readDistanceCm() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  long duration = pulseIn(ECHO_PIN, HIGH);
  return duration * 0.0343 / 2;
}

void loop() {
  float sum = 0;
  for (int i = 0; i < 5; i++) {      // 取多次平均,過濾雜訊
    sum += readDistanceCm();
    delay(60);
  }
  float d = sum / 5;
  int percent = (D_EMPTY - d) / (D_EMPTY - D_FULL) * 100;
  percent = constrain(percent, 0, 100);

  Serial.println(percent);           // 經藍牙模組送到 App
  delay(1000);
}

實作時遇到的幾個實際問題:

  • 衛生紙表面不平整:抽取後頂面會有一張翹起來的紙,單次量測會突然變短。以 多次取樣平均並限制在 0–100 之間,讓畫面上的數字不會亂跳
  • 最小量測距離:HC-SR04 在太近的距離量不準,所以感測器不能直接貼著衛生紙, 要在盒蓋上預留一點高度,這也是 D_full 不是 0 的原因
  • 不同盒子要重新校正:D_full、D_empty 會隨盒子尺寸改變,所以設計成常 數集中在程式開頭,換盒子時只需要量兩次距離

前方螢幕:App Inventor 製作的廣告與促銷畫面

盒子前方的螢幕是一台 Android 裝置,上面跑的 App 用 MIT App Inventor 開發。 App Inventor 以拖拉積木(Blocks)的方式寫程式,對我們來說可以把時間花在 「畫面要呈現什麼」,而不是卡在 Android 開發環境上。

畫面由上而下分成三塊:

  • 廣告輪播區:佔畫面最大的版位,用 Clock 元件每隔幾秒觸發一次,依序切換 Image 的圖片來源,達到輪播效果
  • 剩餘量區:顯示目前百分比與進度條;BluetoothClient 收到 Arduino 送來的數 字後即時更新
  • 促銷活動區:顯示限時優惠與折價券 QR Code,讓使用者在抽衛生紙的幾秒鐘內就 能掃碼帶走優惠

App 端的主要邏輯(以積木表達的流程):

  • Screen.Initialize:連線到衛生紙盒的藍牙模組,啟動輪播與讀值的計時器
  • ReadClock.Timer:若藍牙有資料可讀,就讀出百分比、更新文字與進度條
  • AdClock.Timer:輪播索引加一,從廣告清單中換下一張圖
  • 低量提醒:當百分比低於設定門檻(例如 20%),剩餘量區改成紅色並顯示「請 補充衛生紙」,讓現場人員一眼就看得到

成果與收穫

  • 完成一個可實際展示的原型:抽取衛生紙時,前方螢幕上的剩餘百分比會跟著下降, 同時持續輪播廣告與促銷內容
  • 第一次完整經歷感測器 → 微控制器 → 無線傳輸 → App 的端到端整合,也體會到 硬體資料「先清洗再使用」的重要性——真實世界的感測值永遠比課本上的雜
  • 把「量測」和「呈現」拆成兩個獨立的部分、用一個簡單的協定(只傳一個數字)溝 通,專題後期組員分頭修改 Arduino 和 App 時幾乎不會互相影響,讓我體會到職責 分離、介面越簡單越好的價值
  • 還想改進的地方:目前一個紙盒只能對應一台螢幕,而且補貨提醒只有現場看得到。 如果之後能改用 Wi-Fi 把多個紙盒的剩餘量集中回報到一個後台,清潔人員就能一次 看到所有位置的狀態,廣告內容也能從後台統一更換

使用技術

  • 硬體:Arduino、HC-SR04 超音波感測器、藍牙序列埠模組
  • 韌體:Arduino C/C++(回波量測、距離換算、取樣平均)
  • App:MIT App Inventor(BluetoothClient、Clock、Image 元件)、Android
  • 概念:IoT 感測與資料平滑、數位看板(Digital Signage)廣告輪播