# 2025 陽明交大電機營 Arduino組 ### 底下Exercise與Lab的程式碼都會被挖空,請根據題目要求將程式碼完成 --- # Exercise 0 前置作業 ## CH340與Arduino IDE https://drive.google.com/drive/folders/1xobgSl3XplSYGP4RiAqiI1rOKVg4xDGa?usp=drive_link ## 工具箱 1. Arduino UNO版(含連接線)*1 2. 麵包版*1 3. 公對公杜邦線*18 4. 公對母杜邦線*5 6. 色環電阻*4 7. LED*4 8. 可變電阻*1 9. 按鈕*1 10. 超音波感測器*1 11. 伺服馬達*1 12. 無源蜂鳴器*1 13. 搖桿*1 --- # Exercise 1 可變電阻與LED --- ![image](https://hackmd.io/_uploads/rk5hfvm1ee.png) # Exercise 2 按鈕 --- ![image](https://hackmd.io/_uploads/Syfr4zRJel.png) ## 程式碼 ```arduino= int pushbutton = 2; //設定按鈕的接腳 int buttonState = 1; //代表按鈕現在的狀態 int beforeState = 1; //代表按鈕的前一個狀態 int times = 0; //設定一個用於計次的整數 void setup() { Serial.begin(9600); //開始與電腦連接 ___1___ //設定按鈕並且給予上拉電阻 } void loop() { buttonState = digitalRead(pushbutton); //讀入此時的按鈕狀態 if(buttonState == 0 && beforeState == 1) { //當按鈕被按下時執行 ___2___ //讓程式暫停50毫秒後再繼續讀取 times++; //計次數加1 ___3___ //在視窗列印出計次數並換行 } beforeState = buttonState; //將此時的按鈕狀態存到前一刻的按鈕狀態 } ``` ## Problem 1 設定按鈕給予上拉電阻 ```arduino=5 void setup() { Serial.begin(9600); //開始與電腦連接 ___1___ //設定按鈕並且給予上拉電阻 } ``` <aside> :::success Problem 1 : 選項 >> 只有一個是對的喔! </aside> > A ) `pinmode(pushbutton,INPUT);` > > > B ) `pinmode(pushbutton,INPUT_PULLUP);` > > C ) `pinMode(pushbutton,Input_Pullup);` > > D ) `pinMode(pushbutton,INPUT_PULLUP);` > ## Problem 2 Debounce ```arduino=11 if(buttonState == 0 && beforeState == 1) { //當按鈕被按下時執行 ___2___ //讓程式暫停50毫秒後再繼續讀取 times++; //計次數加1 ___3___ //在視窗列印出計次數並換行 } ``` <aside> :::success Problem 2 : 選項 >> 只有一個是對的喔! </aside> > A ) `delay(50);` > > > B ) `Delay(50);` > > C ) `Debounce(times);` > > D ) `Debounce(buttonState);` > ## Problem 3 在序列埠監控視窗列印出計次數並換行 ```arduino=11 if(buttonState == 0 && beforeState == 1){ //當按鈕被按下時執行 ___2___ //讓程式暫停20毫秒後再繼續讀取 times++; //計次數加1 ___3___ //在視窗列印出計次數並換行 } ``` <aside> :::success Problem 3 : 選項 >> 只有一個是對的喔! </aside> > A ) `Serial.print(times);` > > > B ) `serial.print(times);` > > C ) `Serial.println("times");` > > D ) `Serial.println(times);` > # Exercise 3 超音波感測器 ![image](https://hackmd.io/_uploads/rk0x9DmJlg.png) --- ### 超音波感測器請這樣接。 ![image](https://hackmd.io/_uploads/Sk3c26IBex.png) ## 程式碼 ```arduino= int Trig=13; int Echo=12; double distance(); void setup() { Serial.begin(9600); //設定鮑率為9600 __1.1__ //將Trig腳位訂為輸出 __1.2__ //將Echo腳位訂為輸入 } void loop() { Serial.print("Distance : "); Serial.print(distance()); Serial.println("cm"); delay(2000); } double distance(){ digitalWrite(Trig,__2.1__); //高電位 delayMicroseconds(10); //持續10微秒 digitalWrite(Trig,__2.2__); //回到低電位 long duration = pulseIn(Echo,HIGH); return ___3___; //套公式 } ``` ## Problem 1 設定腳位的模式 ```arduino=5 void setup() { Serial.begin(9600); //設定鮑率為9600 __1.1__ //將Trig腳位訂為輸出 __1.2__ //將Echo腳位訂為輸入 } ``` <aside> :::success Problem 1 : 選項 >> 只有一個是對的喔! </aside> ``` __1.1__ / __1.2__ ``` > A ) `pinMode(Trig,OUTPUT);` / `pinMode(Echo,OUTPUT);` > > B ) `pinMode(Trig,INPUT);` / `pinMode(Echo,INPUT);` > > C ) `pinMode(Trig,OUTPUT);` / `pinMode(Echo,INPUT);` > > D ) `pinMode(Trig,INPUT);` / `pinMode(Echo,OUTPUT);` > ## Problem 2 發出超音波 ```arduino=19 digitalWrite(Trig,__2.1__); //高電位 delayMicroseconds(10); //持續10微秒 digitalWrite(Trig,__2.2__); //回到低電位 ``` <aside> :::success Problem 2 : 選項 >> 只有一個是對的喔! </aside> ``` __2.1__ / __2.2__ ``` > A ) `HIGH` / `LOW` > > > B ) `LOW` / `HIGH` > > C ) `INPUT` / `OUTPUT` > > D ) `OUTPUT` / `INPUT` > ## Problem 3 發出超音波 ```arduino=22 long duration = pulseIn(Echo,HIGH); return ___3___; //套公式 ``` <aside> :::success Problem 3 : 選項 >> 只有一個是對的喔! </aside> > A ) `duration * 0.0346` > > > B ) `duration * 346 / 2` > > C ) `duration * 0.0346 / 2` > > D ) `duration * 346` > # Exercise 4 伺服馬達 --- ![image 1](https://hackmd.io/_uploads/HkOxYwQyle.png) ## 程式碼 ```arduino= #include <Servo.h> Servo servo; int spin = 10; int angle = 0; void setup() { ___1___ //將Servo設定到腳位9 } void loop() { servo.write(angle); //把angle寫入servo中 angle += spin; if(___2___){ //判斷角度是否超出旋轉範圍 spin *= -1; //如果超過範圍就往反方向旋轉 } delay(500); } ``` ## Problem 1 設定伺服馬達的腳位 ```arduino=7 void setup() { ___1___ //將Servo設定到腳位9 } ``` <aside> :::success Problem 1 : 選項 >> 只有一個是對的喔! </aside> > A ) `servo.attach(9);` > > > B ) `servo.write(9);` > > C ) `pinMode(9,OUTPUT);` > > D ) `pinMode(9,INPUT);` > ## Problem 2 判斷旋轉角度的範圍 ```arduino=14 if(___2___){ //判斷角度是否超出旋轉範圍 spin *= -1; //如果超過範圍就往反方向旋轉 } ``` <aside> :::success Problem 2 : 選項 >> 只有一個是對的喔! </aside> > A ) `angle<=0` > > > B ) `angle>=180` > > C ) `angle<=0 && angle>=180` > > D ) `angle<=0 || angle>=180` > # Exercise 5 無源蜂鳴器 --- ![螢幕擷取畫面 2025-06-22 224415](https://hackmd.io/_uploads/rJv1ucrEle.png) ## 程式碼 ```arduino= int TRIG = 9; // 超音波模組的Trig腳位 int ECHO = 10; // 超音波模組的Echo腳位 int BUZZER = 5; // 無源蜂鳴器腳位 double distance(); void setup() { pinMode(TRIG, __1.1__); //將Trig腳位訂為輸出 pinMode(ECHO, __1.2__); //將Echo腳位訂為輸入 pinMode(BUZZER, __1.3__); Serial.begin(9600); // 開啟序列埠監視器 } void loop() { double d = distance(); /*Debug用 Serial.print("Distance : "); Serial.print(d); Serial.println("cm");*/ if (d > 20) { // 大於 20cm,不發出聲音 noTone(BUZZER); } else if (d > 10) { // 10-20 cm,1 秒 1000Hz,1 秒靜音 tone(BUZZER, __2.1__); delay(1000); __2.2__(BUZZER); delay(1000); } else { // 0-10 cm,0.5 秒 2000Hz,0.5 秒靜音 tone(BUZZER, __2.3__); delay(500); noTone(BUZZER); delay(500); } } double distance() { digitalWrite(TRIG,HIGH);//產生高電位脈衝 delayMicroseconds(10); //持續 10 µs digitalWrite(TRIG,LOW); long duration = pulseIn(ECHO,HIGH);//時間∆t return duration * 0.0346 / 2;//距離公式 } ``` ## Problem 1 設定蜂鳴器和超音波腳位 ```arduino=6 void setup() { pinMode(TRIG,__1.1__); //將Trig腳位訂為輸出 pinMode(ECHO,__1.2__); //將Echo腳位訂為輸入 pinMode(BUZZER,__1.3__); // 把蜂鳴器設為輸出 Serial.begin(9600); // 開啟序列埠監視器 } ``` :::success Problem 1 : 選項 >> 只有一個是對的喔! ::: ``` __1.1__ / __1.2__ / ___1.3___ ``` > A ) `INPUT` / `OUTPUT` / `INPUT` > > > B ) `OUTPUT` / `INPUT` / `OUTPUT` > > C ) `INPUT` / `OUTPUT` / `OUTPUT` > > D ) `OUTPUT` / `INPUT` / `INPUT` > ## Problem 2 讓蜂鳴器發出特定聲音 ```arduino=13 void loop() { double d = distance(); if (d > 20) { // 大於 20cm,不發出聲音 noTone(BUZZER); } else if (d > 10) { // 10-20 cm,1 秒 1000Hz,1 秒靜音 tone(BUZZER, __2.1__); delay(1000); __2.2__(BUZZER); delay(1000); } else { // 0-10 cm,0.5 秒 2000Hz,0.5 秒靜音 tone(BUZZER, __2.3__); delay(500); noTone(BUZZER); delay(500); } } ``` :::success Problem 2 : 選項 >> 只有一個是對的喔! ::: ``` __2.1__ / __2.2__ / __2.3__ ``` > A ) `1000` / `tone` / `2000` > > > B ) `2000` / `noTone` / `1000` > > C ) `1000` / `noTone` / `2000` > > D ) `2000` / `tone` / `500` > # Exercise 6 搖桿 --- ![螢幕擷取畫面 2025-06-15 204411](https://hackmd.io/_uploads/S1c8lH37ex.png) ![Arduino (9)](https://hackmd.io/_uploads/H1o2_3lHlx.jpg) ![Arduino (7)](https://hackmd.io/_uploads/B1vOdherxx.jpg) ## 程式碼 ```arduino= #include <Servo.h> int x = A0; // 搖桿 X 軸(控制伺服) int y = A1; // 搖桿 Y 軸(控制蜂鳴器) int SERVO = 9; // 伺服馬達接腳 int BUZZER = 6; // 蜂鳴器接腳 Servo servoMotor; void setup() { pinMode(x, INPUT); pinMode(y, INPUT); pinMode(BUZZER, OUTPUT); servoMotor.attach(SERVO); // 連接伺服馬達 //Serial.begin(9600); } void loop() { // 讀取搖桿數值(0~1023) int xValue = __1.1__; // 讀取搖桿x方向數值(0~1023) int yValue = __1.2__; // 讀取搖桿y方向數值(0~1023) /*Debug用 Serial.print("Xpos : "); Serial.println(xValue); Serial.print("Ypos : "); Serial.println(yValue);*/ // X 軸控制伺服馬達(對應到 0° ~ 180°) int servoAngle = __2.1__; servoMotor.write(servoAngle); // Y 軸控制蜂鳴器頻率(對應到 1000Hz ~ 1500Hz) int buzzerFreq = __2.2__; tone(BUZZER, buzzerFreq); } ``` ## Problem 1 讀取搖桿數值 ```arduino=17 int xValue = __1.1__; // 讀取搖桿x方向數值(0~1023) int yValue = __1.2__; // 讀取搖桿y方向數值(0~1023) ``` :::success Problem 1 : 選項 >> 只有一個是對的喔! ::: ``` __1.1__ / __1.2__ ``` > A ) `analogRead(x)` / `analogRead(y)` > > > B ) `analogread(x)` / `analogread(y)` > > C ) `digitalRead(x)` / `digitalRead(y)` > > D ) `digitalread(x)` / `digitalread(y)` > ## Problem 2 搖桿數值轉換 ```arduino=20 // X 軸控制伺服馬達(對應到 0° ~ 180°) int servoAngle = __2.1__; servoMotor.write(servoAngle); // Y 軸控制蜂鳴器頻率(對應到 1000Hz ~ 1500Hz) int buzzerFreq = __2.2__; tone(BUZZER, buzzerFreq); ``` :::success Problem 2 : 選項 >> 只有一個是對的喔! ::: ``` __2.1__ / __2.2__ ``` > A ) `map(xValue, 0, 180, 0, 1023)` / `map(yValue, 1000, 1500, 0, 1023)` > > > B ) `Map(xValue, 0, 180, 0, 1023)` / `Map(yValue, 1000, 1500, 0, 1023)` > > C ) `map(xValue, 0, 1023, 0, 180)` / `map(yValue, 0, 1023, 1000, 1500)` > > D ) `Map(xValue, 0, 1023, 0, 180)` / `Map(yValue, 0, 1023, 1000, 1500)` > --- # Lab1 平交道 --- ![螢幕擷取畫面 2025-07-01 085523](https://hackmd.io/_uploads/BkfpT2EBex.png) ## 程式碼 --- ```arduino= #include <Servo.h> // 引入伺服馬達函式庫 int trigPin = 9; // TRIG 腳位:超音波模組 int echoPin = 10; // ECHO 腳位:超音波模組 int servoPin = 6; // 伺服馬達腳位 int redLed = 3; // 紅色 LED int greenLed = 4; // 綠色 LED int buzzer = 5; // 蜂鳴器腳位 int button = 7; // 按鈕腳位 Servo servo; // 宣告 Servo 物件控制馬達 void setup() { Serial.__1__(9600); // 設定序列通訊鮑率為 9600 pinMode(trigPin, OUTPUT); // TRIG 設為輸出 pinMode(echoPin, INPUT); // ECHO 設為輸入 pinMode(redLed, OUTPUT); // 紅色 LED 設為輸出 pinMode(greenLed, OUTPUT); // 綠色 LED 設為輸出 pinMode(buzzer, OUTPUT); // 蜂鳴器設為輸出 pinMode(button, __2__); // 按鈕腳位設為輸入,使用內部上拉電阻 servo.__3__(servoPin); // 將伺服馬達接到指定腳位 servo.write(0); // 初始設為 0 度(柵欄打開) } void loop() { long duration; // 儲存超音波回波時間 float distance; // 計算距離(公分) int buttonState; buttonState = digitalRead(button); // 讀取按鈕狀態 /*debug用 Serial.print("距離為: "); Serial.println(distance); Serial.print(" 按鈕狀態: "); Serial.println(buttonState); */ if (__4__) { // 如果按鈕被按下 servo.write(0); // 馬達轉到開啟角度 digitalWrite(redLed, HIGH); // 紅燈亮 digitalWrite(greenLed, HIGH);// 綠燈亮 __5.1__(buzzer, 500); // 蜂鳴器發出聲音(150Hz) Serial.println("狀態:緊急按鈕按下,強制停止"); } else { digitalWrite(trigPin, __6.1__); // 送出超音波 delayMicroseconds(10); // 等 10 微秒 digitalWrite(trigPin, __6.2__); // 停止送出超音波 duration = pulseIn(echoPin, HIGH); // 偵測回音時間 distance = __7__ * 0.034 / 2; // 計算距離(cm) Serial.print("測得距離: "); Serial.print(distance); Serial.println(" cm"); __5.2__(buzzer); // 停止蜂鳴器 if (distance > 20) { delay(500); servo.write(0); // 開啟柵欄 digitalWrite(redLed, LOW); digitalWrite(greenLed, LOW); digitalWrite(buzzer, LOW); Serial.println("狀態:安全,柵欄開啟"); } else if (__8__) { // 如果距離在 10~20cm servo.write(90); // 關閉柵欄 digitalWrite(__9.1__, HIGH); // 紅燈亮 digitalWrite(__9.2__, LOW); // 綠燈關 tone(buzzer,100); // 蜂鳴器響 Serial.println("狀態:危險靠近,警示燈閃爍"); delay(500); digitalWrite(__9.3__, LOW); // 紅燈關 digitalWrite(__9.4__, HIGH); // 綠燈亮 noTone(buzzer); // 蜂鳴器停 delay(500); } else { servo.write(90); // 非常危險,完全關閉 digitalWrite(redLed, HIGH); digitalWrite(greenLed, LOW); tone(buzzer,125); Serial.println("狀態:非常危險,快速警示"); __10__; // 快速閃爍,每0.1秒閃爍一次 digitalWrite(redLed, LOW); digitalWrite(greenLed, HIGH); noTone(buzzer); __10__; // 快速閃爍,每0.1秒閃爍一次 } } } ``` ## Problem 1 設定序列通訊鮑率 ```arduino=13 void setup() { Serial.__1__(9600); // 設定序列通訊鮑率為 9600 pinMode(trigPin, OUTPUT); // TRIG 設為輸出 pinMode(echoPin, INPUT); // ECHO 設為輸入 pinMode(redLed, OUTPUT); // 紅色 LED 設為輸出 ``` :::success Problem 1 : 選項 >> 只有一個是對的喔! ::: > A ) `start` > > > B ) `begin` > > C ) `end` > > D ) `print` > ## Problem 2 設定上拉電阻 ```arduino=19 pinMode(buzzer, OUTPUT); // 蜂鳴器設為輸出 pinMode(button, __2__); // 按鈕腳位設為輸入,使用內部上拉電阻 ``` :::success Problem 2 : 選項 >> 只有一個是對的喔! ::: > A ) `INPUT` > > > B ) `OUTPUT` > > C ) `INPUT_PULLUP` > > D ) `OUTPUT_PULLUP` > ## Problem 3 連接伺服馬達 ```arduino=21 servo.__3__(servoPin); // 將伺服馬達接到指定腳位 servo.write(0); // 初始設為 0 度(柵欄打開) ``` :::success Problem 3 : 選項 >> 只有一個是對的喔! ::: > A ) `Write` > > > B ) `Attach` > > C ) `write` > > D ) `attach` > ## Problem 4 緊急按鈕觸發條件 ```arduino=31 if(__4__){ // 如果按鈕被按下 servo.write(0); // 馬達轉到開啟角度 digitalWrite(redLed, HIGH); // 紅燈亮 digitalWrite(greenLed, HIGH); // 綠燈亮 ``` :::success Problem 4 : 選項 >> 只有一個是對的喔! ::: > A ) `buttonSTATE == LOW` > > > B ) `buttonState == LOW` > > C ) `ButtonState == HIGH` > > D ) `buttonState == 1` > ## Problem 5 蜂鳴器發聲 ```arduino=34 digitalWrite(greenLed, HIGH);// 綠燈亮 __5.1__(buzzer, 500); // 蜂鳴器發出聲音(500Hz) Serial.println("狀態:緊急按鈕按下,強制停止"); } ``` ```arduino=46 Serial.print("測得距離: "); Serial.print(distance); Serial.println(" cm"); __5.2__(buzzer); // 蜂鳴器關閉 ``` :::success Problem 5 : 選項 >> 只有一個是對的喔! ::: ``` __5.1__ / __5.2__ ``` > A ) `tone` / `notone` > > > B ) `TONE` / `noTone` > > C ) `tone` / `noTone` > > D ) `TONE` / `noTone` > ## Problem 6 發出超音波 ```arduino=39 digitalWrite(trigPin, __6.1__); // 送出超音波 delayMicroseconds(10); // 等 10 微秒 digitalWrite(trigPin, __6.2__); // 停止送出超音波 ``` :::success Problem 6 : 選項 >> 只有一個是對的喔! ::: ``` __6.1__ / __6.2__ ``` > A ) `High` / `Low` > > > B ) `Low` / `High` > > C ) `LOW` / `HIGH` > > D ) `HIGH` / `LOW` > ## Problem 7 距離公式 ```arduino=43 duration = pulseIn(echoPin, HIGH); // 偵測回音時間 distance = __7__ * 0.034 / 2; // 計算距離(cm) ``` :::success Problem 7 : 選項 >> 只有一個是對的喔! ::: > A ) `duration` > > > B ) `DuRaTiOn` > > C ) `dUrAtIoN` > > D ) `DURATION` > ## Problem 8 中距離狀態條件 ```arduino=53 digitalWrite(greenLed, LOW); digitalWrite(buzzer, LOW); Serial.println("狀態:安全,柵欄開啟"); } else if (__8__) { // 如果距離在 10~20cm servo.write(90); // 關閉柵欄 ``` :::success Problem 8 : 選項 >> 只有一個是對的喔! ::: > A ) `distance <= 10` > > > B ) `distance < 10` > > C ) `distance > 10` > > D ) `distance > 100` > ## Problem 9 LED閃爍 ```arduino=58 servo.write(90); // 關閉柵欄 digitalWrite(__9.1__, HIGH); // 紅燈亮 digitalWrite(__9.2__, LOW); // 綠燈關 tone(buzzer, 100); // 蜂鳴器響 Serial.println("狀態:危險靠近,警示燈閃爍"); delay(500); digitalWrite(__9.3__, LOW); // 紅燈關 digitalWrite(__9.4__, HIGH); // 綠燈亮 noTone(buzzer); // 蜂鳴器停 delay(500); ``` :::success Problem 9 : 選項 >> 只有一個是對的喔! ::: ``` __9.1__ / __9.2__ / __9.3__ / __9.4__ ``` > A ) `redLed` / `redLed` / `greenLed` / `greenLed` > > > B ) `redLed` / `greenLed` / `redLed` / `greenLed` > > C ) `greenLed` / `greenLed` / `redLed` / `redLed` > > D ) `redLed` / `greenLed` / `greenLed`/ `redLed` > ## Problem 10 LED閃爍時間控制 ```arduino=70 else { servo.write(90); // 非常危險,完全關閉 digitalWrite(redLed, HIGH); digitalWrite(greenLed, LOW); tone(buzzer,125); Serial.println("狀態:非常危險,快速警示"); __10__; // 快速閃爍,每0.1秒閃爍一次 digitalWrite(redLed, LOW); digitalWrite(greenLed, HIGH); noTone(buzzer); __10__; // 快速閃爍,每0.1秒閃爍一次 } ``` --- :::success Problem 10 : 選項 >> 只有一個是對的喔! ::: > A ) `delay(100)` > > > B ) `delay(0.1)` > > C ) `Delay(100)` > > D ) `Delay(0.1)` > # Lab2 打地鼠 ![螢幕擷取畫面 2025-06-29 224044](https://hackmd.io/_uploads/ByjzZA04xl.png) ![Arduino (6)](https://hackmd.io/_uploads/r1-Xb0R4lg.jpg) ![image](https://hackmd.io/_uploads/HkRYFMWHgx.png) ## 程式碼 ```arduino= // 定義四個 LED 的腳位 int UpLed = 2; // 上方LED腳位 int RightLed = 3; // 右方LED腳位 int DownLed = 4; // 下方LED腳位 int LeftLed = 5; // 左方LED腳位 // 定義搖桿的類比輸入腳位 int joyX = A0; // 搖桿 X 軸 int joyY = A1; // 搖桿 Y 軸 int joySw = 7; // 搖桿按鈕 // 蜂鳴器腳位 int buzzer = 6; // LED 腳位陣列 int ledPins[] = {UpLed, RightLed, LeftLed, DownLed}; int activeLED = -1; // 記錄當前點亮的 LED int lastLED = -1; // 記錄上一顆點亮的 LED int validCount = 0; // 記錄正確關閉 LED 次數 int penaltyCount = 0; // 記錄錯誤扣分 int r = 2; // 得分倍率 bool gameStarted = false; // 遊戲是否開始 unsigned long startTime = 0; // 記錄遊戲開始時間 int gameDuration = 15000; // 遊戲時間 15 秒 unsigned long lastButtonPress = 0; // 記錄上次按下按鈕的時間 unsigned long debounceDelay = 200; // Debounce 延遲 200 毫秒 unsigned long lastLedActionTime = 0; // 記錄上次關閉 LED 的時間 unsigned long ledCooldown = 200; // LED 冷卻時間 200 毫秒,避免過快連續操作 //函數宣告 void playStartCountdown(); void lightRandomLED(); void playEndTone(); void turnOffAllLEDs(); void checkJoystick(); void setup() { __1__(9600); // 設定序列埠,用於輸出訊息 // 設定 LED 腳位為輸出 pinMode(UpLed, OUTPUT); pinMode(LeftLed, OUTPUT); pinMode(RightLed, OUTPUT); pinMode(DownLed, OUTPUT); pinMode(joySw, __2__ ); // 設定搖桿按鈕為輸入 pinMode(buzzer, OUTPUT); // 設定蜂鳴器腳位為輸出 Serial.println("按下 Joystick 中間鍵開始遊戲"); } void loop() { if (!gameStarted) { // 如果遊戲尚未開始 // 等待玩家按下搖桿按鈕啟動遊戲 if ( ( __3__ ) && ( __4__ ) ) { //當(按鈕按下時)且(Debounce) delay(1000); lastButtonPress = millis(); // 記錄按下時間 gameStarted = true; // 設定遊戲開始 validCount = 0; penaltyCount = 0; startTime = millis(); // 記錄遊戲開始時間 playStartCountdown(); Serial.println("遊戲開始!15 秒內關掉最多 LED"); lightRandomLED(); // 隨機點亮一顆 LED } } else { // 檢查遊戲是否已達時間限制 if ( __5__ ) { Serial.print("遊戲結束!你關掉了 "); Serial.print(validCount); Serial.print(" 顆 LED,錯誤扣分: "); Serial.println(penaltyCount); Serial.print("<總得分>:"); Serial.println(validCount * r + penaltyCount); // 計算總得分 playEndTone(); gameStarted = false; // 遊戲結束 turnOffAllLEDs(); // 關閉所有 LED Serial.println("按下 Joystick 中間鍵重新開始"); } else { checkJoystick(); // 檢查搖桿輸入 } } } void checkJoystick() { int xVal = analogRead(joyX); // 讀取搖桿 X 軸數值 int yVal = analogRead(joyY); // 讀取搖桿 Y 軸數值 /*debug用 Serial.print("Xpos : "); Serial.println(xVal); Serial.print("Ypos : "); Serial.println(yVal);*/ // 確保 LED 點亮,且符合冷卻時間 if ( __6__ ) { bool correctMove = false; // 是否為正確的移動 bool moved = false; // 是否有移動搖桿 // 判斷是否有移動搖桿 if ( __7.1__ || __7.2__ || __7.3__ || __7.4__ ) { moved = true; } // 檢查移動方向是否與 LED 位置匹配 if( __8__ ) { /* 如果點亮的是 UpLed,則應該向上推 如果點亮的是 RightLed,則應該向右推 如果點亮的是 LeftLed,則應該向左推 如果點亮的是 DownLed,則應該向下推 */ correctMove = true; } if (moved) { // 如果有移動搖桿 if (correctMove) { // 如果移動方向正確 turnOffAllLEDs(); // 關閉所有 LED delay(100); validCount++; // 增加正確關閉計數 Serial.print("LED 關閉數量: "); Serial.println(validCount); lightRandomLED(); // 再次隨機點亮 LED } else { // 如果移動方向錯誤 penaltyCount -= 5; // 錯誤扣 5 分 Serial.print("錯誤操作!目前扣分: "); Serial.println(penaltyCount); } lastLedActionTime = millis(); // 記錄這次操作的時間 } } } // 隨機點亮一顆 LED void lightRandomLED() { activeLED = random(0, 4); // 產生 0~3 之間的隨機數,選擇要點亮的 LED digitalWrite( __9.1__, __9.2__ ); } // 關閉所有 LED void turnOffAllLEDs() { for (int i = 0; i < 4; i++) { __10__ ; } } // 🎵 遊戲開始音效 void playStartCountdown() { for (int i = 3; i > 0; i--) { __11.1__ __11.2__ // 發出 1000 Hz 音調 300ms noTone(buzzer); delay(1000); // 等待 1 秒 } __11.3__ __11.4__ // 發出 1500 Hz 音調 500ms noTone(buzzer); delay(500); } // 🎵 遊戲結束音效 void playEndTone() { tone(buzzer, 500); delay(300); noTone(buzzer); delay(400); tone(buzzer, 300); delay(500); noTone(buzzer); } ``` ### Problem 1 設定序列埠,用於輸出訊息 ```arduino=34 void setup() { __1__(9600); // 設定序列埠,用於輸出訊息 } ``` :::success Problem 1 : 選項 >> 只有一個是對的喔! ::: > A ) `Serial.write` > > > B ) `Serial.print` > > C ) `Serial.begin` > > D ) `Serial.end` > --- ### Problem 2 設定搖桿按鈕為輸入 ```arduino=41 pinMode(joySw, __2__ ); // 請根據你拿到的搖桿選擇正確答案。 ``` ### Hint : **黑色搖桿需要**給予上拉電阻(否則電位會浮動)。 **紅色搖桿不需**給予上拉電阻,只須設定該腳位為輸入。 :::success Problem 2 : 請根據你拿到的搖桿選擇正確答案。 ::: **黑色搖桿:**`INPUT_PULLUP` **紅色搖桿:**`INPUT` ### Problem 3 當按鈕按下時 ```arduino=49 if ( ( __3__ ) && ( __4__ ) ) { //當(按鈕按下時)且(Debounce) //code } ``` ### Hint : **黑色搖桿**有被給予上拉電阻,因此當按鈕按下時,使用digitalRead函式會讀取到低電位。 **紅色搖桿**預設連接到GND,因此當按鈕按下時,使用digitalRead函式會讀取到高電位。 :::success Problem 3 : 選項 >> 請根據你拿到的搖桿選擇正確答案。 ::: **黑色搖桿:**`digitalRead(joySw) == LOW` **紅色搖桿:**`digitalRead(joySw) == HIGH` --- ### Problem 4 Debounce ```arduino=49 if ( ( __3__ ) && ( __4__ ) ) { //當(按鈕按下時)且(Debounce) //code } ``` :::success Problem 4 : 選項 >> 只有一個是對的喔! ::: > A ) `millis() - lastButtonPress < debounceDelay` > > > B ) `millis() - lastButtonPress > debounceDelay` > > C ) `lastButtonPress < debounceDelay` > > D ) `lastButtonPress > debounceDelay` > ### Problem 5 檢查遊戲是否已達時間限制 ```arduino=62 // 檢查遊戲是否已達時間限制 if ( __5__ ) { //code } ``` :::success Problem 5 : 選項 >> 只有一個是對的喔! ::: > > A ) `startTime <= gameDuration` > > B ) `startTime > gameDuration` > > C ) `millis() - startTime < gameDuration` > > D ) `millis() - startTime >= gameDuration` > --- ### Problem 6 確保 LED 點亮,且符合冷卻時間 ```arduino=91 // 確保 LED 點亮,且符合冷卻時間 if ( __6__ ) { //code } ``` :::success Problem 6 : 選項 >> 只有一個是對的喔! ::: > A ) `activeLED == -1 && (millis() - lastLedActionTime) > ledCooldown` > > > B ) `activeLED != -1 && (millis() - lastLedActionTime) > ledCooldown` > > C ) `activeLED == -1 && lastLedActionTime > ledCooldown` > > D ) `activeLED != -1 && lastLedActionTime > ledCooldown` > ### Problem 7 判斷是否有移動搖桿 ```arduino=96 // 判斷是否有移動搖桿 if ( __7.1__ || __7.2__ || __7.3__ || __7.4__ ) { moved = true; } ``` :::success Problem 7 : 選項 >> 只有一個是對的喔! ::: ``` __7.1__ || __7.2__ || __7.3__ || __7.4__ ``` > A ) `yVal < 200 || yVal > 800 || xVal < 200 || xVal > 800` > > > B ) `yVal < 200 || yVal < 800 || xVal > 200 || xVal > 800` > > C ) `yVal > 200 || yVal < 800 || xVal > 200 || xVal < 800` > > D ) `yVal > 200 || yVal > 800 || xVal < 200 || xVal < 800` > --- ### Problem 8 檢查移動方向是否與 LED 位置匹配 ```arduino=101 // 檢查移動方向是否與 LED 位置匹配 if( __8__ ) /* 如果點亮的是 UpLed,則應該向上推 如果點亮的是 RightLed,則應該向右推 如果點亮的是 LeftLed,則應該向左推 如果點亮的是 DownLed,則應該向下推 */ correctMove = true; } ``` ### Hint : ![image](https://hackmd.io/_uploads/HkRYFMWHgx.png) **黑色搖桿:** 1. 往上推:`xVal > 800` 2. 往右推:`yVal > 800` 3. 往左推:`yVal < 200` 4. 往下推:`xVal < 200` **紅色搖桿:** 1. 往上推:`yVal < 200` 2. 往右推:`xVal > 800` 3. 往左推:`xVal < 200` 4. 往下推:`yVal > 800` :::success Problem 8 : 選項 >> 請根據你拿到的搖桿選擇正確答案。 ::: **黑色搖桿:** `( activeLED == 0 && xVal > 800 ) || ( activeLED == 1 && yVal > 800 ) || ( activeLED == 2 && yVal < 200 ) || ( activeLED == 3 && xVal < 200 )` **紅色搖桿:** `( activeLED == 0 && yVal < 200 ) || ( activeLED == 1 && xVal > 800 ) || ( activeLED == 2 && xVal < 200 ) || ( activeLED == 3 && yVal > 800 )` ### Problem 9 隨機點亮一顆 LED ```arduino=129 // 隨機點亮一顆 LED void lightRandomLED() { activeLED = random(0, 4); // 產生 0~3 的隨機數 digitalWrite( __9.1__, __9.2__ ); } ``` :::success Problem 9 : 選項 >> 只有一個是對的喔! ::: ``` __9.1__ / __9.2__ ``` > A ) `ledPins[activeLED] / HIGH` > > > B ) `ledPins[activeLED] / LOW` > > C ) `ledPins[millis()] / HIGH` > > D ) `ledPins[gameDuration] / LOW` > --- ### Problem 10 關閉所有 LED ```arduino=135 // 關閉所有 LED void turnOffAllLEDs() { for (int i = 0; i < 4; i++) { __10__; } ``` :::success Problem 10 : 選項 >> 只有一個是對的喔! ::: > A ) `digitalWrite(ledPins[j], LOW)` > > > B ) `digitalWrite(ledPins[j], HIGH)` > > C ) `digitalWrite(ledPins[i], LOW)` > > D ) `digitalWrite(ledPins[i], HIGH)` > ### Problem 11 發出 1000 Hz 音調 300ms / 發出 1500 Hz 音調 500ms ```arduino=142 // 🎵 遊戲開始音效 void playStartCountdown() { for (int i = 3; i > 0; i--) { __11.1__ __11.2__ // 發出 1000 Hz 音調 300ms noTone(buzzer); delay(1000); // 等待 1 秒 } __11.3__ __11.4__ // 發出 1500 Hz 音調 500ms noTone(buzzer); delay(500); } ``` :::success Problem 11 : 選項 >> 只有一個是對的喔! ::: ``` __11.1__ / __11.2__ / __11.3__ / __11.4__ ``` > A ) `delay(300); / tone(buzzer, 1000); / tone(buzzer, 1500); / delay(500);` > > > B ) `delay(300); / tone(buzzer, 1000); / delay(500); / tone(buzzer, 1500);` > > C ) `tone(buzzer, 1000); / delay(300); / tone(buzzer, 1500); / delay(500);` > > D ) `tone(buzzer, 1000); / delay(300); / delay(500); / tone(buzzer, 1500);` >