我的 Stem Project (四) Push Button 進階一點的用法

在 第 三 課 ,我 們 學 了 Push button 的 其 中 一 種 用 法 ,就 是 按 下 作 為 一 個 狀 態 ,放 手 作 為 另 一 個 狀 態 。但 其 實 在 現 實 生 活 中 ,在 很 多 情 況 ,push button 都 不 是 這 麼 用 的 。試 想 像 一 下 mouse click,又 或 者 keyboard 的 keypress,都 是 按 一 下 算 一 下 的 ,並 不 需 要 長 按 著 那 個 push button 的 。

Lesson 3 circuit

Lesson 3 circuit

首 先 ,我 們 用 回 上 一 課 的 電 路 ,整 個 系 統 只 有 一 個 push button 和 一 個 LED

Lesson 03 - Scratch 01

Lesson 04 – Scratch 01

程 式 要 能 夠 知 道 我 們 按 了 幾 次 的 鍵 ( 例 如 打 了 3 個 A 字 ,又 或 者 mouse 的 single click / double click ),就 需 要 有 一 個 變 數 來 記 錄 按 鍵 的 狀 態 。我 們 新 增 一 個 變 數 buttonState,用 來 記 錄 這 一 次 的 按 鍵 狀 態 。另 外 新 增 一 個 變 數 lastButtonState,用 來 記 錄 上 一 個 狀 態 。

在 無 限 循 環 裡 面 ,每 個 循 環 開 始 我 們 都 檢 查 現 在 的 buttonState 是 什 麼 ( 是 True 還 是 False,即 是 按 下 定 放 開 )。在 每 個 循 環 結 束 ,我 們 都 把 現 在 的 buttonState 轉 給 lastButtonState。

這 次 我 們 只 希 望 在 按 鍵 狀 態 出 現 變 化 時 才 做 野 ,所 以 if block 的 比 對 條 件 就 是 not  ( buttonState = lastButtonState )。

好 了 ,我 們 先 把 program upload 去 Arduino,看 看 結 果 如 何 。當 你 按 下 push button 時 ,LED 會 閃 一 下 ,而 當 你 放 開 push button 時 ,LED 會 閃 另 一 下 。而 無 論 你 按 多 久 ( 長 按 ),LED 都 只 會 閃 一 下 的 ,因 為 push button 的 狀 態 只 改 變 了 一 次 。

用 專 業 一 點 的 說 法 ,就 是 你 已 經 用 程 式 捕 捉 到 那 個 push button 的 keyDown event 和 keyUp event 了 。

但 這 好 像 依 然 沒 有 什 麼 實 際 用 途 。好 ,我 們 可 以 再 加 一 個 ledState 的 變 數 ,去 記 錄 LED 的 狀 態 。

Lesson 04 - Scratch 02

Lesson 04 – Scratch 02

在 上 圖 的 第 二 例 中 ,當 button 的 狀 態 改 變 的 時 候 ,我 們 會 檢 查 buttonState 是 0 還 是 1,如 果 是 1 ( = True ),即 時 button 是 按 下 的 ,亦 即 是 keyDown event 發 生 了 。這 時 候 ,我 們 就 會 去 改 變 LED 的 state ( 亮 著 ,還 是 熄 滅 )。

我 們 再 把 program upload 到 Arduino UNO。這 一 次 ,我 們 按 一 次 按 鈕 ,LED 就 會 亮 著 ,再 按 一 次 ,LED 就 會 熄 滅 。這 就 跟 市 面 上 一 般 的 輕 觸 式 開 關 一 樣 了 ,按 一 次 ON,再 按 一 次 就 OFF。

第 二 例 中 也 運 用 了 一 個 小 技 巧 ,在 每 次 扭 鍵 狀 態 轉 變 之 後 ,我 們 都 會 延 遲 0.1 秒 。很 多 時 候 ,物 理 按 鈕 在 按 下 時 都 會 產 生 一 些 抖 動 ,做 成 錯 誤 的 輸 出 ,例 如 你 按 下 一 次 ,但 按 鈕 又 自 己 彈 跳 了 一 次 ,做 成 兩 次 輸 出 。這 情 況 在 英 文 叫 bouncing。我 們 在 每 一 個 讀 取 循 環 最 後 加 入 一 個 wati 0.1 secs block,令 到 程 序 不 會 過 快 地 讀 取 下 一 個 buttonState,這 樣 就 可 以 有 效 減 少 bouncing。這 樣 的 編 程 技 巧 就 叫 做 debouncing

不 過 wait block 並 不 是 好 東 西 ,會 令 整 個 程 序 停 頓 ,不 能 輸 入 輸 出 ,做 不 了 任 何 事 。所 以 ,雖 然 是 麻 煩 一 點 ,還 是 應 該 養 成 使 用 timer block 而 不 用 wait block 的 良 好 習 慣 。經 改 良 後 的 程 式 如 下 。

