自己寫個 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 檔 ) 的 一 句 。

1
#include <TM1637Display.h>

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

1
#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,設 定 使 用 的 針 腳 ,諸 如 此 類 的 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[
"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 部 分 去 定 義 。

1
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 反 而 我 很 少 用 到 。

1
TM1637Display(uint8_t pinClk, uint8_t pinDIO);

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

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

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

1
display.setBrightness(2);\n

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

TM1637Display Set Brightness Block

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

1
2
3
4
5
6
7
8
9
10
11
12
13
[
"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

接 下 來 我 們 看 看 如 何 實 作 一 個 1602 LCD 的 extension 吧 。

延 伸 閱 讀 :
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 ;

我的 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
[STEM] 如何選購 LED
為什麼安裝新版本的 mBlock 程式之後要重新安裝 mBlock extension?
[STEM] 使用 sensor module 和電子零件的分別
mBlock / Arduino IDE com port 的問題
STEM - 自己造個 Arduino 教學 / 展示平台
修理損壞的 Arduino NANO ( 更換 USB diode )
ctleung張先生,男性,肖龍。
職業:I.T. Consultant
簡介:不好好讀書;七尺差五寸,手長過膝,雙耳垂肩;性寬和,寡言語,喜怒不形於色。據說少時曾斬白蛇於鳳凰山下……

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

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

  1. 陳璽任 says:

    請問在前面的步驟中有個說有副檔名為s2e的部分還有src和js的資料夾應該去哪裡找到呢?我下載後用電腦搜尋也沒有找到這部分,在你的說明裡面有沒有找到能夠去哪裡找到這些檔案。希望可以了解這部分。

    • C.T. Leung says:

      Well… 首先我得問問,究竟你下載了什麼?我這文的 link 也不少。

      假如你是說我為 TM1637 寫的 mblock extension,那是一個 zip 檔,zip 檔裡面就有齊你所問的一切。

      TM1637Display.zip

      難道說,你不會打開 zip 檔??應該不會吧?

Leave a Reply

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