中文 | English

「防疫大作戰」之機電整合分享:新北市三重區明志國中 2020 科技專案

作者:Ted Lee

繼前文《「酷跑遊台灣」之機電整合分享:新北市108年資訊科技教育成果展專案》,本文仍以科技專案系列之機電整合技術分享為前題,揭露筆者於筆者 2020 年二月獲新北市三重區明志國中戴春城校長邀請,和進修部林耀坤主任創客達師(master maker)共同合作產出的作品。

本專案透過 Arduino 程式設計與感測器連結,發展出創新的機電整合課程。老師們使用 PBL 教學法指導學生自製闖關道具,運用課堂所學習到的數學及藝文關鍵素養,再結合健康促進之新冠病毒防疫議題,發展出動手實作的 STEAM 課程,以達到跨領域的學習目標,並具有寓教於樂的功能。

圖 1:筆者近四年來和明志國中的共同創作專案及作品

專案說明

明志國中為新北市 108 學年度國民中學科技領域輔導小組召集學校,亦為新北市程式教育示範學校,為作表率本校將在本展中展示結合科技、健體、社會、數學、藝文等跨領域課程之闖關活動「防疫大作戰」(圖 2)。

本專案由戴春成校長(圖 2 左1)領銜,協同進修部林耀坤主任(圖 2 右2)與筆者組成的專案小組指導若干學生們共同策畫與執行。

圖 2:防疫大作戰展示實景

操作方式為病毐聖戰士們手握如圖 3 中的重裝武器一同站立於黃色發射線後準備撃潰黑暗的病毐軍團。

圖 3:聖戰士們手持防禦性重兵器並齊立於黃色發起線後誓言要摧毀頑強的病毐大軍

每一回合按下圖 4 病毒轉盤左下的紅色按鈕(戴口罩小朋友頭頂左上方處)後藍色的病毒本體開始運轉。左上角的燈板會開始倒數計時兩分鐘。當聖戰士將子彈撃穿病毒的本體後,它就會中彈受傷。此時右上角的燈板就會累計聖戰上的戰績。

圖 4:囂張的病毒正在世界各地轉動肆虐著

專案架構

本專案依各自功能可區分為機構設計、機電整合電路設計與機電整合控制程式設計三大區塊。詳細說明如 1、2 及 3 小節所示。

1. 機構設計

本專案的機構設計乃由耀坤主任親自操刀,共分為射撃裝置和病毒轉盤兩件。

圖 5 中左二學生手持雷切製成的射撃槍即為射撃裝置一。它以內置的彈簧拉力來撃發乒乓球。此外,右一及右二學生手持的桶狀簡易射撃裝置是以回收的洋芋片罐加裝汽球以做為射撃的動力的來源。

圖 5:射撃裝置機構

圖 6 的病毒轉盤融合了耀坤主任精湛的木工技藝以及美術專長特製而成。轉盤上頭裝有計時和計分的燈板各一組。接著是以軸心連接後方齒輪的藍色病毒 COVID-19 模型。

圖 6:病毒轉盤

在病毒轉盤背後,上方是電路控制室。它剛好座落在圖 6 燈板的正後方。中間綠色小齒輪和 AC 馬達相接而形成齒輪動力組,藉此帶動和綠色大齒輪串在一起的圖 6 藍色病毒模型,內部中空相連情形如圖 8 所示。其中,圖 9 及圖 10 為耀坤主任親自指導學生以木工製作大小齒輪組的過程。

此外,圖 7 綠色大齒輪下方的集球溝內埋有一只細長柄的微動開關(micro switch)做計分偵測之用。

圖 7:齒輪動力組

圖 8:病毒轉盤的內部中空結構

圖 9:連接 AC 馬達的小齒輪

圖 10:帶動前方藍色病毒的大齒輪

2. 機電整合電路設計

本專案需求功能三:

