HUB 8735 Ultra實作:用三個實體按鈕選擇三個水井三寶故事
V1.0-03已完成microSD卡與三個MP3檔案的依序播放測試;本次V1.0-04加入三個實體按鈕,讓使用者可直接選擇白馬、烏龜或姻緣花故事,故事機正式進入互動操作階段。
一、測試目標與結果
本次使用HUB 8735 Ultra讀取microSD卡中的三個MP3檔案,並以GPIO10、GPIO11、GPIO12分別連接三個按鈕。按下不同按鈕後,播放對應的故事。
二、按鈕與故事配置
白馬按鈕
↓
001.mp3烏龜按鈕
↓
002.mp3姻緣花按鈕
↓
003.mp3| GPIO腳位 | 實體按鈕 | MP3檔案 | 故事內容 |
|---|---|---|---|
| GPIO10 | 白馬按鈕 | 001.mp3 | 白馬故事 |
| GPIO11 | 烏龜按鈕 | 002.mp3 | 烏龜故事 |
| GPIO12 | 姻緣花按鈕 | 003.mp3 | 姻緣花故事 |
三、準備材料
- HUB 8735 Ultra開發板
- microSD卡一張
- 瞬時按鈕三個
- XPT8871單聲道功率放大板
- 喇叭一顆
- 5V電源、麵包板與杜邦線
四、按鈕接線圖
程式使用INPUT_PULLUP,所以每個按鈕的一端接GPIO,另一端接GND;未按下時讀到HIGH,按下時讀到LOW,不需要另外加外部上拉電阻。
五、音訊接線圖
六、microSD卡檔案配置
將三個MP3檔直接放在microSD卡根目錄,檔名必須完全一致:
microSD 根目錄 ├── 001.mp3 (白馬) ├── 002.mp3 (烏龜) └── 003.mp3 (姻緣花)
七、完整Arduino程式|V1.0-04
/*
* HUB 8735 Ultra 三按鈕故事播放器
* Version: V1.0-04
* GPIO10 → 白馬 → 001.mp3
* GPIO11 → 烏龜 → 002.mp3
* GPIO12 → 姻緣花 → 003.mp3
*/
#include "AmebaFatFS.h"
#include "AmebaFatFSFile.h"
#define MP3_VOLUME 0x90
#define STORY_COUNT 3
#define DEBOUNCE_MS 50
#define BUTTON_HORSE_PIN 10
#define BUTTON_TURTLE_PIN 11
#define BUTTON_FLOWER_PIN 12
AmebaFatFS fs;
const int buttonPins[STORY_COUNT] = {
BUTTON_HORSE_PIN,
BUTTON_TURTLE_PIN,
BUTTON_FLOWER_PIN
};
const char *storyFiles[STORY_COUNT] = {
"001.mp3",
"002.mp3",
"003.mp3"
};
const char *storyNames[STORY_COUNT] = {
"White Horse",
"Turtle",
"Marriage Flower"
};
String getFullPath(const char *filename)
{
return String(fs.getRootPath()) + String(filename);
}
bool checkMP3File(const char *filename)
{
String fullPath = getFullPath(filename);
File testFile = fs.open(fullPath);
Serial.print("[CHECK] ");
Serial.print(fullPath);
Serial.print(" ... ");
if (!testFile.isOpen()) {
Serial.println("NOT FOUND");
return false;
}
Serial.print("OK, ");
Serial.print(testFile.size());
Serial.println(" bytes");
testFile.close();
return true;
}
bool checkAllStoryFiles()
{
bool allReady = true;
for (int i = 0; i < STORY_COUNT; i++) {
if (!checkMP3File(storyFiles[i])) {
allReady = false;
}
}
return allReady;
}
bool playStory(int storyIndex)
{
if (storyIndex < 0 || storyIndex >= STORY_COUNT) {
return false;
}
String fullPath = getFullPath(storyFiles[storyIndex]);
File mp3File = fs.open(fullPath);
Serial.println();
Serial.println("========================================");
Serial.print("[BUTTON] GPIO: ");
Serial.println(buttonPins[storyIndex]);
Serial.print("[PLAY] Story: ");
Serial.println(storyNames[storyIndex]);
Serial.print("[PLAY] File: ");
Serial.println(fullPath);
if (!mp3File.isOpen()) {
Serial.println("[ERROR] Unable to open MP3 file.");
return false;
}
mp3File.setMp3DigitalVol(MP3_VOLUME);
Serial.println("[AUDIO] Playback started.");
// playMp3()會阻塞,直到目前故事播放完成
mp3File.playMp3();
Serial.println("[AUDIO] Playback completed.");
mp3File.close();
Serial.println("========================================");
return true;
}
void waitButtonRelease(int pin)
{
while (digitalRead(pin) == LOW) {
delay(10);
}
delay(DEBOUNCE_MS);
}
void setup()
{
Serial.begin(115200);
delay(2000);
Serial.println();
Serial.println("========================================");
Serial.println("HUB 8735 Ultra Story Player V1.0-04");
Serial.println("========================================");
for (int i = 0; i < STORY_COUNT; i++) {
pinMode(buttonPins[i], INPUT_PULLUP);
}
Serial.println("[SD] Initializing microSD card...");
fs.begin();
Serial.print("[SD] Root path: ");
Serial.println(fs.getRootPath());
if (!checkAllStoryFiles()) {
Serial.println("[FAIL] Check microSD card and filenames.");
while (true) {
delay(1000);
}
}
Serial.println("[READY] Press a story button.");
}
void loop()
{
for (int i = 0; i < STORY_COUNT; i++) {
if (digitalRead(buttonPins[i]) == LOW) {
delay(DEBOUNCE_MS);
if (digitalRead(buttonPins[i]) == LOW) {
playStory(i);
waitButtonRelease(buttonPins[i]);
Serial.println("[READY] Press a story button.");
}
}
}
delay(10);
}
八、操作方式
- 將三個MP3檔放入microSD卡根目錄。
- 依接線圖接好三個按鈕、XPT8871與喇叭。
- 上傳程式後,開啟115200 baud序列監控視窗。
- 按白馬按鈕播放001.mp3;按烏龜按鈕播放002.mp3;按姻緣花按鈕播放003.mp3。
九、序列監控預期訊息
HUB 8735 Ultra Story Player V1.0-04 [SD] Initializing microSD card... [CHECK] ...001.mp3 ... OK [CHECK] ...002.mp3 ... OK [CHECK] ...003.mp3 ... OK [READY] Press a story button. [BUTTON] GPIO: 10 [PLAY] Story: White Horse [PLAY] File: ...001.mp3 [AUDIO] Playback started. [AUDIO] Playback completed.
十、V1.0-03與V1.0-04比較
| 項目 | V1.0-03 | V1.0-04 |
|---|---|---|
| 播放方式 | 開機後依序播放三個故事 | 按下實體按鈕選擇故事 |
| 互動性 | 無 | 三個獨立按鈕 |
| microSD | 三個MP3檔 | 沿用相同三個MP3檔 |
| GPIO | 未使用按鈕 | GPIO10、11、12 |
十一、目前限制與後續方向
目前使用的playMp3()會等待故事播放完畢,因此播放期間不會偵測其他按鈕。對「一按一個完整故事」的操作方式而言很單純穩定;未來若需要中途停止、切換故事或調整音量,則要再研究非阻塞播放或額外的播放控制機制。
下一階段可以加入LED播放指示、音量按鈕、停止鍵、開機提示音,或進一步加入網路語音與AI對話功能。
<html>、<head>與<body>標籤,並已限制程式碼區塊寬度,避免破壞Blogger版型或把右側資訊欄擠出畫面。