作者:Ted Lee
什麼是 Maker Uno?
在開始討論 Maker Uno 之前,我們先回顧開發板(development board)界的經典 Arduino Uno。15 年前(2010),這塊只提供核心控制、所有的電子元件與感測器皆需以外接方式和微控制器(micro controller)相連接的板子,因為其開源硬體(open hardware)的特質,15 年來早就成為機電整合專案開發領域中為廣為人知的個中翹楚了!
然而,為了讓使用者更方便快速體驗電控程式的開發流程,馬來西亞的 Cytron 科技在 2017 年設計了板載復歸式(momentary)的按鈕開關(push button)(圖 1 中標示紅 1 處)、單色 LED(圖 1 中標示紅 2 處) 與蜂鳴器(圖 1 中標示紅 3 處)三種常見的電子元件的 Maker Uno。
![圖 1:Maker Uno[2]](https://makerpro.cc/wp-content/uploads/2025/07/1b_MJJYB8K_-VaLZJi8ucCg.webp)
圖 1:Maker Uno[2]
本文期盼以最短、最無痛的學習曲線帶領讀者們輕輕敲開電控程式的入門磚!
軟、硬體開發環境測試
所有的軟、硬體專案在進行開發之前都需要先設定好開發環境(development environment)。
首先,根據原廠手冊第 14 頁提供的 CH341 驅動程式(driver)連結,下載並安裝(圖 2)。

圖 2:CH341 驅動程式
接著,下載 Arduino IDE、安裝,再設定好開發板的型號(board)與序列埠(serial port)(圖 3),

圖 3:在 Arduino IDE 上設定好 Arduino Uno 板子與序列埠 COMx
最後,從「File -> Examples -> 01.Basics -> Blink」選擇 Arduino IDE 內建的 Blink 範例程式(圖 4)來測試板載接在 D13 腳位上的藍色 SMD LED 能否不斷閃鑠。
Blink 的完整程式碼如下,程式的設計邏輯是讓 D13 腳不斷重覆位輸出高電位來點亮 LED 一秒鐘,再輸出低電位關閉 LED 一秒鐘。
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
板載電子元件一:按鈕開關(第 2 腳位)
板載的四隻腳的按鈕開關按下時電路導通形成電路迴路(loop);放開時則電路斷路(open circuit),圖 5。原廠手冊(Maker Uno User’s Manual.docx)上有提醒:使用前應先將第 2 腳位設定成拉升(pull-up)準位。

圖 5:按鈕開關按下時由 1->0(左圖);按鈕開關按下時由 0->1(右圖)
接著,我們在 ChaGPT 中上傳「Maker Uno User’s Manual.docx」,再輸入以下咒語(prompt)(圖 6):
(人設)你是 Cytron Technology 的 Maker Uno 專家
(任務)
一個字一個讀「Maker Uno User’s Manual.docx」,並簡要說明你讀到的內容Push button 接在 pin 2,使用前要 configure as INPUT_PULLUP
按鈕按一下讓 D13 的 SMD LED 亮,再按一下滅
(輸出)生成 Uno 的程式碼

圖 6:ChatGPT 的回應
最後,生成的完整程式碼如下:
// Pin 定義
const int buttonPin = 2; // 按鈕接在 D2
const int ledPin = 13; // D13 為內建 SMD LED
// 狀態追蹤
bool ledState = false;
bool lastButtonState = HIGH;
bool buttonPressed = false;
void setup() {
pinMode(buttonPin, INPUT_PULLUP); // 啟用內部上拉電阻
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, ledState); // 初始 LED 狀態
}
void loop() {
bool currentButtonState = digitalRead(buttonPin);
// 偵測按下的瞬間(由 HIGH 變 LOW)
if (lastButtonState == HIGH && currentButtonState == LOW) {
buttonPressed = true;
}
// 偵測放開的瞬間(由 LOW 變 HIGH)
if (lastButtonState == LOW && currentButtonState == HIGH && buttonPressed) {
ledState = !ledState; // 切換 LED 狀態
digitalWrite(ledPin, ledState); // 更新 LED 狀態
buttonPressed = false;
}
lastButtonState = currentButtonState; // 儲存目前狀態供下次比較
}
註:經筆者測試,本文的三個由 ChatGPT 生成的程式
板載電子元件二:單色 LED(第 D2~13 腳位)
LED(Light-Emitting Diode,發光二極體)的發光原理是將元件接上順向電壓後,這個半導體元件就會將供給的電能轉換成光能而發光。
首先,我們在 ChatGPT 上接續按鈕開關的例子再下達以下咒語:
(任務)
LED 接在 D2~D13
依序點亮各顆 LED
(輸出)生成 Uno 的程式碼
ChatGPT 生成的完整程式碼如下:
// Cytron Maker Uno - 依序點亮 D2~D13 上的 LED
void setup() {
// 將 D2 ~ D13 設為輸出
for (int pin = 2; pin <= 13; pin++) {
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW); // 初始為關閉
}
}
void loop() {
// 依序點亮每顆 LED
for (int pin = 2; pin <= 13; pin++) {
digitalWrite(pin, HIGH); // 點亮
delay(200); // 停留 200 毫秒
digitalWrite(pin, LOW); // 關閉
}
delay(500); // 每輪間隔
}
板載電子元件三:蜂鳴器(第 8 腳位)
蜂鳴器是電磁效應:電生磁,磁生力。相關原理可參考這個影片。
我們在 ChatGPT 上接續按鈕開關的例子再下達以下咒語:
(任務)
蜂鳴器接在 D8
唱歌
(輸出)生成 Uno 的程式碼
ChatGPT 生成的完整程式碼如下:
// Cytron Maker Uno - 用蜂鳴器(D8)演奏簡單旋律
const int buzzerPin = 8; // 蜂鳴器接腳
// 定義音符頻率 (C4~B4)
#define NOTE_C4 262
#define NOTE_D4 294
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_G4 392
#define NOTE_A4 440
#define NOTE_B4 494
#define NOTE_C5 523
// 簡單旋律:Do Re Mi Fa So La Ti Do(各 300 毫秒)
int melody[] = {
NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4,
NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5
};
int noteDuration = 300; // 每個音的持續時間(毫秒)
void setup() {
// 無需初始化 tone,用時直接呼叫 tone()
}
void loop() {
for (int i = 0; i < 8; i++) {
tone(buzzerPin, melody[i], noteDuration); // 播放音符
delay(noteDuration * 1.3); // 加點間隔
}
delay(1000); // 播完一輪後暫停
}
結語
Arduino 生態系(eco system)經過了數十年的累積,正足以做為 ChatGPT 的先前訓練資料(pre-trained data),以致我們讓它生成 Maker Uno 的程式碼時是完全無縫接軌的。
這一步將撰寫程式碼的工作分派給 ChatGPT 的程式碼隱藏(code hiding)技巧,正足以讓初學者更專注在機電整合設計的上層邏輯思考。
因此,我們變成不怕做不出來,只怕想像不到。進而引領我們得以更深入地往「好設計」的指導原則大步邁進!
進階學習
以下數題提供給讀者們小試身手,仿照前文的咒語方式,自行設計合適的文字內容。再次提醒,生成式 AI(Generative AI,GenAI)的特質:
凡提問必有多套答案,但答案有可能是胡說八道!
-
-
- 按下按鈕時演奏著名的台語民謠:望春風。ChatGPT 產生的參考程式碼如下:
// Maker Uno 彈奏《望春風》簡譜程式
// 按鈕接在第 2 腳,蜂鳴器接在第 8 腳
const int buttonPin = 2; // 按鈕接在第 2 腳
const int buzzerPin = 8; // 蜂鳴器接在第 8 腳
bool lastButtonState = HIGH;
bool currentButtonState = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
// 定義音符頻率 (Hz) - Key: C major, 4/4拍
#define NOTE_C4 262
#define NOTE_D4 294
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_G4 392
#define NOTE_A4 440
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_D5 587
#define NOTE_E5 659
#define REST 0
// 《望春風》簡譜 - 根據圖片轉換
// 第一段:1 - 1 2 4 | 5 4 5 6 - | 1 · 6 6 5 4 | 5 - - - |
// 第二段:6 · 1 1 6 | 4 · 5 5 - | 1 · 6 6 5 4 | 4 - - - |
// 第三段:5 · 5 6 5 4 | 2 1 2 4 - | 2 · 4 5 4 6 | 1 - - - |
// 第四段:1 · 1 2 1 6 | 6 5 4 2 - | 1 · 6 6 5 | 4 - - - ||
int melody[] = {
// 第一句:獨 夜無伴 守燈 下 清 風 對 面 吹
NOTE_C4, NOTE_C4, NOTE_D4, NOTE_F4, NOTE_G4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_C4, NOTE_A4, NOTE_A4, NOTE_G4, NOTE_F4, NOTE_G4,
// 第二句:十 七八歲 未 出嫁 想 著少年 家 開
NOTE_A4, NOTE_C4, NOTE_C4, NOTE_A4, NOTE_F4, NOTE_G4, NOTE_G4, NOTE_C4, NOTE_A4, NOTE_A4, NOTE_G4, NOTE_F4, NOTE_F4,
// 第三句:果 然標緻 面肉 白 誰 家 人 子 弟
NOTE_G4, NOTE_G4, NOTE_A4, NOTE_G4, NOTE_F4, NOTE_D4, NOTE_C4, NOTE_D4, NOTE_F4, NOTE_D4, NOTE_F4, NOTE_G4, NOTE_F4, NOTE_A4, NOTE_C4,
// 第四句:想 要問伊 驚歹 勢 心 內彈琵 慧
NOTE_C4, NOTE_C4, NOTE_D4, NOTE_C4, NOTE_A4, NOTE_A4, NOTE_G4, NOTE_F4, NOTE_D4, NOTE_C4, NOTE_A4, NOTE_A4, NOTE_G4, NOTE_F4
};
// 音符時值 (毫秒) - 配合 4/4 拍
int noteDurations[] = {
// 第一句時值
500, 250, 250, 500, 500, 250, 250, 750, 250, 250, 250, 250, 250, 1000,
// 第二句時值
250, 250, 250, 500, 250, 250, 750, 250, 250, 250, 250, 250, 1000,
// 第三句時值
250, 250, 250, 250, 500, 250, 250, 250, 750, 250, 250, 250, 250, 500, 1000,
// 第四句時值
250, 250, 250, 250, 500, 250, 250, 250, 750, 250, 250, 250, 500, 1500
};
int melodyLength = sizeof(melody) / sizeof(melody[0]);
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(buzzerPin, OUTPUT);
Serial.begin(9600);
Serial.println("《望春風》音樂播放器啟動");
Serial.println("按下按鈕開始播放音樂");
}
void loop() {
// 讀取按鈕狀態
int reading = digitalRead(buttonPin);
// 防彈跳處理
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != currentButtonState) {
currentButtonState = reading;
// 按鈕被按下時播放音樂
if (currentButtonState == LOW) {
Serial.println("開始播放《望春風》");
playMelody();
Serial.println("播放完畢");
}
}
}
lastButtonState = reading;
}
void playMelody() {
for (int i = 0; i < melodyLength; i++) {
// 計算音符持續時間
int noteDuration = noteDurations[i];
if (melody[i] != REST) {
// 播放音符
tone(buzzerPin, melody[i], noteDuration);
Serial.print("播放音符: ");
Serial.print(melody[i]);
Serial.print(" Hz, 持續: ");
Serial.print(noteDuration);
Serial.println(" ms");
} else {
// 休止符
Serial.println("休止符");
}
// 等待音符播放完畢,加上短暫間隔
delay(noteDuration);
// 音符間的短暫停頓
noTone(buzzerPin);
delay(50);
}
}
// 額外功能:播放單一音符測試
void playTestNote(int frequency, int duration) {
tone(buzzerPin, frequency, duration);
delay(duration);
noTone(buzzerPin);
}
// 額外功能:播放音階
void playScale() {
int scale[] = {NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5};
int scaleLength = sizeof(scale) / sizeof(scale[0]);
for (int i = 0; i < scaleLength; i++) {
tone(buzzerPin, scale[i], 300);
delay(350);
}
noTone(buzzerPin);
} - 接續第 1 題,設計一個讓 Maker Uno 可以動態點唱台語「四(季紅)月(夜愁)望(春風)雨(夜花)」的操作方式。
- 讓奇數編號的 LED 和偶數編號的 LED 交替閃爍。ChatGPT 產生的參考程式碼如下:
// 程式範例 3:交替閃爍 (Alternating Flash)
// 讓奇數編號的 LED 和偶數編號的 LED 交替閃爍
const int ledPins[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; // 將 D3 到 D12 的 LED 腳位儲存在陣列中
const int numLeds = sizeof(ledPins) / sizeof(ledPins[0]); // 計算 LED 數量
const int flashDelay = 1000; // 亮滅之間的時間間隔 (毫秒)
const int pauseDelay = 2000; // 兩組 LED 之間的時間間隔 (毫秒)
void setup() {
// 設定所有 LED 腳位為輸出模式
for (int i = 0; i < numLeds; i++) {
pinMode(ledPins[i], OUTPUT);
}
}
void loop() {
// 點亮奇數編號的 LED (例如 D3, D5, D7...)
for (int i = 0; i < numLeds; i += 2) { // 每隔一個 LED 點亮
digitalWrite(ledPins[i], HIGH);
}
delay(flashDelay);
// 熄滅奇數編號的 LED
for (int i = 0; i < numLeds; i += 2) {
digitalWrite(ledPins[i], LOW);
}
delay(pauseDelay); // 暫停一下
// 點亮偶數編號的 LED (例如 D4, D6, D8...)
for (int i = 1; i < numLeds; i += 2) { // 從第二個 LED (索引 1) 開始點亮
digitalWrite(ledPins[i], HIGH);
}
delay(flashDelay);
// 熄滅偶數編號的 LED
for (int i = 1; i < numLeds; i += 2) {
digitalWrite(ledPins[i], LOW);
}
delay(pauseDelay); // 暫停一下
} - 讓 LED 從 D3 亮到 D12,再從 D12 亮回 D3。
// 程式範例 2:來回閃爍 (Bounce Flash)
// 讓 LED 從 D3 亮到 D12,再從 D12 亮回 D3
const int ledPins[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; // 將 D3 到 D12 的 LED 腳位儲存在陣列中
const int numLeds = sizeof(ledPins) / sizeof(ledPins[0]); // 計算 LED 數量
const int delayTime = 80; // 每個 LED 亮滅之間的時間間隔 (毫秒)
void setup() {
// 設定所有 LED 腳位為輸出模式
for (int i = 0; i < numLeds; i++) {
pinMode(ledPins[i], OUTPUT);
}
}
void loop() {
// 從前往後依序點亮 LED
for (int i = 0; i < numLeds; i++) { digitalWrite(ledPins[i], HIGH); // 點亮 LED delay(delayTime); // 延遲 digitalWrite(ledPins[i], LOW); // 熄滅 LED (只亮一下) } // 從後往前依序點亮 LED for (int i = numLeds - 2; i >= 0; i--) { // 注意這裡從倒數第二個開始,避免重複點亮最後一個
digitalWrite(ledPins[i], HIGH); // 點亮 LED
delay(delayTime); // 延遲
digitalWrite(ledPins[i], LOW); // 熄滅 LED (只亮一下)
}
} - 讓 LED 隨機亮起和熄滅。
// 程式範例 4:隨機閃爍 (Random Flash)
// 讓 LED 隨機亮起和熄滅
const int ledPins[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; // 將 D3 到 D12 的 LED 腳位儲存在陣列中
const int numLeds = sizeof(ledPins) / sizeof(ledPins[0]); // 計算 LED 數量
void setup() {
// 設定所有 LED 腳位為輸出模式
for (int i = 0; i < numLeds; i++) {
pinMode(ledPins[i], OUTPUT);
}
randomSeed(analogRead(A0)); // 使用 A0 腳位的類比讀值來初始化亂數種子,增加隨機性
}
void loop() {
// 隨機選擇要點亮多少個 LED
int numToLight = random(1, numLeds + 1); // 至少一個,最多所有 LED
// 隨機選擇要點亮哪些 LED
for (int i = 0; i < numToLight; i++) {
int randomLedIndex = random(0, numLeds); // 隨機選擇一個 LED 索引
digitalWrite(ledPins[randomLedIndex], HIGH); // 點亮該 LED
}
// 隨機亮燈時間
delay(random(100, 500)); // 隨機延遲 100 到 500 毫秒
// 熄滅所有 LED
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW);
}
// 隨機熄燈時間 (下次亮燈前的間隔)
delay(random(50, 300)); // 隨機延遲 50 到 300 毫秒
} - 讓 LED 從 D3 依序亮到 D12,然後再依序熄滅。
// 程式範例 1:流水燈 (Running Light)
// 讓 LED 從 D3 依序亮到 D12,然後再依序熄滅
const int ledPins[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; // 將 D3 到 D12 的 LED 腳位儲存在陣列中
const int numLeds = sizeof(ledPins) / sizeof(ledPins[0]); // 計算 LED 數量
const int delayTime = 100; // 每個 LED 亮滅之間的時間間隔 (毫秒)
void setup() {
// 設定所有 LED 腳位為輸出模式
for (int i = 0; i < numLeds; i++) {
pinMode(ledPins[i], OUTPUT);
}
}
void loop() {
// LED 依序亮起
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], HIGH); // 點亮 LED
delay(delayTime); // 延遲一段時間
}
// LED 依序熄滅
for (int i = 0; i < numLeds; i++) {
digitalWrite(ledPins[i], LOW); // 熄滅 LED
delay(delayTime); // 延遲一段時間
}
}
- 按下按鈕時演奏著名的台語民謠:望春風。ChatGPT 產生的參考程式碼如下:
-
[0]感謝竹南科技中心借用設備做為教學測試。
[1]六種授權條款
[2]圖片來源:https://docs.google.com/document/d/1gJIF-tssdoxk8qAq2aHBmPwVHulFL_lSElOhA17Du64/mobilebasic。
(作者為本刊專欄作家,本文同步表於作者部落格,原文連結;責任編輯:謝涵如)
- 使用 Maker Uno 快速打造 Arduino入門成功經驗 [0] - 2025/07/30
- 【Ted Lee】莫閣比(micro:bit)台語播放機 - 2025/07/04
- 用GenAI生成連連看樣板 - 2025/05/15
訂閱MakerPRO知識充電報
與40000位開發者一同掌握科技創新的技術資訊!