2022年2月19日 星期六

「酷跑遊台灣」之機電整合分享:新北市108年資訊科技教育成果展專案

 「酷跑遊台灣」之機電整合分享:

新北市108年資訊科技教育成果展專案 [1]

Line:ted2016.kpvs
Email:Lct4246@gmail.com
FBhttp://gg.gg/TedLeeFB/
Bloghttp://gg.gg/TedLeeBlog/

Feb. 19, 2022
88x31.png[2]


筆者很幸運地在明志國中戴春城校長「以大御小」的科技領導哲學帶領,並和創客(maker)達師級的進修部林耀坤主任共同合作下,已產出數件中大型創客教育展示教具。是年在明志服務期間,也多次帶著上課班級到校內展示區實際體驗「把玩科技、創造未來」的沉浸式(emerging)跨領域之科技整合教學(大)。更能將之簡化、濃縮成一個個微型的教學模組(小)---師生們遂能從巨觀走向微觀,更是從具體走向抽象。
本專案發表於 108 年 10 月 18-19 日週五至週六兩日在新莊體育館舉辦的「新北市 108 年資訊科技教育成果展」。
明志國中為新北市國民中學科技領域輔導小組召集學校,亦為新北市程式教育示範學校,本參展作品「酷跑遊台灣」(圖 1 )乃結合了科技、健體、社會、數學、藝文等跨領域課程之闖關活動。專案由春成校長領銜,協同進修部林耀坤主任、資訊教師范梅英老師與筆者組成的專案小組共同策畫與執行。
本文乃就筆者參與之「機電整合」部份分享相關的技術內容,以供各方先進及同好不吝賜教。

專案說明

  1. 闖關者在等候區排隊入場。
  2. 一組最多三位玩家,各別在競賽區戴上所屬的 Watch:bit
  3. 玩家於限時內需完成快走環島任務。每組個別快走步數和將依序顯示於展示架的燈條上。
  4. 完成任務後(即環島一週),總成績(步數和轉換成卡路里消耗量)將顯示在排行榜的液晶電視上,並同時更新歷史記錄的前十名。

圖 1:闖關活動場地平面圖

結構設計