Lesson 04 - Scratch 03

Lesson 04 – Scratch 03

timer 而 不 用 wait 的 最 大 分 別 ,就 是 雖 然 兩 者 都 是 等 待 了 0.1 秒 ,但 timer 並 不 會 鎖 死 程 序 ,最 外 面 那 個 循 環 ,還 是 一 路 在 執 行 的 。

到 了 第 四 課 ,大 家 應 該 都 熱 好 身 的 了 。上 半 堂 講 了 輸 入 的 技 巧 ,下 半 堂 就 再 多 講 一 個 輸 出 的 技 巧 吧 。

電 腦 是 digital 的 世 界 ,什 麼 都 是 0 與 1,所 有 的 analog 輸 出 ,其 實 都 只 要 模 擬 出 來 的 。那 我 們 又 如 何 用 Arduino 來 模 擬 analog 輸 出 呢 ?

001

記 得 在 第 二 課 ,我 們 學 了  set  digital pin 9 output as HIGH 這 個 block,它 只 能 選 擇 HIGH 或 者 LOW 兩 個 輸 出 ,所 以 很 明 顯 這 只 能 是 digital 的 輸 出 。但 是 ,在 mBlock 裡 面 ,還 有 另 一 個 output 的 block 的 。

002另 一 個 output block 就 是 set pwm pin 5 output as 0。這 個 block 的 重 點 在 PWM,究 竟 什 麼 是 PWM 呢 ?它 的 全 名 是 Pulse Width Modulation。

pwm

PWM 是 一 種 用 digital output 去 模 擬 analog output 的 方 法 ,它 的 做 法 是 將 output 分 成 很 多 個 好 短 好 短 的 cycle,然 後 在 cycle 裡 面 ,按 照 要 輸 出 的 power 的 百 分 比 去 決 定 輸 出 多 少 時 間 。例 如 如 果 要 輸 出 百 分 之 五 十 的 power,就 只 在 50% 時 間 做 輸 出 ,其 餘 時 間 就 不 輸 出 。

如 果 你 把 輸 出 想 像 成 LED,如 果 輸 出 是 50%,那 就 是 有 一 半 時 間 LED 是 亮 的 ,有 一 半 時 間 LED 是 熄 的 。但 因 為 那 個 cycle 是 超 級 短 的 ,所 以 你 不 會 看 到 LED 閃 爍 ,因 為 有 些 時 間 它 是 不 亮 的 ,所 以 你 會 覺 得 它 暗 淡 了 。

mBlock 的 PWM block 的 輸 出 由 0 – 255,一 共 分 作 256 級 。pwm pin 輸 出 0 的 話 ,就 跟 digital pin 是 LOW 一 樣 。如 果 pwm pin 輸 出 255,那 就 和 digital pin 輸 出 HIGH 是 一 樣 的 。

不 過 ,並 不 是 所 有 digital pin 都 可 以 設 定 為 pwm pin 的 。根 據 Arduino 的 documentation,在  Arduino UNO 上 面 ,PWM 只 能 在 pins 3, 5, 6, 9, 10 和 11 上 面 啟 用 。

好 了 ,說 了 這 麼 多 ,現 在 試 試 實 際 操 作 吧 。還 是 用 回 上 面 一 顆 LED 和 一 個 push button 的 電 路 ,不 過 ,因 為 pin 13 並 不 支 援 PWM,所 以 ,請 把 LED 改 接 到 pin 11,而 程 式 則 作 出 如 下 修 改 。

Lesson 04 - Scratch 04

Lesson 04 – Scratch 04

Upload 到 Arduino 之 後 ,當 你 每 按 一 下 push button,變 數 ledState 都 會 加 1。如 果 ledState 大 於 4,則 會 自 動 歸 0。然 後 ,我 們 自 定 的 CHANGE_LED_STATE block,就 會 根 據 ledState 去 改 變 LED 的 亮 度 ,由 0, 31, 63, 127, 255,周 而 復 始 。

( 功 課 :1. 試 試 新 增 一 個 buttonCount 變 數 ,從 而 令 到 每 按 三 次 按 鈕 ,LED 的 亮 度 才 會 產 生 一 次 變 化 。2. 試 試 用 算 式 簡 化  CHANGE_LED_STATE block,例 如 output = 2^(ledState+4) – 1。 )

ctleung張 先 生 ,男 性 ,肖 龍 。
職 業 :I.T. Consultant
簡 介 :不 好 好 讀 書 ;七 尺 差 五 寸 ,手 長 過 膝 ,雙 耳 垂 肩 ;性 寬 和 ,寡 言 語 ,喜 怒 不 形 於 色 。據 說 少 時 曾 斬 白 蛇 於 鳳 凰 山 下 ……
Posted in STEM | Tagged , , , , , , , , | Leave a comment

