自己寫個 mBlock extension (一) TM1637 4-digit-display

Arduino 有 林 林 總 總 各 式 各 樣 的 Sensors,絕 大 部 分 Sensors 的 店 家 ,都 會 提 供 能 在 Arduino 上 使 用 的 libraries。但 偏 偏 這 些 Arduino libraries 都 不 能 夠 直 接 在 mBlock 上 面 使 用 ,對 廣 大 的 入 門 使 用 者 造 成 了 相 當 的 困 難 。

但 其 實 ,mBlock 本 身 亦 有 擴 展 功 能 ,不 過 它 不 叫 libraries,而 是 叫 做 extensions。其 實 我 們 只 要 通 過 幾 個 簡 單 的 步 驟 ,就 可 以 把 sensor 的 arduino library 自 己 改 寫 成 mblock 用 的 extension。下 面 我 們 一 起 實 作 幾 個 例 子 吧 。

筆 者 手 邊 正 好 有 幾 個 不 同 類 型 的 顯 示 器 ,正 好 拿 來 作 示 範 用 途 。

4-digit display

第 一 個 就 是 在 之 前 《我 的 Stem Project (八 )》也 有 用 過 的 4 位 數 碼 管 ,它 是 由 一 個 TM1637 晶 片 去 推 動 的 。之 前 第 八 課 ,那 個 由 店 家 提 供 的 Arduino Library 其 實 很 不 好 用 ,所 以 這 一 次 ,我 就 選 了 另 一 個 在 Arduino 網 頁 找 得 到 的 TM1637 Arduino Library,名 字 就 叫 TM1637Display。

介 紹 :https://playground.arduino.cc/Main/TM1637

介 紹 :https://github.com/avishorp/TM1637

下 載 :https://github.com/avishorp/TM1637/releases/

我 下 載 的 是 v1.1.0,解 壓 之 後 裡 面 有 很 多 檔 案 ,也 有 例 子 之 類 的 。要 自 己 改 寫 成 mBlock extension,我 們 只 需 要 裡 面 的  TM1637Display.h 和  TM1637Display.cpp。.h 檔 和 .cpp 檔 才 是 arduino library 真 正 的 source code 所 在 。

TM1637Dispaly Arduino Library

有 了 源 材 料 ,我 們 就 可 以 開 始 打 造 我 們 的 第 一 個 mBlock extension 了 。每 一 個 mBlock extension 其 實 就 是 一 個 folder,有 其 相 關 的 獨 特 格 式 。

mBlock extension folder structure

首 先 ,我 們 會 有 一 個 *.s2e 檔 ,這 檔 案 是 用 來 定 義 整 個 extension 的 ,可 以 說 是 整 個 extension 的 靈 魂 。然 後 分 別 會 有 兩 個 sub-folder。第 一 個 是 src ( 指 source ),就 是 存 放 Arduino Library 的 地 方 ,亦 即 是 前 面 所 說 的 *.h 檔 和 *.cpp 檔 。另 一 個 是 js,是 存 放 javascript 碼 的 地 方 。

src 的 Arduino Library 是 在 Arduino Mode 時 用 的 ,而 js 內 的 javascript,則 是 Scratch Mode 時 使 用 的 。因 為 我 不 太 理 解 ( 也 覺 得 沒 有 需 要 ) Scratch Mode 的 運 作 方 式 ,所 以 我 不 打 算 花 時 間 去 寫 javascript 的 部 分 ,所 以 在 這 裡 下 載 的 mBlock extension 只 會 在 Arduino Mode 有 用

首 先 ,我 們 先 在 電 腦 上 建 立 一 個 「TM1637Display」的 folder,作 為 這 個 mBlock extension 的 根 目 錄 。然 後 我 們 建 立 一 個 「src」的 sub-folder,然 後 就 把 「TM1637Display.h」和 「TM1637Display.cpp」兩 個 檔 案 複 製 到 src 目 錄 裡 面 。

The include header line.

因 為 mBlock 和 Arduino IDE 的 引 用 方 式 不 同 ,所 以 我 們 要 對 這 個 library 作 出 一 點 點 的 小 改 變 。首 先 ,我 們 打 開  TM1637Display.cpp 檔 ,在 第 24 行 會 有 引 用 header 檔 ( *.h 檔 ) 的 一 句 。

#include <TM1637Display.h>

我 們 要 把 它 改 成 下 面 的 樣 子 ,即 是 那 個 「單 書 名 號 」( < > ) 要 改 成 「雙 引 號 」( double quotes )。

#include "TM1637Display.h"

