🎵 音樂與聲效控制

學會控制蜂鳴器發聲,製作自己的Arduino音樂播放器!

🔌 本功課所需杜邦線

蜂鳴器與麵包板接線請依下表準備(直接對照右側「收納位置」欄到收納盒取線即可)。上方為數量表,下方為接線圖

顏色長度規格數量收納位置
10 cm公公1C1
15 cm公公1C1
功課三音樂按鈕:電路接線圖

圖:功課三(音樂按鈕/蜂鳴器)接線圖

🎯 挑戰任務

製作一個結合數碼管倒數、RGB燈光和蜂鳴器音效的完整專案:

按下按鈕 → 蜂鳴器響一秒 → 開始倒數 → 燈光變化 → 完成!

🤖

與ChatGPT協作

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

我想用Arduino製作一個結合聲音、燈光和數字顯示的倒數計時器。 功能需求: 1. 按下按鈕時,蜂鳴器發出1秒的提示音(1000Hz) 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 - 蜂鳴器接在接腳11 請幫我寫Arduino程式碼,並加上詳細註解。

💡 提問技巧

  • 詢問tone()和noTone()函數的使用方法
  • 了解如何產生不同頻率的音調
  • 學習如何整合多個元件同時運作
  • 如果想播放旋律,可以請ChatGPT教你音階頻率

📝 程式碼詳細解說

讓我們一步步了解這個整合專案是怎麼運作的!

📚 第一部分:引入函式庫

延續上一個專案,我們需要TM1637數碼管函式庫

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

🎯 第二部分:腳位定義

這次我們有更多元件了!包括按鈕、RGB燈、數碼管和蜂鳴器

// --- 腳位定義 --- 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 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(buzzerPin, OUTPUT); // 🔊 蜂鳴器設為輸出 display.setBrightness(7); // 數碼管亮度0~7 display.showNumberDec(0); allOff(); // 關閉所有燈 Serial.begin(9600); Serial.println("準備好了!按下按鈕開始倒數~"); }

🔄 第五部分:loop 主要迴圈

檢查按鈕,當按下時先讓蜂鳴器響一秒,然後開始倒數

void loop() { int buttonState = digitalRead(buttonPin); // 偵測按下(從HIGH變LOW) if (buttonState == LOW && lastButtonState == HIGH) { if (!counting) { // 如果沒有在倒數中 counting = true; counter = 9; // 🔊 蜂鳴器響一秒(提示音) tone(buzzerPin, 1000); // 發出1000Hz音調 delay(1000); // 等待1秒 noTone(buzzerPin); // 停止聲音 Serial.println("開始倒數!"); startCountdown(); // 開始倒數 } } lastButtonState = buttonState; }

🔔 什麼是tone()和noTone()?

🎵 tone() 函數:讓蜂鳴器發出聲音

  • tone(接腳, 頻率) - 持續發出聲音直到呼叫 noTone()
  • tone(接腳, 頻率, 時間) - 發出聲音指定的毫秒數後自動停止
  • 頻率單位是 Hz(赫茲),數字越大音調越高

🔇 noTone() 函數:停止發聲

  • noTone(接腳) - 停止指定接腳的聲音

💡 小知識:
人類能聽到的聲音範圍大約是 20Hz ~ 20,000Hz。程式中的 1000Hz 是一個中等音調,聽起來像「嗶」的一聲!

⏱️ 第六部分:倒數函式

執行倒數,同時控制數碼管顯示和燈光顏色

// --- 倒數計時 --- 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 if (i >= 0) { setColor(0, 1, 0); // 3,2,1,0 → 綠燈 } delay(1000); // 等待1秒 } // 倒數結束:全關 allOff(); display.showNumberDec(0); Serial.println("倒數結束!"); counting = false; }

💡 第七部分:輔助函式

控制燈光的函式,讓程式更簡潔

// --- 控制燈光 --- 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. 🎮 按下按鈕:老師吹哨子(蜂鳴器響1秒)表示準備開始
  2. 🔢 數碼管顯示:就像計時器顯示秒數
  3. 🚦 燈光變化
    • 藍燈(9~7):還有很多時間,慢慢來
    • 紅燈(6~4):要加快速度囉!
    • 綠燈(3~0):最後倒數,衝刺!
  4. ⏱️ 每秒倒數一次:delay(1000) 讓每個數字停留1秒
  5. 🏁 倒數結束:所有東西都關閉,回到初始狀態

💡 為什麼要先讓蜂鳴器響?
就像比賽前的預備音,告訴使用者「我準備好要開始倒數了!」這是一種友善的提示設計。

🎵 想要不同的音調?
可以改變 tone() 的頻率參數:

  • 低音:200~500 Hz
  • 中音:500~2000 Hz
  • 高音:2000~5000 Hz

📋 完整程式碼

點擊展開完整程式碼
#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 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(buzzerPin, OUTPUT); display.setBrightness(7); // 數碼管亮度0~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; // 🔊 蜂鳴器響一秒 tone(buzzerPin, 1000); // 發出1000Hz音調 delay(1000); noTone(buzzerPin); // 停止聲音 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 if (i >= 0) { setColor(0, 1, 0); // 綠燈 } delay(1000); } // 倒數結束:全關 allOff(); display.showNumberDec(0); Serial.println("倒數結束!"); counting = false; } // --- 控制燈光 --- 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); }

🎉 完成挑戰後

恭喜你完成了整合聲光效果的完整專案!現在你學會了: