⚡ PWM與馬達驅動

學會控制震動馬達,掌握PWM調速和馬達驅動電路技術!

🔌 本功課所需杜邦線

整合數碼管、RGB、蜂鳴器與震動馬達時線材較多,請依下表備齊(含公公與公母;直接對照右側「收納位置」欄到收納盒取線即可)。上方為數量表,下方為接線圖

顏色長度規格數量收納位置
15 cm公公1C1
10 cm公公1C1
10 cm公公1C1
30 cm公公1C3
30 cm公公1C3
30 cm公母1C2
30 cm公母1C2
功課四震動馬達:電路接線圖

圖:功課四(震動馬達整合專案)接線圖

🎯 最終挑戰任務

製作一個整合所有元件的完整系統!結合數碼管、RGB燈、蜂鳴器和震動馬達:

按下按鈕 → 蜂鳴器+震動馬達響1秒 → 開始倒數 → 燈光變化 → 完成!

🤖

與ChatGPT協作

你可以試著問ChatGPT這些問題來獲得幫助和完整程式碼:

我想用Arduino製作一個整合多個元件的倒數計時系統。 功能需求: 1. 按下按鈕時,蜂鳴器和震動馬達同時運作1秒 2. 提示音結束後開始從9倒數到0 3. 倒數時數碼管顯示數字 4. 根據倒數數字顯示不同顏色: - 9~7:藍燈 - 6~4:紅燈 - 3~0:綠燈 5. 倒數結束後全部關閉 硬體接線: - 按鈕接在接腳2 - 紅色LED接在接腳3 - 綠色LED接在接腳4 - 藍色LED接在接腳5 - TM1637的DIO接在接腳6 - TM1637的CLK接在接腳7 - 震動馬達接在接腳9 - 蜂鳴器接在接腳11 請幫我寫Arduino程式碼,並加上詳細註解。

💡 提問技巧

  • 說明你要整合哪些元件
  • 描述清楚每個元件的功能和時機
  • 詢問如何控制震動馬達(digitalWrite vs analogWrite)
  • 如果有疑問,可以請ChatGPT分別解釋每個部分

📝 程式碼詳細解說

讓我們一步步了解這個完整的整合專案!

📚 第一部分:引入函式庫

繼續使用TM1637數碼管函式庫

#include <TM1637Display.h> // 數碼管控制函式庫

🎯 第二部分:腳位定義

這是最完整的專案!我們用到了所有學過的元件

// --- 腳位定義 --- const int buttonPin = 2; // 按鈕接在2號接腳 const int redPin = 3; // 紅燈接在3號接腳 const int greenPin = 4; // 綠燈接在4號接腳 const int bluePin = 5; // 藍燈接在5號接腳 const int DIO = 6; // 數碼管資料線 const int CLK = 7; // 數碼管時鐘線 const int motorPin = 9; // 🔄 震動馬達接在9號接腳 const int buzzerPin = 11; // 🔔 蜂鳴器接在11號接腳

🎨 第三部分:建立物件和變數

建立數碼管控制器和狀態變數

// --- 數碼管物件 --- TM1637Display display(CLK, DIO); // --- 狀態變數 --- int lastButtonState = HIGH; // 上一次按鈕狀態 bool counting = false; // 是否正在倒數 int counter = 9; // 倒數從9開始

⚙️ 第四部分:setup 開機設定

設定所有接腳,這次多了震動馬達!

