今 堂 又 回 到 便 宜 夾 大 碗 的 Multi-Function Shield,這 次 我 們 會 把 它 做 成 一 個 Kitchen Timer。
古 代 的 Kitchen Timer 是 機 械 式 的 ,在 時 間 設 定 方 面 不 太 準 確 ,例 如 我 要 煮 個 公 仔 麵 ,生 產 商 建 議 煮 3 分 鐘 ,我 喜 歡 食 生 少 少 ,會 煮 2 分 15 秒 ,用 舊 式 廚 房 計 時 器 ,是 有 點 難 。
所 以 後 來 有 了 digital 的 kitchen timer 之 後 ,我 就 第 一 時 間 轉 用 了 。這 一 課 我 用 Arduino + Multi-Function Shield 來 做 kitchen timer,當 然 就 是 做 digital 的 了 。Digital kitchen timer 有 什 麼 零 部 件 呢 ?
從 上 圖 可 以 見 到 ,最 基 本 的 廚 房 計 時 器 ,會 有 一 個 4 位 數 的 顯 示 屏 ,用 來 顯 示 時 間 ,另 外 會 有 3 個 push button,用 來 設 定 / 重 設 時 間 ,和 開 始 /停 止 。當 倒 數 完 成 ,它 會 發 出 響 聲 ,所 以 ,它 裡 面 亦 會 有 一 個 蜂 鳴 器 。
再 看 看 我 們 的 Multi-Function Shield,剛 剛 好 有 齊 所 需 要 的 東 西 ,真 的 一 根 線 也 不 用 接 ,就 可 以 動 手 寫 Kitchen Timer 的 program,實 在 是 太 爽 了 。
在 開 始 動 手 寫 scratch 之 前 ,讓 我 們 先 清 楚 定 義 我 們 的 arduino kitchen timer 能 做 什 麼 吧 。
廚 房 計 時 器 的 功 能 :
1. 倒 數 計 時 ,最 長 的 計 時 時 間 為 99 分 59 秒 ;
2. 計 時 器 會 有 三 個 狀 態 ,「閒 置 」、「倒 數 進 行 中 」和 「倒 數 完 成 」。
2. 程 序 開 始 時 ,計 時 器 顯 示 00 分 00 秒 ,並 把 系 統 狀 態 設 置 為 閒 置 ;
3. 在 系 統 閒 置 時 ,按 btn_1 鍵 時 ,分 鐘 位 會 加 1,如 果 分 鐘 位 大 於 99,分 鐘 位 就 歸 零 ;
4. 在 系 統 閒 置 時 ,按 btn_2 鍵 時 ,秒 鐘 位 會 加 1;如 果 秒 鐘 位 大 於 59,秒 鐘 位 就 歸 零 ;
5. 在 系 統 閒 置 時 ,同 時 按 btn_1 + btn_2 鍵 ,分 鐘 位 和 秒 鐘 位 同 時 歸 零 ;
6. 按 btn_3 鍵 時 ,如 果 系 統 閒 置 ,便 開 始 倒 數 計 時 ,如 果 倒 數 進 行 中 ,就 暫 停 計 時 ;
7. 在 倒 數 進 行 中 時 ,每 過 一 秒 ,秒 鐘 位 減 1;如 果 秒 鐘 位 等 於 0,而 分 鐘 位 大 於 零 ,分 鐘 位 減 1,並 且 把 秒 鐘 位 設 定 為 59;如 果 分 鐘 位 和 秒 鐘 位 同 時 等 於 0,則 系 統 進 入 倒 數 完 成 狀 態 。
8. 在 倒 數 完 成 時 ,蜂 鳴 器 會 響 起 提 示 聲 。提 示 聲 完 結 時 ,又 或 者 使 用 按 任 何 鍵 ,系 統 即 回 到 閒 置 狀 態 。
看 起 來 很 複 雜 ,是 不 是 ?但 其 實 是 完 全 不 複 雜 的 。這 就 是 任 何 一 個 的 digital kitchen timer 都 會 做 的 工 作 ,你 不 會 以 為 你 比 不 上 10 塊 錢 一 個 的 kitchen timer 吧 ?哈 哈 。你 覺 得 有 些 東 西 很 複 雜 ,主 要 原 因 是 你 怕 它 ,只 要 你 不 去 怕 它 ,其 實 它 們 一 點 都 不 複 雜 。
把 全 部 功 能 ( 有 人 會 叫 它 們 做 程 式 的 邏 輯 ) 清 清 楚 楚 地 羅 列 出 來 ,對 寫 program 有 莫 大 的 好 處 。其 實 不 只 是 programming,同 學 們 開 始 每 一 個 project 之 都 應 該 要 有 完 整 的 規 劃 ,這 對 我 們 安 排 人 手 和 時 間 等 都 很 有 幫 助 。
好 吧 ,回 到 mblock,開 始 programming 的 部 分 。我 們 嘗 試 按 照 上 面 功 能 列 表 的 次 序 ,慢 慢 去 完 成 我 們 的 程 式 。不 過 ,因 為 我 們 是 使 用 Multi-Function Shield,大 家 要 記 得 先 安 裝 好 Multi-Function Shield 的 extension,唔 係 好 多 功 能 都 會 用 唔 到 架 。( 如 果 之 前 裝 左 ,就 唔 洗 再 裝 ,如 果 未 裝 過 ,就 請 參 閱 我 的 Stem Project (十 ) Arduino Multi-function Shield using Scratch (1) )
檔 案 下 載 : MultiFunctionShield.zip
首 先 ,是 顯 示 時 間 ,我 們 設 定 4 個 變 數 ,min 和 sec 就 是 現 在 顯 示 的 分 和 秒 ,而 minSave 和 secSave 就 用 來 儲 存 使 用 者 設 置 的 時 間 ,因 為 倒 數 完 成 之 後 ,廚 房 計 時 器 都 會 把 時 間 重 設 為 上 一 次 的 時 間 ,因 為 廚 房 通 常 有 很 多 重 複 性 的 工 作 。程 序 開 始 時 ,我 們 把 這 4 個 變 數 都 設 定 為 0。
然 後 我 們 會 有 另 一 個 變 數 systemState;如 果 其 數 值 為 0,則 表 示 系 統 狀 態 為 「閒 置 」;如 果 其 數 值 為 1,則 表 示 系 統 狀 態 為 「倒 數 進 行 中 」;如 果 其 數 值 為 2,則 表 示 系 統 狀 態 為 「倒 數 完 成 」。程 序 開 始 時 ,我 們 把 systemState 設 定 為 0。
然 後 ,我 們 就 要 把 現 在 的 「時 間 」顯 示 出 來 。我 們 使 用 會 自 動 補 零 的 Display Integer 積 木 來 顯 示 時 間 。
再 來 使 是 設 定 閒 置 時 ,各 按 鍵 的 功 能 。就 像 第 十 課 所 教 的 那 樣 ,我 們 用 一 個 變 數 btn 來 儲 存 Multi-Function Shield 的 按 鍵 狀 態 。還 記 得 麼 ?因 為 有 了 好 使 好 用 的 extension,所 以 一 個 btn 變 數 就 能 管 理 好 全 部 3 個 按 鍵 的 狀 態 。
讓 我 們 先 看 BTN_1 的 部 分 。在 上 例 中 ,如 果 我 們 按 一 下 BTN_1,min 就 會 加 1。雖 然 這 已 經 滿 足 了 我 們 的 需 要 ,但 其 實 Multi-Function Shield 的 library 還 有 一 個 有 少 許 特 別 的 用 法 。
如 果 改 成 上 面 這 種 寫 法 ,除 了 每 按 一 下 會 加 1 之 外 ,長 按 就 會 不 停 加 1 。這 樣 寫 就 會 更 像 現 實 中 的 kitchen timer 了 。
然 後 就 是 min 超 過 99 要 歸 0 的 部 分 ,和 加 入 一 下 短 beep 聲 作 為 使 用 者 輸 入 的 回 饋 。
BTN_2 是 設 定 秒 數 的 ,我 們 也 作 出 和 BTN_1 相 同 的 處 理 。
在 這 一 步 ,我 們 已 經 開 始 去 處 理 關 於 系 統 狀 態 的 邏 輯 ,所 以 我 們 亦 應 順 手 創 建 好 systemState 相 關 的 if then else 積 木 。
將 上 面 幾 個 部 分 加 在 一 起 就 是 上 圖 的 樣 子 。
然 後 我 們 要 處 理 同 時 按 BTN_1 和 BTN_2 ,時 間 會 reset 為 0 的 程 序 。因 為 Multi-Function Shield 的 library 並 沒 有 同 時 按 下 多 鍵 的 狀 態 ,所 以 這 部 分 要 由 我 們 自 己 來 寫 。首 先 我 們 要 兩 個 變 數 btn_1_down 和 btn_2_down 來 記 錄 按 鍵 的 狀 態 ,0 就 代 表 沒 有 按 下 ,1 就 代 表 已 經 按 下 。程 式 加 入 這 兩 個 變 數 之 後 就 是 上 圖 的 樣 子 。
別 忘 了 ,當 button release ( 就 是 使 用 者 放 開 手 時 ) 時 ,我 們 也 要 把 btn_1_down 和 btn_2_down 這 兩 個 變 數 設 回 0。
然 後 我 們 就 可 以 寫 btn_1 和 btn_2 一 起 按 的 程 式 。雖 說 是 兩 鍵 一 起 按 ,但 按 鍵 總 是 有 分 先 後 的 ,所 以 我 們 可 以 把 這 個 事 件 分 作 兩 個 可 能 ,一 個 是 先 按 住 btn_1 然 後 按 下 btn_2,又 或 者 先 按 住 btn_2 然 後 按 下 btn_1。兩 者 所 要 做 的 事 是 完 全 相 同 的 ,就 是 把 時 間 reset 去 0,然 後 系 統 可 以 發 出 一 下 長 beep 來 回 饋 使 用 者 。
然 後 就 是 btn_3。在 systemState = 0 的 時 候 ( 亦 即 閒 置 時 ),按 一 下 btn_3 就 會 開 始 倒 數 計 時 。首 先 ,我 們 要 檢 查 一 下 「時 間 」是 不 是 大 於 0,不 然 開 始 倒 數 也 沒 意 思 。然 後 ,我 們 把 systemState 設 定 為 1,即 「倒 數 進 行 中 」。然 後 ,我 們 要 儲 存 起 分 鐘 和 秒 數 ,以 便 倒 數 完 成 時 重 設 時 間 時 使 用 。因 為 在 倒 數 時 我 們 要 計 時 ,當 然 就 要 reset 一 次 timer。最 後 ,我 們 也 短 beep 一 次 ,作 為 使 用 者 按 鍵 時 的 回 饋 。
把 所 有 東 西 加 在 一 起 ,我 們 的 systemState = 0 的 if block 就 像 上 面 的 樣 子 。下 面 我 們 開 始 處 理 systemState = 1 的 情 況 。
在 systemState = 1,亦 即 是 「倒 數 進 行 中 」的 狀 態 ,我 們 不 停 地 檢 查 「倒 數 時 間 」,如 果 大 於 0,那 每 過 一 秒 ,我 們 便 把 秒 數 減 1。如 果 秒 數 為 0,我 們 便 把 分 鐘 減 1。
如 果 時 間 不 是 大 於 0 ( 即 等 於 0 ),「倒 數 」便 完 成 ,我 們 把 systemState 設 為 2,發 出 提 示 聲 響 ( Quick Alarm ) 以 及 閃 動 顯 示 屏 ( Blink Display ON ) 來 提 示 使 用 者 。
在 「倒 數 進 行 中 」時 ,只 有 一 個 按 鈕 有 效 ,就 是 btn_3,按 下 時 「倒 數 」就 會 暫 停 。
把 上 面 的 東 西 加 在 一 起 ,就 是 readyState = 1 時 的 if block ( 上 圖 )。
終 於 來 到 最 後 的 systemState = 2,亦 即 是 「倒 數 完 成 」的 狀 態 。在 這 個 state,我 們 要 做 的 只 有 一 件 事 ,就 是 把 系 統 狀 態 回 歸 到 0 ( 閒 置 )。當 提 示 聲 播 放 完 ( 我 這 裡 設 定 為 3 秒 ,timer > 3 ),又 或 者 使 用 者 按 下 btn_1、btn_2 或 btn_3,系 統 就 會 回 到 systemState = 0。這 時 候 ,我 們 停 止 閃 爍 顯 示 屏 ,並 時 間 回 復 到 上 一 次 的 倒 數 時 間 。
這 一 課 的 程 式 頗 長 ,下 面 就 是 完 整 kitchen timer 程 式 的 連 結 。
檔 案 下 載 : lesson13.zip
最 後 ,當 然 是 功 課 時 間 :
1. 嘗 試 用 Set Display Brightness block 來 降 低 顯 示 屏 的 亮 度 ,以 達 到 省 電 的 目 的 ;
2. 當 使 用 者 長 按 btn_3 時 ,循 環 改 變 顯 示 屏 的 亮 度 ( 0 -> 1 -> 2 -> 3 -> 0 -> 1 … );
3. 一 般 的 Kitchen Timer 在 倒 數 時 ,時 鐘 的 冒 號 會 閃 爍 。試 用 Multi-Function Shield 的 LED_4 來 模 擬 時 鐘 冒 號 的 閃 爍 ( 用 Set Blinking XXX for LED XXX block ) ;
4. 試 使 用 Multi-Function Shield 來 做 點 什 麼 ( 例 如 :stop watch )。
這 就 是 我 自 製 的 DIY Arduino Kitchen Timer,用 了 一 片 Mega2560 的 外 殼 ( 螺 絲 孔 和 UNO 是 一 樣 的 ,可 以 直 接 安 裝 ) 作 為 底 板 。兩 節 3A / AAA 電 池 盒 是 用 熱 熔 膠 固 定 的 ,上 面 用 了 兩 節 10440 鋰 電 池 。
因 為 Arduino 平 時 也 很 耗 電 ,所 以 加 了 個 開 關 ,不 用 時 就 關 上 ,用 時 才 開 。底 部 用 熱 熔 膠 固 定 了 4 顆 超 強 力 磁 鐵 ,可 以 非 常 穩 固 地 吸 在 雪 櫃 上 面 。
不 要 以 為 這 樣 DIY 一 個 kitchen timer 會 好 貴 ,其 實 全 部 東 西 加 起 來 也 只 要 40-50 蚊 。街 外 面 大 把 kitchen timer 賣 得 更 貴 呢 。