本專案的結構及美工設計方面是由耀坤主任親自操刀,台灣地圖規畫與大圖輸出(圖 2)、展示架木工製作(圖 3等等…都來自於他的巧思。

圖 2:台灣地圖設計稿

圖 3:作品展示架

專案架構

如圖 4 所示,本專案從 1~3 位玩家手戴 Watch:bit A-C(傳送端)將慢跑的計數經由板載的 2.4G Hz 無線電廣播傳送給中控的 micro:bit R(接收端)累計加總後,顯示於 WS2812B 燈條的 LED 亮燈(顯示端 1)。最後,在比賽限時一分鐘結束後,將各組最終成績結算,並於液晶螢幕上顯示歷史紀錄前十名的排名(顯示端 2)。

圖 4:專案架構圖

機電整合硬體

筆者採主從式架構(client/ server architecture)來設計機電整合,展示架的接線線路如圖 5 所示。它可分為無線及有線傳輸兩種方式來作為資料的介接:

  1. 客戶端(client side):前端資料以不織布及手工縫紉的錶帶的三塊 Watch:bit 作為客戶端的傳輸載具。這三部 Watch:bit 穿戴在玩家們身上以取得各自的快走步數。
  2. 伺服器端(server side):三家的計步數值全數送往固定在展示架後頭作為伺服器端的 micro:bit R 累計。如所圖 6 所示,此端點以(3/5V)雙電源共地的方式和 WS2812B 的213 顆套管燈條連接來 [3] 展示玩家環台的進度燈號。此外, micro:bit R 以 USB 傳輸線和筆電相接。一方面除了供電給它之外,也透 過mbed 的序列埠驅動程式(https://reurl.cc/pW8M4e)將由 Watch:bit A-C 以無線電廣播傳來各自的計步和透過有線的序列埠傳輸到筆電上。最後,再將 Excel 的排行榜輸出至液晶電視上顯示。

本專案硬體的材料清單詳列如表 1。

圖 5:展示架線路。

圖 6:伺服器端 micro:bit R 的接線

表 1:材料清單

編號

品名

單位

數量

備註

1

手作 Watch:bit(含 micro:bit 主板與 KSB040 鋰電池擴充板各一塊)

3

客戶端

3

收納盒

1

2

micro:bit 主板(含 KSB040 鋰電池擴充板一塊)

1

伺服器端

9

USB 傳輸線

2

10

USB 延長線(2.0 A -A 3 米)

1

4

WS2812B 燈條

1

展示端

5

杜邦線(公母三條、公公一條)

4

6

USB TTL

1

7

5V 變壓器

1

8

魔鬼氈

1

11

延長線

1

12

筆記型電腦

1

13

液晶電視

1

機電整合編程

本專案的編程分成 Watch:bit(傳送端)micro:bit R(接收端)燈條顯示Excel 排行榜四大區塊:

1. Watch:bit A-C   :(https://reurl.cc/QjNW69https://reurl.cc/rQkZ14https://reurl.cc/12l0oV)如圖 6 中紅色區塊所標示,三隻手錶上的程式內容皆相同,僅修改對應的代碼即可。JavaScript 和 MakeCode 的程式碼如表 2 和圖 7 所示。
  • 重置(reset):開始闖關前,選手們都按下A+B按鈕來重置各自的Watch:bit。
  • 開始(start):按下A按鈕後啟動計步器,Watch:bit每動一下便累計行走步數。
  • 停止(stop):當競賽時間到時,三位選手各自按下B按鈕結束計數,並將步數廣播給 micro:bit R。

表 2:Watch:bit A-C端的JavaScript程式

// 啟動計步器

input.onButtonPressed(Button.A, function () {

    basic.showNumber(0)

    start = true

})

// 計步

input.onGesture(Gesture.Shake, function () {

    if (start) {

        no = no + 1

        radio.sendValue("A", no)

        basic.showNumber(no)

    }

})

radio.onReceivedValue(function (name, value) {

    if (name == "AA") {

        ack = 0

        music.playTone(262, music.beat(BeatFraction.Whole))

    }

})

// reset

input.onButtonPressed(Button.AB, function () {

    ack = 0

    no = 0

    start = false

    basic.showString("A")

})

// stop

input.onButtonPressed(Button.B, function () {

    ack = 1

    start = false

})

let no = 0

let start = false

let ack = 0

radio.setGroup(168)

basic.showString("A")

ack = 0

basic.forever(function () {

    if (ack) {

        radio.sendValue("SA", no)

        basic.pause(0)

    }

})


圖 6:伺服器端 micro:bit R 的接線

圖 7:Watch:bit A-C 端的 MakeCode 程式

圖 8:micro:bit R 接收端程式

2. micro:bit R :(https://reurl.cc/44YXdR)如圖 9 紅色區塊所示,MakeCode 和 JavaScript 如表 3 和圖 10 所示。
  • 重置:按下 A+B 按鈕將 micro:bit R 恢復到初始狀態(initial state)
  • 廣播接收:micro:bit R 接收 Watch:bit A-C 的計步廣播資料 (A/ B/ C, 計步值) 如圖 11 所示。
表 3:micro:bit R 端的 JavaScript 程式

// 歸零

input.onButtonPressed(Button.AB, function () {

    basic.showString("R")

    led_sum = 0

    initStrip()

})

radio.onReceivedValue(function (name, value) {

    if (name == "SA") {

        a = value

        radio.sendValue("AA", a)

    } else if (name == "SB") {

        b = value

        radio.sendValue("AB", b)

    } else if (name == "SC") {

        c = value

        radio.sendValue("AC", c)

    }

    if (name == "RA" || name == "RB" || name == "RC") {

        basic.showString("R")

        led_sum = 0

        initStrip()

    } else {

        // stop

        if (name == "SA") {

            a = value

            led_sum = a + (b + c)

            sa = 1

            radio.sendValue("AA", 0)

            basic.pause(0)

        } else if (name == "SB") {

            b = value

            led_sum = a + (b + c)

            sb = 1

            radio.sendValue("AB", 0)

            basic.pause(0)

        } else if (name == "SC") {

            c = value

            led_sum = a + (b + c)

            sc = 1

            radio.sendValue("AC", 0)

            basic.pause(0)

        }

        if (sa && (sb && sc)) {

            basic.showLeds(`

                . # # # .

                # . . # #

                # . # . #

                # # . . #

                . # # # .

                `)

            basic.showNumber(led_sum)

            serial.writeString("Data,")

            serial.writeNumber(led_sum)

            serial.writeLine("")

            sa = 0

            sb = 0

            sc = 0

        } else {

            if (name == "A") {

                a = value

            } else if (name == "B") {

                b = value

            } else if (name == "C") {

                c = value

            }

            led_sum = a + (b + c)

            basic.showNumber(led_sum)

            basic.pause(0)

            if (led_sum <= led_no) {

                showStrip(led_sum)

            }

        }

    }

})

function showStrip (num: number) {

    for (let i = 0; i <= num - 1; i++) {

        strip.setPixelColor(i, strip_color)

        strip.show()

        // 這裡不pause一下下就會出錯,hen

        basic.pause(200)

    }

}

function initStrip () {

    strip_color = neopixel.colors(NeoPixelColors.Yellow)

    a = 0

    b = 0

    c = 0

    sa = 0

    sb = 0

    sc = 0

    strip.clear()

    strip.show()

}

let strip_color = 0

let sc = 0

let sb = 0

let sa = 0

let c = 0

let b = 0

let a = 0

let strip: neopixel.Strip = null

let led_no = 0

let led_sum = 0

radio.setGroup(168)

basic.showString("R")

led_sum = 0

// start from 0

led_no = 213

// 初始化灯條

strip = neopixel.create(DigitalPin.P1, led_no, NeoPixelMode.RGB)

strip.clear()

strip.show()

initStrip()


圖 9:micro:bit R 接收端程式

圖 10:micro:bit R 端的 MakeCode 程式

圖 11:計步廣播

3. 燈條顯示環島進度:如圖 12 中紅色區塊所示。

圖 12:燈條顯示

4. Excel 歷史記錄排行榜:如圖 13 中紅色區塊所示,我們参考了這篇 https://reurl.cc/bkeGWl ,下載 PLX-DAQ(Parallax Data Acquisition tool https://reurl.cc/6EXLqd的 Excel 外掛(plugin)  [4] 並實測(https://reurl.cc/9O01Da)成功。如圖 14 所示, micro:bit R 透過序列埠傳送玩家們的計步和餵到中繼筆電上,再由以 VBA(Visual Basic Application)寫成的 PLX-DAQ 插件接收後將資料記錄於「分數」欄位。接著排行榜表格使用 rank() 函數排出該欄玩家記錄的前十名。此畫面亦將於展場同步顯示在液晶電視上供玩家查核。

圖 13:玩家競技排行榜顯示

圖 14:玩家競技排行榜顯示

來賓闖關翦影

現場展示影片

感謝攝影師蔡建民先生的紀錄(https://reurl.cc/WkzavD ),在影片的 2:15~2:16 可到現場體驗的全貌。


照片

 
 


自主學習情境建置

本專案乃落實春成校長之「以大御小」之科技領導哲思,以中大型教具在校園週遭建置各自主學習角落(learning corner),讓師生們都能從玩教具的過程中去思考科技與教和學的生活關連,徹底實無所不在的(ubiquitous)自主學習精神!

圖 15:以大御小科技領導之自主學習角落環境建置
  1. 本專案因已過保密年限,並經由明志國中(戴春成校長與林耀坤主任)同意而公開分享「機電整合」之技術內容,以供各方同好參考。
  2. 六種授權條款
  3. micro:bit R 串接 KSB034 I/O 擴充板後由筆電供應 3V 電源,燈條由 110V 轉 5V 變壓器供電,兩者間的 GND 彼此相連。另一方面,燈條的資料輸入 DI(Data In) 接到 KSB034 上的 P1 接腳接線。
  4. 該外掛要求:序列埠需調整到編號 7 以內。同時,發送端以( Data, 傳送數值)格式和 Excel 工作表(worksheet)對應之。其中,Data 固定對應到圖 14 的「分數」欄位。

沒有留言: