아두이노 나노 ESP32 미니 MP3 플레이어
Arduino Nano ESP32는 내장 WiFi와 Bluetooth를 갖춘 강력한 3.3V 보드입니다. 이 튜토리얼에서는 DIYables 미니 MP3 플레이어 모듈과 페어링하여 완전히 제어 가능한 MP3 플레이어를 구축할 것입니다. 다음 내용을 살펴볼 것입니다:
3.3V 로직 레벨 덕분에 저항 없이 모듈을 Nano ESP32에 연결하기.
올바르게 이름이 지정된 MP3 파일로 SD 카드 준비하기.
트랙 재생, 일시 정지, 재개, 중지 및 건너뛰기 코드 작성하기.
버튼과 시리얼 명령을 통한 볼륨 제어.
트랙 루프, 전체 셔플, 폴더 기반 재생 설정하기.
모듈의 상태 읽기(현재 트랙, 볼륨, 재생 상태).
| 1 | × | 아두이노 나노 ESP32 | 쿠팡 | 아마존 | |
| 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 | × | (추천) 아두이노 나노용 스크루 터미널 확장 보드 | 쿠팡 | 아마존 | |
| 1 | × | (추천) 아두이노 나노용 브레이크아웃 확장 보드 | 쿠팡 | 아마존 | |
| 1 | × | (추천) 아두이노 나노 ESP32용 전원 분배기 | 쿠팡 | 아마존 | |
공개: 이 포스팅 에 제공된 일부 링크는 아마존 제휴 링크입니다. 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
참고: 1K 저항이 필요하지 않습니다 — Nano ESP32는 3.3V 로직을 사용하며, 이는 모듈과 기본적으로 일치합니다.
DIYables 미니 MP3 플레이어는 YX5200-24SS 칩으로 구동되는 독립형 MP3 디코더 모듈입니다. 마이크로 SD 카드에 MP3 파일을 넣고, 작은 스피커를 연결하고, 시리얼 명령을 전송하여 재생을 제어합니다.
모듈은 9600 보드 UART 명령을 받으며 다음 기능을 제공합니다:
전체 재생 제어: 재생, 일시 정지, 재개, 중지, 다음, 이전
31단계 볼륨 (0~30)
6가지 이퀄라이저 프리셋 (일반, 팝, 록, 재즈, 클래식, 베이스)
반복 모드: 단일 트랙 루프, 폴더 루프, 전체 루프, 셔플
분류된 오디오를 위한 폴더 구성 재생
광고 삽입(중단 및 재개)
실시간 상태 쿼리
| Pin | Function |
| VCC | 3.2V~5.0V 전원 공급 |
| GND | 접지 |
| RX | UART 입력 (보드 TX에 연결) |
| TX | UART 출력 (보드 RX에 연결) |
| SPK_1 | 스피커 + (온보드 3W 앰프) |
| SPK_2 | 스피커 − |
| DAC_R | 오른쪽 라인 레벨 출력 |
| DAC_L | 왼쪽 라인 레벨 출력 |
| BUSY | LOW = 재생 중, HIGH = 대기 중 |
| IO_1 | 짧게 누름 → 이전, 길게 누름 → 볼륨 감소 |
| IO_2 | 짧게 누름 → 다음, 길게 누름 → 볼륨 증가 |
Nano ESP32는 3.3V 로직으로 작동합니다 — 미니 MP3 플레이어가 내부적으로 사용하는 것과 동일한 전압입니다. 즉, 저항 없이 TX/RX를 직접 연결할 수 있습니다.
모듈과의 통신을 위해 Nano ESP32에서 Serial1을 사용하여, 기본 Serial을 시리얼 모니터용으로 유지합니다.
| Mini Mp3 Player | Arduino Nano ESP32 | Notes |
| VCC | 3.3V | 필요한 경우 VBUS에서 5V도 허용 |
| GND | GND | |
| RX | TX1 (D5) | 직접 연결 — 저항 불필요 |
| TX | RX1 (D4) | 직접 연결 |
| SPK_1 | Speaker + | |
| SPK_2 | Speaker − | |

