ESP32 미니 MP3 플레이어
ESP32는 WiFi, 블루투스, 다중 하드웨어 시리얼 포트를 갖춘 다재다능한 3.3V 마이크로컨트롤러입니다. DIYables 미니 MP3 플레이어 모듈과 결합하면 간단한 효과음 보드부터 WiFi 제어 주크박스까지 무엇이든 만들 수 있습니다.
이 튜토리얼에서 다루는 내용:
저항 없이 미니 MP3 플레이어를 ESP32에 직접 연결하기.
SD 카드에 MP3 파일을 올바르게 로드하기.
트랙 재생, 일시정지, 재개, 중지, 건너뛰기.
물리적 버튼으로 볼륨 조절.
트랙 반복, 셔플, 폴더로 오디오 정리.
코드에서 재생 상태 모니터링.
| 1 | × | 38-pin ESP32 ESP-WROOM-32 Dev Module - Narrow | 쿠팡 | 아마존 | |
| 1 | × | (또는) 38-pin ESP32 ESP-WROOM-32 Dev Module - Wide | 쿠팡 | 아마존 | |
| 1 | × | (또는) 30-pin ESP32 ESP-WROOM-32 Dev Module - Wide | 아마존 | |
| 1 | × | (또는) ESP32 Uno-form board | 아마존 | |
| 1 | × | (또는) ESP32 S3 Uno-form board | 아마존 | |
| 1 | × | USB 케이블 타입-A to 타입-C (USB-A PC용) | 쿠팡 | 아마존 | |
| 1 | × | USB 케이블 타입-C to 타입-C (USB-C PC용) | 아마존 | |
| 1 | × | DIYables Mini Mp3 Player module | 아마존 | |
| 1 | × | 마이크로 SD 카드 | 아마존 | |
| 1 | × | Speaker | 아마존 | |
| 1 | × | 브레드보드 | 쿠팡 | 아마존 | |
| 1 | × | 점퍼케이블 | 쿠팡 | 아마존 | |
| 1 | × | (추천) ESP32용 스크루 터미널 확장 보드 | 쿠팡 | 아마존 | |
| 1 | × | (추천) Breakout Expansion Board for ESP32 | 쿠팡 | 아마존 | |
| 1 | × | (추천) ESP32용 전원 분배기 | 쿠팡 | 아마존 | |
공개: 이 포스팅 에 제공된 일부 링크는 아마존 제휴 링크입니다. 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
저항 불필요. ESP32는 3.3V로 동작합니다 — 미니 MP3 플레이어의 UART가 기대하는 전압과 동일합니다.
DIYables 미니 MP3 플레이어는 YX5200-24SS 칩을 기반으로 한 소형 보드입니다. 마이크로 SD 카드에서 MP3 파일을 디코딩하며, 내장 3W 앰프를 통해 스피커를 직접 구동할 수 있습니다. 또는 더 큰 출력을 위해 DAC 핀을 외부 앰프에 연결할 수 있습니다.
모든 것은 9600 보드의 시리얼 명령으로 제어됩니다:
전송: 재생, 일시정지, 재개, 중지, 다음, 이전
볼륨: 31단계 (0–30)
이퀄라이저: 일반, 팝, 록, 재즈, 클래식, 베이스
반복: 단일 트랙 반복, 폴더 반복, 전체 트랙 반복, 랜덤 셔플
폴더: 카드의 번호가 매겨진 디렉토리에서 재생
광고: 재생을 일시 중단 후 계속
쿼리: 트랙 번호, 볼륨, 재생 상태, 트랙 수 읽기
| 핀 | 용도 |
| VCC | 3.2V~5.0V 전원 입력 |
| GND | 접지 |
| RX | 시리얼 데이터 입력 (ESP32 TX 핀에 연결) |
| TX | 시리얼 데이터 출력 (ESP32 RX 핀에 연결) |
| SPK_1 | 스피커 + (내장 앰프, 최대 3W) |
| SPK_2 | 스피커 - |
| DAC_R | 오른쪽 채널 라인 출력 |
| DAC_L | 왼쪽 채널 라인 출력 |
| BUSY | LOW = 재생 중, HIGH = 중지됨 |
| IO_1 | 짧게 누르기 → 이전 트랙; 길게 누르기 → 볼륨 감소 |
| IO_2 | 짧게 누르기 → 다음 트랙; 길게 누르기 → 볼륨 증가 |
ESP32는 3.3V 로직을 기본으로 사용하므로 시리얼 라인을 직접 연결합니다 — 레벨 변환이나 저항이 필요 없습니다.
대부분의 ESP32 DevKit 보드에서 기본으로 사용 가능한 Serial2를 권장합니다:
| 미니 MP3 플레이어 | ESP32 | 비고 |
| VCC | 3.3V | 또는 사용 가능한 경우 VIN의 5V |
| GND | GND | |
| RX | GPIO 17 (TX2) | 직접 연결 |
| TX | GPIO 16 (RX2) | 직접 연결 |
| SPK_1 | 스피커 + | |
| SPK_2 | 스피커 - | |

이 이미지는 Fritzing을 사용하여 만들어졌습니다. 이미지를 확대하려면 클릭하세요.
ESP32 및 다른 구성 요소에 전원을 공급하는 방법에 대해 잘 알지 못하는 경우, 다음 튜토리얼에서 안내를 찾을 수 있습니다: ESP32 전원 공급 방법.
팁: ESP32 변형 보드 중 GPIO 16/17이 노출되지 않은 경우(일부 DevKit-C V4 보드는 PSRAM에 사용), 코드에서 Serial2 핀을 재할당할 수 있습니다:
Serial2.begin(9600, SERIAL_8N1, 4, 5);
FAT16 또는 FAT32로 포맷합니다.
루트에 MP3 파일을 저장합니다:
/001.mp3
/002.mp3
/003.mp3
정리된 재생을 위해 번호가 매겨진 폴더를 사용합니다:
/01/001.mp3
/01/002.mp3
/02/001.mp3
중요 사항:
트랙 번호는 1부터 시작합니다.
모듈은 파일 이름이 아닌 카드에 복사된 순서대로 트랙을 인덱싱합니다. 항상 먼저 포맷하고 순서대로 복사하세요.
폴더 이름: 01–99 (2자리), 파일 이름: 001–255 (3자리).
#include <DIYables_MiniMp3.h>
DIYables_MiniMp3 mp3;
void setup() {
Serial.begin(115200);
Serial2.begin(9600);
mp3.begin(Serial2);
delay(1000);
mp3.setVolume(25);
}
void loop() {
}
#include <DIYables_MiniMp3.h>
DIYables_MiniMp3 mp3;
void setup()
{
Serial.begin(9600);
Serial2.begin(9600);
mp3.begin(Serial2);
delay(1000);
mp3.setVolume(25);
Serial.println("Playing track 1...");
mp3.play(1);
}
void loop()
{
}
SD 카드를 로드하고, 모듈을 연결하고, USB로 ESP32를 연결합니다.
IDE에서 ESP32 보드를 선택하고 업로드합니다.
| 메서드 | 동작 | 코드 예시 |
| play(n) | 트랙 n 재생 | mp3.play(1) |
| playNext() | 다음 트랙으로 이동 | mp3.playNext() |
| playPrevious() | 이전 트랙으로 이동 | mp3.playPrevious() |
| pause() | 재생 일시 정지 | mp3.pause() |
| resume() | 중단된 위치에서 재개 | mp3.resume() |
| stop() | 재생 완전히 종료 | mp3.stop() |
#include <DIYables_MiniMp3.h>
DIYables_MiniMp3 mp3;
int currentTrack = 1;
int totalTracks = 3;
unsigned long lastTrackTime = 0;
unsigned long trackDuration = 5000;
void setup()
{
Serial.begin(9600);
Serial2.begin(9600);
mp3.begin(Serial2);
delay(1000);
mp3.setVolume(20);
Serial.println("Playing track 1...");
mp3.play(currentTrack);
lastTrackTime = millis();
}
void loop()
{
if (millis() - lastTrackTime >= trackDuration)
{
currentTrack++;
if (currentTrack > totalTracks)
currentTrack = 1;
Serial.print("Playing track ");
Serial.println(currentTrack);
mp3.play(currentTrack);
lastTrackTime = millis();
}
}
#include <DIYables_MiniMp3.h>
DIYables_MiniMp3 mp3;
const int BUTTON_VOL_UP = 1;
const int BUTTON_VOL_DOWN = 3;
int volume = 15;
void setup()
{
Serial.begin(9600);
Serial2.begin(9600);
pinMode(BUTTON_VOL_UP, INPUT_PULLUP);
pinMode(BUTTON_VOL_DOWN, INPUT_PULLUP);
mp3.begin(Serial2);
delay(1000);
mp3.setVolume(volume);
mp3.loopTrack(1);
Serial.print("Volume: ");
Serial.println(volume);
}
void loop()
{
if (digitalRead(BUTTON_VOL_UP) == LOW)
{
if (volume < 30)
{
volume++;
mp3.setVolume(volume);
Serial.print("Volume: ");
Serial.println(volume);
}
delay(200);
}
if (digitalRead(BUTTON_VOL_DOWN) == LOW)
{
if (volume > 0)
{
volume--;
mp3.setVolume(volume);
Serial.print("Volume: ");
Serial.println(volume);
}
delay(200);
}
}
| 메서드 | 동작 | 예시 |
| setVolume(v) | v 레벨로 점프 | mp3.setVolume(20) |
| volumeUp() | 1 증가 | mp3.volumeUp() |
| volumeDown() | 1 감소 | mp3.volumeDown() |
| getVolume() | 현재 레벨 읽기 | mp3.getVolume() |
#include <DIYables_MiniMp3.h>
DIYables_MiniMp3 mp3;
const int BUTTON_NEXT = 1;
const int BUTTON_PREV = 3;
void setup()
{
Serial.begin(9600);
Serial2.begin(9600);
pinMode(BUTTON_NEXT, INPUT_PULLUP);
pinMode(BUTTON_PREV, INPUT_PULLUP);
mp3.begin(Serial2);
delay(1000);
mp3.setVolume(20);
mp3.play(1);
Serial.println("Press NEXT or PREV button to change track");
}
void loop()
{
if (digitalRead(BUTTON_NEXT) == LOW)
{
Serial.println("Next track");
mp3.playNext();
delay(300);
}
if (digitalRead(BUTTON_PREV) == LOW)
{
Serial.println("Previous track");
mp3.playPrevious();
delay(300);
}
}
#include <DIYables_MiniMp3.h>
DIYables_MiniMp3 mp3;
const int BUTTON_PIN = 1;
bool paused = false;
void setup()
{
Serial.begin(9600);
Serial2.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
mp3.begin(Serial2);
delay(1000);
mp3.setVolume(20);
mp3.play(1);
Serial.println("Playing. Press button to pause/resume.");
}
void loop()
{
if (digitalRead(BUTTON_PIN) == LOW)
{
if (paused)
{
mp3.resume();
Serial.println("Resumed");
}
else
{
mp3.pause();
Serial.println("Paused");
}
paused = !paused;
delay(300);
}
}
#include <DIYables_MiniMp3.h>
DIYables_MiniMp3 mp3;
void setup()
{
Serial.begin(9600);
Serial2.begin(9600);
mp3.begin(Serial2);
delay(1000);
mp3.setVolume(25);
mp3.setEQ(DIYables_MiniMp3::EQ_NORMAL);
Serial.println("Playing track 1 on loop...");
mp3.loopTrack(1);
}
void loop()
{
}
| 메서드 | 동작 | 예시 |
| loopTrack(n) | 트랙 n을 무한 반복 | mp3.loopTrack(1) |
| loopFolder(f) | 폴더 f의 모든 트랙 반복 | mp3.loopFolder(1) |
| loopAll() | 모든 트랙 반복 | mp3.loopAll() |
| stopLoop() | 활성 반복 취소 | mp3.stopLoop() |
| shuffle() | 재생 무작위화 | mp3.shuffle() |
#include <DIYables_MiniMp3.h>
DIYables_MiniMp3 mp3;
void setup()
{
Serial.begin(9600);
Serial2.begin(9600);
mp3.begin(Serial2);
delay(1000);
mp3.setVolume(20);
Serial.println("Playing folder 01, track 001...");
mp3.playFolder(1, 1);
delay(5000);
Serial.println("Playing folder 01, track 002...");
mp3.playFolder(1, 2);
delay(5000);
Serial.println("Playing folder 02, track 001...");
mp3.playFolder(2, 1);
}
void loop()
{
}
| 메서드 | 설명 | 예시 |
| playFolder(f, t) | 폴더 f에서 트랙 t 재생 | mp3.playFolder(1, 1) |
| playLargeFolder(f, t) | 대용량 폴더 (15개 폴더, 3000개 트랙) | mp3.playLargeFolder(1, 2000) |
| playFromMP3Folder(t) | /mp3 폴더에서 재생 | mp3.playFromMP3Folder(1) |
#include <DIYables_MiniMp3.h>
DIYables_MiniMp3 mp3;
void setup()
{
Serial.begin(9600);
Serial2.begin(9600);
mp3.begin(Serial2);
delay(1000);
mp3.setVolume(20);
Serial.println("=== DIYables Mini Mp3 Player ===");
Serial.println("Commands:");
Serial.println(" 1-9 Play track number");
Serial.println(" + Volume up");
Serial.println(" - Volume down");
Serial.println(" p Pause");
Serial.println(" r Resume");
Serial.println(" s Stop");
Serial.println(" n Next track");
Serial.println(" b Previous track");
Serial.println(" ? Show status");
Serial.println("================================");
}
void loop()
{
if (Serial.available())
{
char cmd = Serial.read();
switch (cmd)
{
case '1': case '2': case '3':
case '4': case '5': case '6':
case '7': case '8': case '9':
Serial.print("Playing track ");
Serial.println(cmd - '0');
mp3.play(cmd - '0');
break;
case '+':
Serial.println("Volume up");
mp3.volumeUp();
break;
case '-':
Serial.println("Volume down");
mp3.volumeDown();
break;
case 'p':
Serial.println("Paused");
mp3.pause();
break;
case 'r':
Serial.println("Resumed");
mp3.resume();
break;
case 's':
Serial.println("Stopped");
mp3.stop();
break;
case 'n':
Serial.println("Next track");
mp3.playNext();
break;
case 'b':
Serial.println("Previous track");
mp3.playPrevious();
break;
case '?':
{
Serial.println("--- Status ---");
int16_t vol = mp3.getVolume();
Serial.print("Volume: ");
Serial.println(vol);
int16_t track = mp3.getCurrentTrack();
Serial.print("Current track: ");
Serial.println(track);
bool playing = mp3.isPlaying();
Serial.print("Playing: ");
Serial.println(playing ? "Yes" : "No");
int16_t total = mp3.getTrackCount();
Serial.print("Total tracks: ");
Serial.println(total);
Serial.println("--------------");
break;
}
default:
break;
}
}
}
| 명령 | 효과 |
| 1–9 | 트랙 재생 |
| + / − | 볼륨 |
| p / r / s | 일시정지 / 재개 / 중지 |
| n / b | 다음 / 이전 |
| ? | 상태 |
| 상수 | ID | 특성 |
| DIYables_MiniMp3::EQ_NORMAL | 0 | 중립 |
| DIYables_MiniMp3::EQ_POP | 1 | 밝음 |
| DIYables_MiniMp3::EQ_ROCK | 2 | 힘참 |
| DIYables_MiniMp3::EQ_JAZZ | 3 | 따뜻함 |
| DIYables_MiniMp3::EQ_CLASSIC | 4 | 균형 |
| DIYables_MiniMp3::EQ_BASS | 5 | 저음 |
mp3.setEQ(DIYables_MiniMp3::EQ_BASS);
이 함수들은 모듈의 응답을 기다리는 동안 최대 100ms 동안 블록됩니다. 응답이 없으면 -1을 반환합니다.
| 함수 | 반환값 | 설명 |
| isPlaying() | bool | 활성 재생 중에는 true |
| getVolume() | int16_t | 현재 볼륨 (0–30) |
| getEQ() | int16_t | 활성 EQ (0–5) |
| getTrackCount() | int16_t | SD의 총 트랙 수 |
| getCurrentTrack() | int16_t | 현재 재생 중인 트랙 번호 |
| getFolderCount() | int16_t | SD의 총 폴더 수 |
| getTrackCountInFolder(f) | int16_t | 폴더 f의 트랙 수 |