void setup() { pinMode(buttonPin, INPUT_PULLUP); // 按鈕設為輸入 pinMode(redPin, OUTPUT); // 紅燈設為輸出 pinMode(greenPin, OUTPUT); // 綠燈設為輸出 pinMode(bluePin, OUTPUT); // 藍燈設為輸出 pinMode(motorPin, OUTPUT); // 🔄 震動馬達設為輸出 pinMode(buzzerPin, OUTPUT); // 🔔 蜂鳴器設為輸出 display.setBrightness(7); display.showNumberDec(0); allOff(); Serial.begin(9600); Serial.println("系統準備好了~ 按下按鈕開始倒數!"); }

🔄 第五部分:loop 主要迴圈

按下按鈕時,蜂鳴器和震動馬達會同時運作1秒!

void loop() { int buttonState = digitalRead(buttonPin); // 偵測按下事件(HIGH → LOW) if (buttonState == LOW && lastButtonState == HIGH) { if (!counting) { counting = true; counter = 9; // 🔊🔄 蜂鳴器與震動馬達同步運作 1 秒 tone(buzzerPin, 1000); // 蜂鳴器發出1000Hz音調 digitalWrite(motorPin, HIGH); // 震動馬達開始震動 delay(1000); // 等待1秒 noTone(buzzerPin); // 停止蜂鳴器 digitalWrite(motorPin, LOW); // 停止震動馬達 Serial.println("開始倒數!"); startCountdown(); } } lastButtonState = buttonState; }

🔄 什麼是震動馬達?

⚡ 震動馬達的原理

震動馬達就是一個小型馬達,軸上裝了一個偏心的重物。當馬達轉動時,這個偏心重物會造成不平衡,產生震動效果!

💡 手機的震動就是這樣來的!

  • digitalWrite(motorPin, HIGH) - 打開馬達,開始震動
  • digitalWrite(motorPin, LOW) - 關閉馬達,停止震動
  • 也可以用 analogWrite(motorPin, 速度) 控制震動強度(0~255)

🎮 應用場景:

  • 遊戲手把的震動回饋
  • 手機來電震動
  • 提醒裝置(例如手環)
  • 觸覺反饋系統

⏱️ 第六部分:倒數函式

執行倒數,控制數碼管和燈光

// --- 倒數函式 --- void startCountdown() { for (int i = counter; i >= 0; i--) { display.showNumberDec(i, false); // 顯示數字 if (i > 6) { setColor(0, 0, 1); // 9,8,7 → 藍燈 } else if (i > 3) { setColor(1, 0, 0); // 6,5,4 → 紅燈 } else { setColor(0, 1, 0); // 3,2,1,0 → 綠燈 } delay(1000); } // 倒數結束 allOff(); display.showNumberDec(0); Serial.println("倒數結束!"); counting = false; }

💡 第七部分:輔助函式

控制RGB燈光的函式

// --- 控制RGB燈 --- void setColor(int r, int g, int b) { digitalWrite(redPin, r); digitalWrite(greenPin, g); digitalWrite(bluePin, b); } // --- 關燈 --- void allOff() { digitalWrite(redPin, LOW); digitalWrite(greenPin, LOW); digitalWrite(bluePin, LOW); }

🧠 完整系統運作流程

想像你在體驗一個完整的計時系統:

  1. 🎮 按下按鈕:系統啟動!
  2. 🔔🔄 蜂鳴器+震動馬達:雙重提示音,告訴你「我準備好了!」(1秒)
  3. 🔢 數碼管倒數:從9倒數到0,每秒顯示一個數字
  4. 🚦 燈光變化
    • 藍燈(9~7):冷靜的開始
    • 紅燈(6~4):注意!時間過半
    • 綠燈(3~0):最後衝刺
  5. 🏁 倒數結束:所有東西關閉,系統回到待命狀態

💡 為什麼要同時用蜂鳴器和震動馬達?
這叫做「多感官反饋」!聲音+震動可以讓使用者更清楚地感受到系統的狀態變化,就像手機來訊息時會震動+響鈴一樣!

🎯 這個專案整合了你學過的所有技能:

  • ✅ 按鈕輸入控制
  • ✅ RGB LED 燈光效果
  • ✅ TM1637 數碼管顯示
  • ✅ tone() 蜂鳴器音效
  • ✅ digitalWrite() 馬達控制
  • ✅ 狀態機邏輯設計
  • ✅ 多元件協同運作

📋 完整程式碼

點擊展開完整程式碼
#include <TM1637Display.h> // --- 腳位定義 --- const int buttonPin = 2; const int redPin = 3; const int greenPin = 4; const int bluePin = 5; const int DIO = 6; const int CLK = 7; const int motorPin = 9; const int buzzerPin = 11; // --- 數碼管物件 --- TM1637Display display(CLK, DIO); // --- 狀態變數 --- int lastButtonState = HIGH; bool counting = false; int counter = 9; void setup() { pinMode(buttonPin, INPUT_PULLUP); pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); pinMode(motorPin, OUTPUT); pinMode(buzzerPin, OUTPUT); display.setBrightness(7); display.showNumberDec(0); allOff(); Serial.begin(9600); Serial.println("系統準備好了~ 按下按鈕開始倒數!"); } void loop() { int buttonState = digitalRead(buttonPin); // 偵測按下事件(HIGH → LOW) if (buttonState == LOW && lastButtonState == HIGH) { if (!counting) { counting = true; counter = 9; // 🔊🔄 蜂鳴器與震動馬達同步運作 1 秒 tone(buzzerPin, 1000); digitalWrite(motorPin, HIGH); delay(1000); noTone(buzzerPin); digitalWrite(motorPin, LOW); Serial.println("開始倒數!"); startCountdown(); } } lastButtonState = buttonState; } // --- 倒數函式 --- void startCountdown() { for (int i = counter; i >= 0; i--) { display.showNumberDec(i, false); if (i > 6) { setColor(0, 0, 1); // 藍燈 } else if (i > 3) { setColor(1, 0, 0); // 紅燈 } else { setColor(0, 1, 0); // 綠燈 } delay(1000); } // 倒數結束 allOff(); display.showNumberDec(0); Serial.println("倒數結束!"); counting = false; } // --- 控制RGB燈 --- void setColor(int r, int g, int b) { digitalWrite(redPin, r); digitalWrite(greenPin, g); digitalWrite(bluePin, b); } // --- 關燈 --- void allOff() { digitalWrite(redPin, LOW); digitalWrite(greenPin, LOW); digitalWrite(bluePin, LOW); }

🎉 完成功課四:震動馬達整合專案!

恭喜你完成整合多元件的專案!現在你學會了:

🎓 你已經完成的學習路程:

🚀 下一步:請繼續挑戰 功課五:電流急急棒,結合感測、計時與警報的遊戲式專案!