이 이미지는 Fritzing을 사용하여 만들어졌습니다. 이미지를 확대하려면 클릭하세요.
모듈에 삽입하기 전에 마이크로 SD 카드를 준비합니다:
FAT16 또는 FAT32로 포맷합니다.
제로 패딩된 이름으로 루트에 MP3 파일을 복사합니다:
/001.mp3
/002.mp3
/003.mp3
폴더 재생의 경우:
/01/001.mp3
/01/002.mp3
/02/001.mp3
기억하세요:
트랙 번호는 1부터 시작합니다(0이 아님).
모듈은 파일 이름이 아닌 복사 순서로 트랙 순서를 결정합니다. 먼저 카드를 포맷한 다음 파일을 순서대로 개별적으로 복사하세요.
폴더 이름: 2자리, 제로 패딩(01–99). 내부 파일 이름: 3자리, 제로 패딩(001–255).
USB-C를 통해 Nano ESP32를 컴퓨터에 연결합니다.
Arduino IDE를 열고, Arduino Nano ESP32를 보드로 선택하고 올바른 포트를 선택합니다.
왼쪽의 Libraries 패널로 이동합니다.
"DIYables_MiniMp3"를 검색하고 DIYables의 라이브러리를 설치합니다.
Install을 클릭합니다.
라이브러리에는 외부 의존성이 없습니다.
Nano ESP32는 하드웨어 시리얼 포트가 있으므로 SoftwareSerial 대신 Serial1을 사용합니다:
#include <DIYables_MiniMp3.h>
DIYables_MiniMp3 mp3;
void setup() {
Serial.begin(115200);
Serial1.begin(9600);
mp3.begin(Serial1);
delay(1000);
mp3.setVolume(25);
}
void loop() {
}
SoftwareSerial 라이브러리가 필요 없습니다! 하드웨어 시리얼이 더 안정적이며, 특히 이 모듈이 사용하는 낮은 9600 보드 속도에서도 그렇습니다.
#include <DIYables_MiniMp3.h>
#include <SoftwareSerial.h>
SoftwareSerial mp3Serial(D10, D11);
DIYables_MiniMp3 mp3;
void setup()
{
Serial.begin(9600);
mp3Serial.begin(9600);
mp3.begin(mp3Serial);
delay(1000);
mp3.setVolume(25);
Serial.println("Playing track 1...");
mp3.play(1);
}
void loop()
{
}
SD 카드에 MP3 파일을 로드하고 모듈에 삽입합니다.
위에 표시된 대로 모듈을 Nano ESP32에 연결합니다(저항 없이!).
USB-C를 통해 보드를 연결하고, Arduino Nano ESP32를 선택하고 업로드합니다.
연결된 스피커를 통해 001.mp3 트랙이 들려야 합니다.
| Method | Purpose | Example |
| play(trackNum) | 특정 트랙 시작 | mp3.play(1) |
| playNext() | 다음 트랙으로 이동 | mp3.playNext() |
| playPrevious() | 이전 트랙으로 이동 | mp3.playPrevious() |
| pause() | 활성 트랙 일시 정지 | mp3.pause() |
| resume() | 트랙 재개 | mp3.resume() |
| stop() | 재생 중지 | mp3.stop() |
#include <DIYables_MiniMp3.h>
#include <SoftwareSerial.h>
SoftwareSerial mp3Serial(D10, D11);
DIYables_MiniMp3 mp3;
int currentTrack = 1;
int totalTracks = 3;
unsigned long lastTrackTime = 0;
unsigned long trackDuration = 5000;
void setup()
{
Serial.begin(9600);
mp3Serial.begin(9600);
mp3.begin(mp3Serial);
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>
#include <SoftwareSerial.h>
SoftwareSerial mp3Serial(D10, D11);
DIYables_MiniMp3 mp3;
const int BUTTON_VOL_UP = D2;
const int BUTTON_VOL_DOWN = D3;
int volume = 15;
void setup()
{
Serial.begin(9600);
mp3Serial.begin(9600);
pinMode(BUTTON_VOL_UP, INPUT_PULLUP);
pinMode(BUTTON_VOL_DOWN, INPUT_PULLUP);
mp3.begin(mp3Serial);
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);
}
}
| Method | Purpose | Example |
| setVolume(v) | 특정 볼륨 레벨로 이동 | mp3.setVolume(20) |
| volumeUp() | 1단계 증가 | mp3.volumeUp() |
| volumeDown() | 1단계 감소 | mp3.volumeDown() |
| getVolume() | 현재 레벨 쿼리 | mp3.getVolume() |
#include <DIYables_MiniMp3.h>
#include <SoftwareSerial.h>
SoftwareSerial mp3Serial(D10, D11);
DIYables_MiniMp3 mp3;
const int BUTTON_NEXT = D2;
const int BUTTON_PREV = D3;
void setup()
{
Serial.begin(9600);
mp3Serial.begin(9600);
pinMode(BUTTON_NEXT, INPUT_PULLUP);
pinMode(BUTTON_PREV, INPUT_PULLUP);
mp3.begin(mp3Serial);
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>
#include <SoftwareSerial.h>
SoftwareSerial mp3Serial(D10, D11);
DIYables_MiniMp3 mp3;
const int BUTTON_PIN = D2;
bool paused = false;
void setup()
{
Serial.begin(9600);
mp3Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
mp3.begin(mp3Serial);
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>
#include <SoftwareSerial.h>
SoftwareSerial mp3Serial(D10, D11);
DIYables_MiniMp3 mp3;
void setup()
{
Serial.begin(9600);
mp3Serial.begin(9600);
mp3.begin(mp3Serial);
delay(1000);
mp3.setVolume(25);
mp3.setEQ(DIYables_MiniMp3::EQ_NORMAL);
Serial.println("Playing track 1 on loop...");
mp3.loopTrack(1);
}
void loop()
{
}
| Method | Purpose | Example |
| loopTrack(t) | 하나의 트랙 계속 반복 | mp3.loopTrack(1) |
| loopFolder(f) | 폴더의 모든 트랙 반복 | mp3.loopFolder(1) |
| loopAll() | 카드의 모든 트랙 반복 | mp3.loopAll() |
| stopLoop() | 현재 반복 모드 종료 | mp3.stopLoop() |
| shuffle() | 재생 순서 무작위화 | mp3.shuffle() |
#include <DIYables_MiniMp3.h>
#include <SoftwareSerial.h>
SoftwareSerial mp3Serial(D10, D11);
DIYables_MiniMp3 mp3;
void setup()
{
Serial.begin(9600);
mp3Serial.begin(9600);
mp3.begin(mp3Serial);
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()
{
}
| Method | Purpose | Example |
| playFolder(f, t) | 폴더 f에서 트랙 t 선택 | mp3.playFolder(1, 1) |
| playLargeFolder(f, t) | 대용량 폴더 모드 (최대 3000 트랙) | mp3.playLargeFolder(1, 1500) |
| playFromMP3Folder(t) | 특수 /mp3 폴더 액세스 | mp3.playFromMP3Folder(1) |
#include <DIYables_MiniMp3.h>
#include <SoftwareSerial.h>
SoftwareSerial mp3Serial(D10, D11);
DIYables_MiniMp3 mp3;
void setup()
{
Serial.begin(9600);
mp3Serial.begin(9600);
mp3.begin(mp3Serial);
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;
}
}
}
| Input | Result |
| 1–9 | 해당 트랙 재생 |
| + / − | 볼륨 증가 / 감소 |
| p | 일시 정지 |
| r | 재개 |
| s | 중지 |
| n | 다음 트랙 |
| b | 이전 트랙 |
| ? | 상태 표시 |
| Constant | ID | Tone |
| 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_POP);
각 쿼리는 최대 100ms 동안 블록됩니다. 타임아웃 시 −1을 반환합니다.
| Method | Returns | Info |
| isPlaying() | bool | 트랙이 활성 상태인지 여부 |
| getVolume() | int16_t | 볼륨 (0–30) |
| getEQ() | int16_t | EQ 프리셋 (0–5) |
| getTrackCount() | int16_t | 카드의 총 트랙 수 |
| getCurrentTrack() | int16_t | 현재 재생 중인 트랙 |
| getFolderCount() | int16_t | 폴더 수 |
| getTrackCountInFolder(f) | int16_t | 폴더 f의 트랙 수 |