我的 Stem Project (三) 使用 Push Button 來做 Input

上 一 課 ,我 們 學 會 了 如 何 使 用 Arduino 的 digital pin 作 為 output,非 常 的 容 易 。這 一 次 ,我 們 增 加 一 點 點 難 度 ,嘗 試 把 digital pin 變 為 input。

這 次 我 們 使 用 的 電 子 零 件 ,叫 做 tactile switch,又 叫 push button,是 開 關 ( switch ) 的 其 中 一 種 。在 電 路 裡 面 ,開 關 的 功 能 就 是 閉 合 和 斷 開 電 路 。電 路 要 閉 合 時 ,才 會 有 電 流 流 動 。電 路 中 的 開 關 分 為 兩 大 類 ,toggle switch 和 momentary switch。Push button 就 是 屬 於 momentary switch。

Tactile Switch

Tactile Switch ( 6 x 6 mm )

這 類 輕 觸 式 按 鈕 開 關 ,一 般 會 有 四 隻 腳 。四 隻 腳 會 分 成 兩 組 ,每 組 自 己 本 身 都 會 通 電 的 。而 當 按 鈕 按 下 ,就 四 隻 腳 都 會 通 電 。而 一 放 手 ,又 會 回 復 到 分 成 兩 組 的 狀 態 。

Tactile Switch Circuit

Tactile Switch Circuit

輕 觸 式 按 鈕 開 關 有 大 有 小 ,有 些 可 以 加 上 鍵 帽 。如 果 是 給 孩 子 玩 ,個 人 建 議 按 鈕 可 以 買 大 一 點 的 ,再 加 上 大 一 點 的 鍵 帽 ,按 起 來 會 舒 服 很 多 。

Tactile button 的 大 小 是 按 mm 算 的 ,常 見 是 6 x 6mm,一 般 我 會 買 大 一 點 12 x 12mm 的 。不 管 是 那 一 個 大 小 ,Tactile button 都 可 以 直 接 插 在 麵 包 板 上 使 用 ,方 便 得 很 。Tactile button 通 常 會 有 圓 形 正 方 形 顏 色 鍵 帽 ,鍵 帽 上 面 可 以 再 加 透 明 帽 蓋

讓 我 們 先 按 照 下 圖 建 立 我 們 這 一 課 要 用 的 電 路 。

Lesson 2 circuit

Lesson 2 circuit ( pull down )

LED 還 是 照 舊 接 在 Pin 13。至 於 新 的 Tactile button,接 法 有 點 特 別 ,可 能 不 是 那 麼 的 直 觀 。Tactile button 有 四 個 pin,在 同 一 邊 ,相 鄰 的 兩 個 pin 是 不 通 的 ,但 在 對 邊 ,跟 自 己 成 一 直 線 的 兩 個 pin,則 是 互 通 的 ( A-B 是 通 的 ,C-D 是 通 的 )。

我 們 先 把 tactile button 的 其 中 一 pin ( pin A ) 接 到 Arduino UNO 的 Pin2,我 們 以 Pin 2 作 為 我 們 的 input pin。為 了 在 沒 有 按 鍵 的 狀 態 給 Pin 2 一 個 LOW 的 信 號 ,我 們 要 把 Tactile button 相 連 的 那 一 pin ( pin B )  接 到 GND。而 Tactile button 的 另 一 邊 ( pin D ),我 們 要 連 接 到 5V,於 是 ,當 按 鍵 被 按 下 ,Pin 2 就 會 接 收 到 一 個 HIGH 的 信 號 。

以 上 的 這 一 個 設 置 ,pin B 接 地 的 時 候 必 須 要 加 上 一 個 電 阻 ,以 防 止 按 鈕 時 短 路 ,燒 毀 Arduino。我 們 這 樣 以 一 個 電 阻 把 input pin 在 沒 有 輸 入 時 接 地 的 接 駁 方 法 ,那 個 電 阻 ,就 叫 做 pull down resistor。

建 立 好 電 路 之 後 ,讓 我 們 看 看 程 式 的 部 分 。

Lesson 2 Scratch

Lesson 2 Scratch ( pull down )

在 程 式 裡 ,我 們 建 立 了 一 個 無 限 循 環 。在 循 環 裡 面 ,我 們 不 停 去 檢 查 pin 2 的 值 。如 果 訊 號 是 HIGH 的 話 ,它 就 會 傳 回 True。如 果 是 LOW,它 就 會 傳 回 False。我 們 用 一 個 if block 去 判 斷 ,如 果 True,就 點 亮 pin 13 的 LED,如 果 False,就 熄 滅 之 。