計時:按下啟動按鈕後開始倒數 2 分鐘(120秒)並於燈板上顯示剩餘時間。
計分:有球進洞後需計分並於燈板上顯示累計得分。
重置(reset):按下啟動按鈕後轉動病毒轉盤重新開局。

由於我們尋獲的燈板是以 UART 和 Nano 開發板通信,而一塊 Nano 板只有一個 UART 通信通道。因而我們以 sss(signal to scoring Nano)接線來串接(cascade)計時 Nano(圖 11)和計分 Nano(圖 12)。

在圖 10的計時線路中,按鈕採下拉(pull down)設計以維持準確的電壓準位。和燈板以 D0(Rx)和 D1(Tx)兩支接腳進行序列傳輸。最後,使用一顆繼電器(relay)來控制病毒轉盤組的 AC 慢速馬達。

在圖 12 的計分電路中,燈板的接法和計時線路相同。三路的微動開關也是採用下拉的設計來處理。整體的接線以模組化(modularized)的方式來佈局(layout),方便除錯和後續教學解說。完成後的電路控制箱如圖 13 和圖 14 所示。專案的所有材料清單如表 1 所示。

表 1:材料清單

表1

圖 11:計時接線圖

圖 12:計分接線圖

圖 13:電路控制箱

圖 14:電路控制箱近照

3. 機電整合控制程式設計

由於第 2 小節的模組化硬體設計,我們也以計時和計分來撰寫相對應的控制程式。這兩隻程式設計的流程圖如圖 15 所示。

圖 15:計時與計數程式的流程圖

計時程式在處理完按鈕彈跳(debounce)的機械特性後才進入計時燈板刷新(refresh)與繼電器控制馬達的程式邏輯。完整程式碼如下:

#define relay_pin 3

#define sss_pin 12

const int buttonPin = 2; // the number of the pushbutton pin

// Variables will change:

//int ledState = HIGH; // the current state of the output pin

int buttonState; // the current reading from the input pin

int lastButtonState = LOW; // the previous reading from the input pin

// the following variables are unsigned longs because the time, measured in

// milliseconds, will quickly become a bigger number than can be stored in an int.

unsigned long lastDebounceTime = 0; // the last time the output pin was toggled

unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers

void ini() {

lastButtonState = LOW;

lastDebounceTime = 0;

}

void setup() {

pinMode(relay_pin, OUTPUT);

pinMode(buttonPin, INPUT);

pinMode(sss_pin, OUTPUT);

Serial.begin(115200); //設定UART

delay(1000);

Serial.print(“atd0=()”); //清除畫面

while (Serial.read() != ‘E’) {} //等待燈板完成動作

Serial.print(“at2b=(0)”); //設定為覆蓋模式

while (Serial.read() != ‘E’) {} //傳送指令終止的字元

} //end of setup()

void loop() {

// read the state of the switch into a local variable:

int reading = digitalRead(buttonPin);

// check to see if you just pressed the button

// (i.e. the input went from LOW to HIGH), and you’ve waited long enough

// since the last press to ignore any noise:

// If the switch changed, due to noise or pressing:

if (reading != lastButtonState) {

// reset the debouncing timer

lastDebounceTime = millis();

}

if ((millis() – lastDebounceTime) > debounceDelay) {

// whatever the reading is at, it’s been there for longer than the debounce delay, so take it as the actual current state:

// if the button state has changed:

if (reading != buttonState) {

buttonState = reading;

// only toggle the LED if the new button state is HIGH

if (buttonState == HIGH) {

//Spin the wheel

digitalWrite(relay_pin, HIGH);

//Score counting

digitalWrite(sss_pin, HIGH);

//Time counting

//Serial.print(“atef=(4)”); //設定文字顏色為綠色

//while (Serial.read() != ‘E’) {}

//Serial.print(“at83=(1,0,Count:)”); //顯示8×16字型 Count: 字串

//while (Serial.read() != ‘E’) {}

Serial.print(“atef=(32)”); //設定數字顏色為0:Black、3:B、4:G、32:R

while (Serial.read() != ‘E’) {}

for (int i = 120; i > 0; i–) {

Serial.print(“atd0=()”); //清除畫面

while (Serial.read() != ‘E’) {} //等待燈板完成動作

Serial.print(“at83=(1,3,”); //傳送部分指令

Serial.print((String)i); //傳送指令中變動的部分

Serial.write(‘)’); //傳送指令終止的字元

while (Serial.read() != ‘E’) {}

delay(950);

//Serial.print(“atd0=()”); //清除畫面

//while (Serial.read() != ‘E’) {} //等待燈板完成動作

} //end of for loop

digitalWrite(sss_pin, LOW);

digitalWrite(relay_pin, LOW);

} //end of if

} //end of if

} //end of if

// save the reading. Next time through the loop, it’ll be the lastButtonState:

lastButtonState = reading;

//ini();

} //end of loop()