如 果 沒 有 更 正 ,那 我 們 在 mBlock 按 下 Upload to Arduino 時 ,就 會 見 到 一 些 找 不 到 檔 案 之 類 的 錯 誤 。值 得 注 意 的 是 ,所 有 其 它 的 include 行 ,都 是 不 用 修 改 的 。只 有 在 引 用 src 目 錄 裡 面 的 檔 案 的 時 候 ,我 們 才 要 把 「書 名 號 」改 為 「雙 引 號 」。

改 好 之 後 就 保 存 檔 案 ,然 後 我 們 就 可 以 開 始 寫 那 個 s2e 檔 案 。

s2e Format

s2e 檔 亦 有 自 己 的 特 定 格 式 。整 個 s2e 檔 案 ,其 實 就 是 一 個 JSON object。裡 面 又 分 成 幾 個 部 分 ,首 先 是 basic information,就 是 基 本 資 料 ,例 如 名 稱 ,作 者 等 等 的 資 訊 。然 後 就 是 block definition,就 是 定 義 我 們 在 mBlock 裡 面 會 使 用 的 積 木 。然 後 就 是 menus,values 和 translators,這 3 項 我 們 後 面 再 講 。

Basic Information

首 先 我 們 在 extension 的 根 目 錄 建 立 一 個 叫  TM1637Display.s2e 的 純 文 字 檔 。然 後 按 照 mBlock 提 供 的 例 子 寫 好 了 我 們 的 基 本 資 料 。這 裡 面 最 重 要 的 是 extensionName,因 為 這 個 是 不 可 以 和 別 的 extension 相 同 的 ,所 以 要 改 得 有 技 巧 一 點 。我 自 己 的 習 慣 ,就 是 用 回 Arduino Library 的 名 字 。一 來 是 易 記 ,二 來 也 不 容 易 撞 名 ( 所 以 你 見 到 我 的 folder 名 和 檔 名 都 是 跟 library 名 的 ,在 此 例 中 就 是 「TM1637Display」)。

s2e defining blocks

再 來 就 是 重 頭 戲 ,寫 block definition 了 。所 有 的 block 就 放 在 blockSpecs 裡 面 ,是 一 個 Array,Array 就 意 味 著 你 想 放 多 少 個 block 都 可 以 。那 究 竟 這 個 extension 我 們 需 要 多 少 個 積 木 呢 ?

TM1637Dispaly usage

在 TM1637Display 的 說 明 文 件 裡 ,我 們 知 道 這 個 library 有 4 個 方 法 給 我 們 去 用 ,但 其 實 我 們 不 一 定 需 要 把 library 的 所 有 方 法 都 改 寫 成 積 木 的 。例 如 我 就 覺 得 setSegments 沒 什 麼 用 ,而 我 的 display 也 沒 有 小 數 點 ,也 就 不 去 改 寫 showNumberDecEx 了 。( 這 些 留 給 讀 者 自 己 去 補 回 ,哈 哈 )

如 果 大 家 是 完 全 沒 有 寫 Arduino IDE 的 經 驗 ,可 能 會 覺 得 吃 力 一 點 。但 其 實 只 要 讀 一 次 header 檔 ( *.h 檔 ),所 有 的 functions 都 會 在 裡 面 的 了 。然 後 再 仔 細 看 一 下 library 裡 面 的 examples,應 該 都 可 以 了 解 到 發 生 了 什 麼 事 。

TM1637Display Initialize Block

一 般 來 說 ,extension 的 第 一 個 積 木 ,大 都 是 初 始 化 那 個 extension,例 如 include library,initialize 個 class,設 定 使 用 的 針 腳 ,諸 如 此 類 的 。

[
"w",
"TM1637Display Initialize CLK pin %d.pin DIO pin %d.pin",
"TM1637Display",
"2",
"3",
{
"setup":"display.setBrightness(2);\n",
"inc":"#include \"TM1637Display.h\"\nTM1637Display display({0},{1});\n",
"def":"",
"work":"",
"loop":""
}
],

在 上 面 的 例 子 中 ,第 一 行 的 w,是 指 積 木 的 種 類 。w 是 指 write blocks,是 發 送 command 去 電 子 零 件 的 ,一 般 來 說 ,最 常 用 的 積 木 就 是 write blocks。r 則 是 reading blocks,是 由 電 子 零 件 讀 取 一 個 數 值 回 來 。b 是 binary blocks,它 跟 reading block 很 相 似 ,但 傳 回 的 只 是 true / false 的 值 。

第 二 行 就 是 定 義 積 木 的 文 字 和 輸 入 。例 如 %n 和 %d 是 輸 入 number,%s 和 %m 是 string。%n 和 %d 都 是 輸 入 數 字 ,它 們 的 分 別 在 於 %d 可 以 加 入 一 個 選 單 ,給 使 用 者 去 選 擇 。而 這 些 選 單 ,就 是 在 後 面 的 menus 部 分 去 定 義 。