完 成 程 式 之 後 就 按 Upload to Arduino。完 成 之 後 ,當 你 按 下 電 路 中 的 按 鍵 ,LED 燈 就 會 亮 起 。當 你 放 手 ,LED 就 會 熄 滅 。

在 前 面 的 例 子 ,我 們 把 input pin 接 到 ground,中 間 加 一 個 pull down resistor。其 實 ,做 input 還 有 另 外 一 種 接 法 的 ,且 看 下 圖 。

Lesson 2 circuit ( pull up )

Lesson 2 circuit ( pull up )

第 二 個 接 法 ,我 們 會 把 pin 2 在 沒 有 按 鍵 的 時 候 接 到 5V / 3.3V,令 input pin 長 期 處 於 一 個 HIGH 的 訊 號 。而 Tactile button 的 另 一 邊 ,我 們 會 接 地 。於 是 ,當 按 鍵 按 下 時 ,pin 2 就 會 接 地 而 令 訊 號 變 成 LOW。在 這 個 方 法 ,我 們 把 電 阻 連 接 到 高 電 壓 的 一 邊 ,所 以 這 個 電 阻 就 叫 做 pull up resistor。

在 第 二 種 接 法 ,亦 即 是 使 用 pull up resistor 的 接 法 ,HIGH 和 LOW 的 訊 號 會 和 之 前 相 反 。所 以 ,我 們 的 程 式 亦 要 作 出 相 應 的 調 整 。在 pull up 的 接 法 ,不 按 鍵 時 是 True ( HIGH ),按 鈕 時 才 是 False ( LOW )。

Lesson 2 Scratch ( pull up )

Lesson 2 Scratch ( pull up )

雖 然 按 鈕 的 接 法 不 同 ,程 序 也 不 同 ,但 最 後 用 起 來 是 完 全 一 樣 的 。按 鍵 時 LED 會 亮 著 ,放 手 時 LED 會 熄 滅 ,大 家 不 要 搞 錯 了 。

就 這 樣 ,你 便 學 識 了 如 何 用 Tactile button 在 Arduino 上 面 做 input,而 且 仲 係 兩 種 唔 同 的 方 法 ,係 唔 係 好 開 心 呢 ?現 在 ,大 家 可 以 用 按 鈕 來 嘗 試 觸 發 不 同 的 事 件 。( 功 課 :1. 按 鍵 時 LED 閃 動 ,不 按 鈕 時 LED 熄 滅 ;2. 使 用 兩 顆 LED,按 鍵 時 A 亮 B 滅 ,不 按 鍵 時 A 滅 B 亮 ; 3. 使 用 兩 顆 LED 和 兩 個 按 鈕 ,按 A 鍵 時 LED A 亮 ,按 B 鍵 時 LED B 亮 。)

pull up 和 pull down 兩 種 方 法 ,究 竟 那 一 個 比 較 好 呢 ?個 人 覺 得 應 該 是 沒 有 差 別 的 。但 基 於 某 種 神 秘 原 因 ( 也 許 是 歷 史 遺 留 的 原 因 ? ),在 現 實 世 界 ,pull up 是 比 pull down 常 見 許 多 許 多 的 。

甚 至 乎 ,Arduino 使 用 的 ATmega328p 晶 片 ,本 身 就 內 建 了 20K pull up resistor 可 供 input pin 使 用 。在 Arduino IDE,我 們 只 要 設 定 pinMode 為 INPUT_PULLUP 就 可 以 直 接 使 用 ,連 接 按 鈕 和 其 他 sensor 就 簡 單 得 多 。

pinMode( pin , INPUT );    // 不 使 用 internal pull up resistor
pinMode( pin , INPUT_PULLUP );   // 啟 用 internal pull up resistor

不 過 ,可 惜 的 是 ,mBlock 並 沒 有 供 我 們 啟 用 internal pull up resistor 的 選 項 ,我 們 還 是 乖 乖 的 自 行 外 接 pull up 又 或 者 pull down resistor 吧 。

Arduino 的 documentation 建 議 我 們 使 用 10KΩ 的 電 阻 ,作 為 pull up 或 者 pull down resistor。

ctleung張 先 生 ,男 性 ,肖 龍 。
職 業 :I.T. Consultant
簡 介 :不 好 好 讀 書 ;七 尺 差 五 寸 ,手 長 過 膝 ,雙 耳 垂 肩 ;性 寬 和 ,寡 言 語 ,喜 怒 不 形 於 色 。據 說 少 時 曾 斬 白 蛇 於 鳳 凰 山 下 ……
Posted in STEM | Tagged , , , , , , , | Leave a comment