啟動按鈕被按下後,計時程式就會收到計時線路傳來的 sss 信號。當微動開關被聖戰士射入的乒乓球按壓後才進入計分燈板更新計分的程式邏輯。完整程式碼如下:

#define sss_pin 12

#define micro_sw_pin A0

int i = 0;

int x = 0;

float debounce_time = 1;

int start_time = 0;

int end_time = 0;

void setup() {

pinMode(micro_sw_pin, INPUT);

pinMode(sss_pin, INPUT);

Serial.begin(115200); //設定UART

delay(1000);

Serial.print(“atd0=()”); //清除畫面

while (Serial.read() != ‘E’) {} //等待燈板完成動作

Serial.print(“at2b=(0)”); //設定為覆蓋模式

while (Serial.read() != ‘E’) {} //傳送指令終止的字元

} //end of setup()

void loop() {

while (digitalRead(sss_pin)) {

Serial.print(“atef=(4)”); //設定數字顏色為0:Black、3:B、4:G、32:R

while (Serial.read() != ‘E’) {}

//Serial.print(“atd0=()”);

//while (Serial.read() != ‘E’) {}

x = analogRead(micro_sw_pin);

if (x < 10) {

//scoring();

//i=10;

++i;

Serial.print(“atd0=()”); //清除畫面

while (Serial.read() != ‘E’) {} //等待燈板完成動作

Serial.print(“at83=(1,3,”); //傳送部分指令

Serial.print(i); //傳送指令中變動的部分

Serial.write(‘)’); //傳送指令終止的字元

while (Serial.read() != ‘E’) {}

delay(500);

} //end of if

} //end of while

i=0;

} //end of loop()

void scoring() {

//i=11;

//int x = 0;

//x = analogRead(micro_sw_pin);

//Serial.println(x);

start_time = millis();

while (x <10) { //i=12; //Serial.print(“start_time=”); //Serial.println(start_time); if (x > 1000) {

//i=13;

end_time = millis();

//Serial.print(“end_time=”);

//Serial.println(end_time);

//break;

} //end of if

x = analogRead(micro_sw_pin);

} //end of while

//i = end_time – start_time;

if ((end_time – start_time) > debounce_time ) {

//i=14;

//Serial.print(“i=”);

//Serial.println(++i);

++i;

start_time = 0;

end_time = 0;

}

}

未來擴充

本專案已展示了一個可供跨領課程的教具與多方融入多元教學雛型。當然,後續還能有不少可擴充及延伸的可能性,例如:燈板字體大小的調整、增加的燈光與音效、重置機制的安排、將控制電路洗成 PCB 板、…。筆者亦期待本專案能起一拋磚引玉之功效,提供有志於此類教學者一個起點的參考。

 

 

分享到社群

vMaker編輯部

歡迎各界朋友投稿你的maker故事,不論是個人作品、創客觀點或是創客的經驗分享,我們都十分期待能聽到您的分享。 投稿請至:contact@vmaker.tw