
這是一個適合 Arduino 初學者的第一個電子實作專案。使用 Arduino Uno R3、8 顆 LED、麵包板及公對公杜邦線,學習如何控制多顆 LED 依序亮起、熄滅,製作出跑馬燈、流水燈及左右來回閃爍等顯示效果。
/*
Arduino UNO R3
8 LED 跑馬燈 + 加速/減速按鍵
LED:
LED1 -> D2
LED2 -> D3
LED3 -> D4
LED4 -> D5
LED5 -> D6
LED6 -> D7
LED7 -> D8
LED8 -> D9
按鍵:
加速 -> D10 -> 按鍵 -> GND
減速 -> D11 -> 按鍵 -> GND
動作流程:
1. 全亮 1 秒
2. 全滅 1 秒
3. 重複 5 次
4. 跑馬燈 LED1 -> LED8 -> LED1
5. 來回共 5 次
6. 回到全亮/全滅
7. 永久循環
速度:
預設 1000 ms
每按一次改變 100 ms
最快 100 ms
最慢 3000 ms
*/
// =========================
// LED 接腳
// =========================
const byte ledPins[8] = {
2, 3, 4, 5, 6, 7, 8, 9
};
// =========================
// 按鍵接腳
// =========================
const byte SPEED_UP_BUTTON = 10;
const byte SPEED_DOWN_BUTTON = 11;
// =========================
// 速度設定
// =========================
unsigned long ledDelay = 1000; // 預設 1 秒
const unsigned long MIN_DELAY = 100; // 最快 0.1 秒
const unsigned long MAX_DELAY = 3000; // 最慢 3 秒
const unsigned long STEP_DELAY = 100; // 每次調整 0.1 秒
// 按鍵前一次狀態
bool lastSpeedUpState = HIGH;
bool lastSpeedDownState = HIGH;
// ======================================================
// 初始化
// ======================================================
void setup()
{
Serial.begin(9600);
// LED 設成輸出
for (byte i = 0; i < 8; i++)
{
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], LOW);
}
// 按鍵使用內部上拉
pinMode(SPEED_UP_BUTTON, INPUT_PULLUP);
pinMode(SPEED_DOWN_BUTTON, INPUT_PULLUP);
Serial.println("8 LED Running Light");
Serial.println("Default speed = 1000 ms");
}
// ======================================================
// 主程式
// ======================================================
void loop()
{
// --------------------------------
// 第一階段:
// 全亮、全滅,共 5 次
// --------------------------------
for (byte count = 0; count < 5; count++)
{
allLEDOn();
waitWithButton(ledDelay);
allLEDOff();
waitWithButton(ledDelay);
}
// --------------------------------
// 第二階段:
// 跑馬燈來回,共 5 次
// --------------------------------
for (byte cycle = 0; cycle < 5; cycle++)
{
// LED1 -> LED8
for (byte i = 0; i < 8; i++)
{
showOnlyLED(i);
waitWithButton(ledDelay);
}
// LED7 -> LED1
//
// LED8 不再重複一次,
// 所以從 LED7 開始往回。
for (int i = 6; i >= 0; i--)
{
showOnlyLED(i);
waitWithButton(ledDelay);
}
}
// 跑馬燈結束後全部關掉
allLEDOff();
// loop() 會自動重新開始
}
// ======================================================
// 全部 LED 亮
// ======================================================
void allLEDOn()
{
for (byte i = 0; i < 8; i++)
{
digitalWrite(ledPins[i], HIGH);
}
}
// ======================================================
// 全部 LED 滅
// ======================================================
void allLEDOff()
{
for (byte i = 0; i < 8; i++)
{
digitalWrite(ledPins[i], LOW);
}
}
// ======================================================
// 只點亮指定的一顆 LED
//
// index:
// 0 = LED1
// 1 = LED2
// ...
// 7 = LED8
// ======================================================
void showOnlyLED(byte index)
{
for (byte i = 0; i < 8; i++)
{
if (i == index)
{
digitalWrite(ledPins[i], HIGH);
}
else
{
digitalWrite(ledPins[i], LOW);
}
}
}
// ======================================================
// 等待時間
//
// 不直接使用 delay(ledDelay),
// 因為 delay() 期間無法立即處理按鍵。
//
// 此函式等待時會持續檢查兩顆按鍵。
// ======================================================
void waitWithButton(unsigned long waitTime)
{
unsigned long startTime = millis();
while (millis() - startTime < waitTime)
{
checkButtons();
delay(10);
}
}
// ======================================================
// 檢查加速 / 減速按鍵
// ======================================================
void checkButtons()
{
bool speedUpState =
digitalRead(SPEED_UP_BUTTON);
bool speedDownState =
digitalRead(SPEED_DOWN_BUTTON);
// =========================
// 加速鍵
// =========================
if (speedUpState == LOW &&
lastSpeedUpState == HIGH)
{
// 簡單消除彈跳
delay(20);
if (digitalRead(SPEED_UP_BUTTON) == LOW)
{
if (ledDelay > MIN_DELAY)
{
if (ledDelay >= MIN_DELAY + STEP_DELAY)
{
ledDelay -= STEP_DELAY;
}
else
{
ledDelay = MIN_DELAY;
}
}
Serial.print("Speed UP : ");
Serial.print(ledDelay);
Serial.println(" ms");
}
}
// =========================
// 減速鍵
// =========================
if (speedDownState == LOW &&
lastSpeedDownState == HIGH)
{
// 簡單消除彈跳
delay(20);
if (digitalRead(SPEED_DOWN_BUTTON) == LOW)
{
if (ledDelay < MAX_DELAY)
{
ledDelay += STEP_DELAY;
if (ledDelay > MAX_DELAY)
{
ledDelay = MAX_DELAY;
}
}
Serial.print("Speed DOWN : ");
Serial.print(ledDelay);
Serial.println(" ms");
}
}
// 記錄目前按鍵狀態
lastSpeedUpState = speedUpState;
lastSpeedDownState = speedDownState;
}