ESP32 + MAX98357A+喇叭+SSD OLED1306
| 模塊 | 引腳 | 接線說明 |
|---|---|---|
| ESP32 | GPIO22 | → MAX98357A DIN |
| ESP32 | GPIO26 | → MAX98357A BCLK |
| ESP32 | GPIO25 | → MAX98357A LRC(或 WS) |
| ESP32 | 5V | → MAX98357A VIN(推薦使用 5V) |
| ESP32 | GND | → MAX98357A GND |
| MAX98357A | OUT+ | → 喇叭正極 |
| MAX98357A | OUT? | → 喇叭負極 |
├── data/
│ └── music.mp3
├── src/
│ └── main.cpp
├── platformio.ini
#include <Arduino.h>
#include <SPIFFS.h>
#include <Audio.h>
#include <WiFi.h>
// WiFi 信息
const char* ssid = "Y0ur_SSID";
const char* password = "Y0ur_pass";
// I2S 引腳定義
#define I2S_DOUT 22
#define I2S_BCLK 26
#define I2S_LRC 25
Audio audio;
void setup() {
Serial.begin(115200);
delay(1000);
// 連接 WiFi
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// 初始化 SPIFFS(可選,如果不再用可以注釋)
// if (!SPIFFS.begin(true)) {
// Serial.println("SPIFFS 掛載失敗!");
// return;
// }
// 初始化音頻(使用 I2S 輸出)
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(10); // 0~21
// 播放公網 MP3
audio.connecttohost("http://www.taotao01.fun/music.mp3");
}
void loop() {
audio.loop(); // 必須放 loop 中不斷調用
}
pio run --target uploadfs #上傳文件
進階版V2
| 元件 | ESP32 引腳 | 說明 |
|---|---|---|
| MAX98357A DOUT(DIN) | GPIO 22 | 音頻數據(I2S DATA) |
| MAX98357A BCLK | GPIO 26 | I2S 時鐘 |
| MAX98357A LRC(WS) | GPIO 25 | I2S 左右聲道同步 |
| OLED SDA | GPIO 21 | I2C 數據 |
| OLED SCL | GPIO 22 | I2C 時鐘(共用沒問題) |
| 按鈕 1 | GPIO 34 | 播放/暫停(輸入,僅支持輸入) |
| 按鈕 2 | GPIO 35 | 下一首(輸入,僅支持輸入) |
點擊查看代碼
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <Audio.h>
#include <Wire.h>
#include <ArduinoJson.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// ==== 配置 ==== //
const char* ssid = "Y0ur_SSID";
const char* password = "Y0ur_pass";
const char* music_api = "http://www.expamle.com/get_music_list.php";
// OLED 設置
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// 按鈕引腳
#define BUTTON_PLAY 34
#define BUTTON_NEXT 35
// I2S 引腳
#define I2S_DOUT 25
#define I2S_BCLK 26
#define I2S_LRC 27
Audio audio;
bool isPlaying = false;
// 音樂信息結構體
struct MusicItem {
String url;
String title;
};
// ========== 獲取音樂 JSON ==========
MusicItem fetchMusicURL() {
MusicItem result;
HTTPClient http;
http.begin(music_api);
int httpCode = http.GET();
if (httpCode == 200) {
String payload = http.getString();
http.end();
StaticJsonDocument<1024> doc;
DeserializationError error = deserializeJson(doc, payload);
if (!error && doc.is<JsonArray>()) {
JsonObject obj = doc[0];
result.url = obj["url"].as<String>();
result.title = obj["title"].as<String>();
}
} else {
http.end();
}
return result;
}
// ========== OLED 顯示函數 ==========
void showStatus(const String& line1, const String& line2 = "") {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 10);
display.println(line1);
display.println(line2);
display.display();
}
// ========== 播放下一首 ==========
void playNext() {
showStatus("Loading...");
MusicItem item = fetchMusicURL();
if (item.url != "") {
showStatus("Playing", item.title);
audio.connecttohost(item.url.c_str());
isPlaying = true;
} else {
showStatus("Failed to load");
}
}
// ========== 初始化 ==========
void setup() {
Serial.begin(115200);
pinMode(BUTTON_PLAY, INPUT_PULLUP);
pinMode(BUTTON_NEXT, INPUT_PULLUP);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected!");
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("SSD1306 init failed");
while (true);
}
showStatus("WiFi Connected", WiFi.localIP().toString());
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(10);
playNext();
}
// ========== 主循環 ==========
unsigned long lastPlayNextTime = 0;
void loop() {
static bool lastPlayState = HIGH;
static bool lastNextState = HIGH;
// 播放/暫停
bool currentPlay = digitalRead(BUTTON_PLAY);
if (currentPlay == LOW && lastPlayState == HIGH) {
if (isPlaying) {
audio.stopSong();
showStatus("Paused");
isPlaying = false;
} else {
playNext();
}
}
lastPlayState = currentPlay;
// 下一首
bool currentNext = digitalRead(BUTTON_NEXT);
if (currentNext == LOW && lastNextState == HIGH) {
playNext();
}
lastNextState = currentNext;
// ? 播放完成 -> 自動下一首(加延時防抖)
if (!audio.isRunning() && isPlaying) {
unsigned long now = millis();
if (now - lastPlayNextTime > 3000) { // 至少間隔3秒
playNext();
lastPlayNextTime = now;
}
}
audio.loop();
delay(50);
}

浙公網安備 33010602011771號