TM1637Display Initialize CLK pin %d.pin DIO pin %d.pin

例 如 我 在 menus 裡 面 定 義 了 一 個 叫 pin 的 menu,選 項 內 容 就 是 由 1 到 13。然 後 我 用 %d.pin 的 語 法 來 使 用 它 。

s2e menus

兩 者 加 在 一 起 ,就 會 造 出 下 面 這 個 樣 子 的 積 木 了 。

TM1637Display Initialize Block

然 後 就 是 第 三 行 ,那 是 javascript function name,因 為 我 不 寫 javascript 的 部 分 ,所 以 我 都 是 隨 便 改 個 不 重 覆 的 名 字 就 算 了 。

第 四 行 和 第 五 行 ,是 輸 入 的 預 設 值 ( default values )。這 裡 大 家 要 非 常 小 心 ,因 為 我 這 個 積 木 是 兩 個 輸 入 ,所 以 必 須 是 寫 兩 行 ,兩 個 預 設 值 。如 果 你 的 積 木 只 有 一 個 輸 入 ,就 寫 一 行 ,兩 個 輸 入 就 寫 兩 行 ,三 個 輸 入 就 寫 三 行 ,如 此 類 推 。如 果 你 的 積 木 沒 有 輸 入 ,就 一 行 也 不 用 寫 。這 個 千 萬 不 要 出 錯 。

然 後 由 我 的 第 七 行 至 第 十 一 行 ,分 別 是 setup、inc、def、work 和 loop。是 分 別 定 義 把 程 式 碼 寫 到 Arduino Sketch 的 不 同 部 分 。inc 就 是 放 置 include 語 句 和 初 始 化 語 句 的 地 方 。def 就 是 定 義 變 數 和 常 數 的 地 方 。setup 就 是 程 式 開 始 時 會 執 行 一 次 的 地 方 ,有 時 會 把 一 些 設 定 放 在 這 裡 做 。work 就 是 正 常 放 置 這 個 積 木 相 關 巧 能 的 程 式 碼 的 地 方 。loop 反 而 我 很 少 用 到 。

TM1637Display(uint8_t pinClk, uint8_t pinDIO);

再 回 到 上 面 的 例 子 ,因 為 是 初 始 化 的 積 木 ,所 以 只 有 inc 和 setup 才 有 內 容 。在 inc 裡 面 就 是 先 include 了 library,然 後 用 library 的 constructor 建 立 一 次 。在 初 始 化 的 時 候 ,我 們 要 用 到 CLK pin 和   DIO pin 的 號 碼 ,這 時 候 我 們 需 要 用 到 使 用 者 輸 入 。使 用 者 在 積 木 中 的 輸 入 ,會 變 成 一 組 特 殊 的 變 數 ,由 第 一 個 輸 入 開 始 ,分 別 會 變 成 {0},{1},{2},…. ,如 此 類 推 。只 要 把 它 們 替 代 到 相 關 的 地 方 使 可 以 了 。

TM1637Display display({0},{1});\n

大 家 特 別 留 意 一 下 兩 個 特 殊 字 符 ,第 一 個 是 「\”」,要 在 內 容 中 使 用 「雙 引 號 」,「雙 引 號 」前 面 要 加 上 「\」。第 二 個 是 「\n」,這 是 代 表 new line ( 分 行 ) 的 意 思 。這 些 是 JSON 的 語 法 ,就 不 用 深 究 為 什 麼 了 。

display.setBrightness(2);\n

而 在 setup 裡 面 ,我 順 手 在 程 式 開 始 時 把 顯 示 器 的 光 度 設 定 為 2。

TM1637Display Set Brightness Block

我 的 第 二 個 積 木 ,就 是 set brightness 積 木 。

[
"w",
"TM1637Display Set Brightness %d.brightness",
"displayBrightness",
"2",
{
"setup":"",
"inc":"",
"def":"",
"work":"display.setBrightness({0});\n",
"loop":""
}
],

同 樣 是 w 類 的 積 木 ,但 今 次 只 有 一 個 輸 入 。輸 入 亦 在 menus section 做 了 一 個 menu,就 叫 birghtness,數 值 由 0 去 到 7。預 設 值 只 有 一 個 ,數 值 是 2。因 為 這 是 功 能 性 的 積 木 ,所 以 只 在 work 裡 面 有 內 容 。

TM1637Display Set Brightness Block

最 後 就 是 Display 積 木 ,這 是 用 來 顯 示 數 字 到 顯 示 器 的 ,所 以 同 樣 是 w 積 木 。這 個 積 木 亦 只 有 一 個 輸 入 ,預 設 值 為 1234。這 個 積 木 亦 是 只 有 在 work 才 有 內 容 。

