📝 程式碼詳細解說
讓我們一步步了解這個整合專案是怎麼運作的!
📚 第一部分:引入函式庫
延續上一個專案,我們需要TM1637數碼管函式庫
#include <TM1637Display.h>
🎯 第二部分:腳位定義
這次我們有更多元件了!包括按鈕、RGB燈、數碼管和蜂鳴器
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;
⚙️ 第四部分:setup 開機設定
設定所有接腳的模式,初始化數碼管和燈光
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
display.setBrightness(7);
display.showNumberDec(0);
allOff();
Serial.begin(9600);
Serial.println("準備好了!按下按鈕開始倒數~");
}
🔄 第五部分:loop 主要迴圈
檢查按鈕,當按下時先讓蜂鳴器響一秒,然後開始倒數
void loop() {
int buttonState = digitalRead(buttonPin);
if (buttonState == LOW && lastButtonState == HIGH) {
if (!counting) {
counting = true;
counter = 9;
tone(buzzerPin, 1000);
delay(1000);
noTone(buzzerPin);
Serial.println("開始倒數!");
startCountdown();
}
}
lastButtonState = buttonState;
}
🔔 什麼是tone()和noTone()?
🎵 tone() 函數:讓蜂鳴器發出聲音
tone(接腳, 頻率) - 持續發出聲音直到呼叫 noTone()
tone(接腳, 頻率, 時間) - 發出聲音指定的毫秒數後自動停止
- 頻率單位是 Hz(赫茲),數字越大音調越高
🔇 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);
} 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);
}
🧠 程式運作流程(完整故事)
想像你在體育課倒數計時:
- 🎮 按下按鈕:老師吹哨子(蜂鳴器響1秒)表示準備開始
- 🔢 數碼管顯示:就像計時器顯示秒數
- 🚦 燈光變化:
- 藍燈(9~7):還有很多時間,慢慢來
- 紅燈(6~4):要加快速度囉!
- 綠燈(3~0):最後倒數,衝刺!
- ⏱️ 每秒倒數一次:delay(1000) 讓每個數字停留1秒
- 🏁 倒數結束:所有東西都關閉,回到初始狀態
💡 為什麼要先讓蜂鳴器響?
就像比賽前的預備音,告訴使用者「我準備好要開始倒數了!」這是一種友善的提示設計。
🎵 想要不同的音調?
可以改變 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);
display.showNumberDec(0);
allOff();
Serial.begin(9600);
Serial.println("準備好了!按下按鈕開始倒數~");
}
void loop() {
int buttonState = digitalRead(buttonPin);
if (buttonState == LOW && lastButtonState == HIGH) {
if (!counting) {
counting = true;
counter = 9;
tone(buzzerPin, 1000);
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);
}