TM1637Display Display Block

TM1637Display Display Block

在 這 個 我 們 寫 的 第 一 個 Library,我 們 就 不 加 入 values 和 translators 了 。保 存 好  TM1637Display.s2e 檔 之 後 ,我 們 把 整 個 extension 的 folder ( TM1637Display ) 做 成 一 個 zip 檔 ( TM1637Display.zip )。這 個 zip 檔 就 是 你 的 extension 的 安 裝 檔 了 ,你 要 給 朋 友 用 ,又 或 者 及 佈 到 互 聯 網 ,都 是 發 一 個 zip 檔 出 去 就 行 。

mBlock extension 下 載 : TM1637Display.zip

要 在 mBlock 使 用 這 個 extension,只 要 在 mBlock 選 Extensions >> Manage Extensions。然 後 按 下 Add Extension,在 File name 後 面 的 檔 案 格 式 改 為 zip,再 選 取 上 面 的  TM1637Display.zip 檔 案 ,再 按 一 下 Open 就 完 成 了 。

Manage Extensions

完 成 之 後 ,你 就 可 以 見 到 自 己 的 extension 了 。關 上 對 話 閘 ,在 Arduino Mode,去 到 Robots 類 別 ,就 可 以 見 到 新 增 加 的 積 木 了 。

New Blocks

然 後 當 然 第 一 時 間 接 駁 好 顯 示 器 ,寫 個 小 程 式 ,測 試 一 下 各 個 新 積 木 的 功 能 。

Test New Extensions

如 果 一 切 正 常 ,你 應 該 可 以 見 到 顯 示 器 由 0000,1111,….,7777 這 般 循 環 顯 示 ,而 且 也 會 由 最 暗 ,一 直 增 加 到 最 光 。

這 個 TM1637Display library 雖 說 好 使 好 用 ,但 它 原 來 是 給 有 小 數 點 的 4 位 顯 示 器 用 的 ,和 我 的 4 位 時 間 顯 示 器 不 太 兼 容 。至 少 ,它 不 能 點 亮 那 個 時 間 的 冒 號 。其 實 很 多 電 子 零 件 的 Arduino library 都 不 只 得 一 套 ,大 家 其 實 可 以 多 看 幾 套 ,才 決 定 用 那 一 套 來 製 作 自 己 的 mBlock extension。

其 實 我 的 4 位 時 間 顯 示 器 真 正 的 library 是 下 面 這 個 ,但 要 把 它 改 成 mBlock extension 是 有 一 點 點 難 度 的 ,未 必 適 合 作 為 入 門 的 教 材 ,所 以 在 這 一 篇 我 們 就 暫 時 不 討 論 。

Grove – 4-Digit Display ( time display ) Library

延 伸 閱 讀 :
1. Writing a Library for Arduino ;
2. Create Extensions for mBlock ;
3. Getting Start with mBlock (PDF) ;
4. The Programing Structure of an Arduino Sketch ;
5. Arduino – Wire Library ( I2C ) ;
6. Arduino Playground – I2C Scanner ;

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

我 的 STEM Project 系 列

我 的 Stem Project (一 ) Raspberry Pi 3 vs Arduino UNO
我 的 Stem Project (二 ) 使 用 Scratch 來 控 制 Arduino UNO
我 的 Stem Project (三 ) 使 用 Push Button 來 做 Input
我 的 Stem Project (四 ) Push Button 進 階 一 點 的 用 法
如 何 購 買 Arduino ?( STEM project )
我 的 Stem Project (五 ) 考 反 應 小 遊 戲
我 的 Stem Project (六 ) 用 Arduino 控 制 7 segment display (基 礎 篇 )
我 的 Stem Project (七 ) 用 Arduino 控 制 7 segment display ( 進 階 篇 )
我 的 Stem Project (八 ) 用 Arduino 控 制 7 segment display ( 簡 化 篇 )
我 的 Stem Project (九 ) 用 Arduino 控 制 Buzzer 唱 歌
我 的 Stem Project (十 ) Arduino Multi-function Shield using Scratch (1)
自 己 動 手 做 一 個 Arduino Shield ( STEM project )
我 的 Stem Project (十 一 ) Arduino Multi-function Shield using Scratch (2)
我 的 Stem Project (十 二 ) Arduino Music Light Show
Arduino 的 電 池 ( STEM project )
我 的 Stem Project (十 三 ) Arduino Multi-function Shield using Scratch (3)
自 己 寫 個 mBlock extension (一 ) TM1637 4-digit-display
自 己 寫 個 mBlock extension (二 ) 1602 I2C LCD Module
自 己 寫 個 mBlock extension (三 ) 2-digit-display using 74HC595

This entry was posted in STEM and tagged , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *