본문 바로가기

ESP32

ESP32 SD 카드의 폴더를 PC에서 직접 보이게

반응형

ESP32 데이터 케이블을 사용하여 SD 카드의 폴더를 PC에서 직접 보이게 만드는 것은 가능합니다. 💡

 

다만, 모든 ESP32 모델이 이 기능을 지원하는 것은 아니며, 사용하는 칩의 종류에 따라 구현 방법과 난이도가 크게 달라집니다. 

 

칩 모델별 지원 여부
ESP32 모델지원 여부설명
ESP32-S2 / S3 완전 지원 하드웨어적으로 USB OTG(On-The-Go) 기능을 내장하고 있어, PC에서 일반 USB 메모리(Mass Storage Class)처럼 인식하게 만들 수 있습니다.
ESP32-C3 / C6 제한적 지원 내장된 USB-Serial/JTAG 컨트롤러를 통해 일부 기능을 구현할 수 있으나, S 시리즈만큼 유연하지 않습니다.
ESP32 (Original) 불가능(직접 연결 시) 하드웨어 USB 컨트롤러가 없습니다. 케이블은 'USB-to-Serial' 칩을 거치기 때문에 PC는 이를 저장 장치가 아닌 **통신 포트(COM Port)**로만 인식합니다.

 

구현 방법 (ESP32-S2/S3 기준)
PC에서 SD 카드를 이동식 디스크로 인식시키려면 USB MSC (Mass Storage Class) 기능을 사용해야 합니다.
1. Arduino IDE 설정 🛠️
S3 모델을 사용할 경우, 보드 설정에서 다음 옵션을 활성화해야 합니다:
 
  • USB Mode: USB-OTG (TinyUSB)
  • Upload Mode: USB-OTG CDC (TinyUSB)
2. TinyUSB 라이브러리 활용
Adafruit TinyUSB 라이브러리나 ESP32 Core에 내장된 USB 예제를 사용하여 SD 카드를 마운트할 수 있습니다.
  • 핵심 원리: ESP32가 SD 카드의 데이터를 섹터 단위로 읽어 USB 프로토콜을 통해 PC에 전달합니다.
  • 주의사항: PC와 ESP32가 동시에 SD 카드에 쓰기 작업을 하면 파일 시스템이 깨질 수 있습니다. PC가 연결된 동안은 ESP32의 쓰기 기능을 잠시 멈춰야 합니다.
 
대안: 케이블 연결 없이 폴더 보기 🌐
기존 ESP32(WROOM 등)를 사용 중이라 USB 메모리 방식이 불가능하다면, 네트워크를 이용하는 것이 훨씬 간편합니다.
  • Web Server: ESP32에 웹 서버를 띄워 브라우저(Chrome 등)에서 파일을 다운로드하거나 폴더를 관리할 수 있습니다.
  • FTP Server: FTP 라이브러리를 사용하면 알집이나 FileZilla 같은 프로그램으로 윈도우 탐색기처럼 파일을 관리할 수 있습니다.

 

ESP32-S3를 USB 메모리로 인식시켜도 속도는 약 0.5MB/s ~ 1MB/s 정도로 매우 느립니다. 대용량 파일을 옮기기보다는 설정 파일 수정이나 간단한 로그 확인용으로 적합합니다.  

 

ESP32-S3는 하드웨어 USB 기능을 지원하므로, PC에서 일반 USB 메모리(이동식 디스크)처럼 인식되게 만들어 MP3 파일을 마운트하고 업로드할 수 있습니다.
가장 대중적이고 안정적인 Adafruit TinyUSB 라이브러리를 활용한 예제 코드를 안내해 드립니다.

 

1. 사전 준비 (필수 설정)
Arduino IDE에서 다음 설정을 반드시 확인해야 합니다.
  • 라이브러리 설치: Adafruit TinyUSB Library 설치
  • 보드 설정:
    • Board: ESP32S3 Dev Module (또는 사용 중인 S3 보드)
    • USB Mode: Hardware CDC and JTAG (또는 USB-OTG)
    • Upload Mode: USB-OTG CDC (TinyUSB) 또는 Internal USB

 
2. SD 카드 -> USB 메모리 구현 코드 💾
이 코드를 업로드하면 ESP32-S3를 PC에 연결했을 때 '이동식 디스크'가 나타납니다. 여기에 MP3 파일을 드래그 앤 드롭으로 넣을 수 있습니다.

 

 

#include "SdFat.h"
#include "Adafruit_TinyUSB.h"

// SD 카드 핀 설정 (보드에 맞게 수정하세요)
const int SD_CS_PIN = 5; 

SdFat sd;
Adafruit_USBD_MSC usb_msc;

// USB를 통해 들어오는 읽기 요청 처리
int32_t msc_read_cb(uint32_t lba, void* buffer, uint32_t bufsize) {
  return sd.card()->readSectors(lba, (uint8_t*)buffer, bufsize / 512) ? bufsize : -1;
}

// USB를 통해 들어오는 쓰기 요청 처리 (파일 업로드 시 실행)
int32_t msc_write_cb(uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
  return sd.card()->writeSectors(lba, buffer, bufsize / 512) ? bufsize : -1;
}

// 상태 확인 (PC가 장치를 준비할 때 호출)
void msc_flush_cb(void) {
  sd.card()->syncDevice();
}

void setup() {
  Serial.begin(115200);

  // 1. SD 카드 초기화
  if (!sd.begin(SD_CS_PIN, SD_SCK_MHZ(16))) {
    Serial.println("SD 카드 초기화 실패!");
    return;
  }

  // 2. USB MSC 설정
  usb_msc.setID("ESP32-S3", "SD Card", "1.0");
  usb_msc.setCapacity(sd.card()->sectorCount(), 512);
  usb_msc.setReadWriteCallback(msc_read_cb, msc_write_cb, msc_flush_cb);
  usb_msc.setUnitReady(true);
  usb_msc.begin();

  Serial.println("USB 메모리 모드 시작됨. PC 연결을 확인하세요.");
}

void loop() {
  // USB 처리는 백그라운드에서 실행되므로 루프는 비워두어도 됩니다.
  delay(10); 
}

 

 

⚠️ 주의 사항 및 팁
  • 동시 접근 금지: PC가 USB를 통해 SD 카드에 파일을 쓰고 있을 때, ESP32 내부 코드(Arduino 코드)에서 동시에 SD 카드 파일을 열거나 쓰려고 하면 파일 시스템이 손상(Corrupt)될 수 있습니다.
  • 파일 포맷: SD 카드는 반드시 FAT32 형식으로 포맷되어 있어야 PC에서 정상적으로 인식됩니다.
  • 케이블 체크: 데이터 전송 기능이 있는 데이터 전송용 케이블을 사용해야 합니다 (충전 전용 케이블은 인식 불가).

 

3. MP3 재생 확인용 추가 팁 🎵
파일 업로드 후 ESP32에서 이 파일을 재생하려면 ESP32-audioI2S 라이브러리를 함께 사용하는 것을 추천합니다.
현재 SD 카드의 어떤 핀(CS, MOSI, MISO, SCK)을 사용 중이신가요? 보드마다 핀 번호가 다르므로, 연결이 안 된다면 핀 번호를 알려주세요! 그에 맞춰 코드를 바로 수정해 드릴 수 있습니다.
또한, 파일을 단순히 업로드하는 것 외에 특정 상황에서 재생하는 기능도 필요하신가요? 구체적인 동작 시나리오를 알려주시면 완성된 코드를 만들어 드릴게요.

 

 

ESP32-S3의 내장 USB 기능을 활용하면 별도의 장치 없이 데이터 케이블 하나로 전원 공급(충전)과 USB 메모리 기능을 동시에 구현할 수 있습니다.
PC에 연결했을 때 SD 카드가 이동식 디스크로 나타나게 하려면 Adafruit TinyUSB 라이브러리를 사용하는 것이 가장 효율적입니다.

 

🛠️ 하드웨어 구성 및 준비
1. 연결 방식 (SPI)
일반적인 ESP32-S3 SPI 핀 맵은 다음과 같습니다 (보드 제조사에 따라 다를 수 있으니 확인이 필요합니다).
  • CS: 10
  • MOSI: 11
  • MISO: 13
  • SCK: 12
  • GND/3.3V: 전원 및 접지 연결
2. 라이브러리 설치 (Arduino IDE)
  1. SdFat (by Bill Greiman) 라이브러리 설치
  2. Adafruit TinyUSB Library 라이브러리 설치
3. 보드 설정 (매우 중요 ⚠️)
Arduino IDE의 Tools 메뉴에서 다음을 설정하세요:
  • USB Mode: USB-OTG (TinyUSB)
  • Upload Mode: USB-OTG CDC (TinyUSB)
  • MSC 클래스 활성화: TinyUSB 라이브러리를 선택하면 자동으로 적용됩니다.

 
💻 구현 코드
이 코드는 PC가 SD 카드의 섹터에 직접 접근할 수 있도록 다리를 놓아주는 역할을 합니다.

 

 

#include "SdFat.h"
#include "Adafruit_TinyUSB.h"

// 1. SPI 및 SD 카드 설정
const int SD_CS_PIN = 10; // 자신의 보드 설정에 맞게 수정
SdFat sd;
Adafruit_USBD_MSC usb_msc;

// 2. USB 디스크 상태 및 콜백 함수
bool scsi_ready = false;

// PC가 SD 카드 데이터를 읽을 때 호출
int32_t msc_read_cb(uint32_t lba, void* buffer, uint32_t bufsize) {
  return sd.card()->readSectors(lba, (uint8_t*)buffer, bufsize / 512) ? bufsize : -1;
}

// PC가 SD 카드에 데이터를 쓸 때 호출 (MP3 업로드 시)
int32_t msc_write_cb(uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
  return sd.card()->writeSectors(lba, buffer, bufsize / 512) ? bufsize : -1;
}

// 쓰기 완료 후 데이터 동기화
void msc_flush_cb(void) {
  sd.card()->syncDevice();
}

void setup() {
  Serial.begin(115200);

  // 3. SPI 통신 및 SD 카드 시작
  // S3의 기본 SPI 핀을 사용하거나 지정할 수 있습니다.
  if (!sd.begin(SD_CS_PIN, SD_SCK_MHZ(16))) {
    Serial.println("SD 카드 초기화 실패! 배선을 확인하세요.");
    while (1) delay(1);
  }

  uint32_t block_count = sd.card()->sectorCount();
  Serial.print("SD 카드 연결 성공. 크기: ");
  Serial.print(block_count * 512 / 1024 / 1024);
  Serial.println(" MB");

  // 4. USB MSC(Mass Storage Class) 설정
  usb_msc.setID("ESP32-S3", "SD-Reader", "1.0");
  usb_msc.setCapacity(block_count, 512);
  usb_msc.setReadWriteCallback(msc_read_cb, msc_write_cb, msc_flush_cb);
  usb_msc.setUnitReady(true);
  usb_msc.begin();

  Serial.println("USB 케이블을 통해 PC에서 폴더를 확인할 수 있습니다.");
}

void loop() {
  // USB 처리는 내부 인터럽트로 작동하므로 loop는 비워두어도 됩니다.
  // 나중에 버튼 입력이나 센서 작동 코드를 여기에 넣으세요.
  delay(100);
}

 

 

⚡ 주요 특징 및 주의사항
  • 동시 전원 공급: USB 데이터 케이블로 연결하면 PC로부터 5V 전원을 공급받아 충전회로(보드에 있는 경우)와 ESP32-S3를 동시에 작동시킵니다.
  • 폴더 자동 인식: 코드를 업로드하고 PC에 연결하면 약 2~3초 후 '이동식 디스크'로 팝업이 뜹니다.
  • 충돌 방지: PC가 SD 카드를 점유하고 있을 때 ESP32 코드 내에서 sd.open() 등을 사용하여 파일을 수정하려고 하면 파일 시스템이 깨질 수 있습니다. 파일 업로드 중에는 ESP32가 파일을 건드리지 않도록 주의해야 합니다.
  • 속도: SPI 방식 특성상 초당 약 500KB~1MB 내외의 속도가 나옵니다. MP3 파일 몇 개를 옮기기에는 충분한 속도입니다.

📍 다음 단계 제안:
혹시 업로드한 MP3 파일을 ESP32에서 재생까지 하고 싶으신가요? 그렇다면 I2S DAC(예: MAX98357A) 연결 방법과 재생 라이브러리 사용법을 추가로 알려드릴 수 있습니다. 재생 기능도 필요하신지 말씀해 주세요!

 

 

ESP32-S3와 MAX98357A(I2S DAC)를 연결하여 SD 카드에 저장된 MP3 파일을 재생하는 시스템을 구성해 보겠습니다. 이 시스템은 PC에 연결하면 USB 메모리로 작동하고, 평소에는 MP3 플레이어로 작동합니다.

 

1. 하드웨어 연결 (I2S DAC)
MAX98357A는 디지털 신호를 직접 소리로 바꿔주는 DAC 겸 앰프입니다. ESP32-S3와 다음과 같이 연결하세요.
MAX98357A 핀ESP32-S3 핀설명
LRC (WS) GPIO 45 왼쪽/오른쪽 채널 구분 신호
BCLK (SCK) GPIO 47 데이터 비트 클럭 신호
DIN (SD) GPIO 21 실제 오디오 데이터 신호
VIN 5V USB 전원 사용 권장
GND GND 접지

 
2. 라이브러리 설치
재생을 위해 가장 강력하고 사용하기 쉬운 라이브러리를 설치해야 합니다.
  1. Arduino IDE에서 Library Manager 열기
  2. ESP32-audioI2S (작성자: Wolle / schreibfaul1) 설치

3. 통합 코드 (USB 메모리 + MP3 재생)
이 코드는 USB 메모리 기능 자동 재생 기능을 통합한 코드입니다. SD 카드 루트 폴더에 있는 music.mp3 파일을 재생합니다.
 
#include "SdFat.h"
#include "Adafruit_TinyUSB.h"
#include "Audio.h"

// [1] 핀 설정
const int SD_CS_PIN = 10;
#define I2S_LRC       45
#define I2S_BCLK      47
#define I2S_DOUT      21

// [2] 객체 선언
SdFat sd;
Adafruit_USBD_MSC usb_msc;
Audio audio;

// [3] USB 관련 콜백 함수 (수정 불필요)
int32_t msc_read_cb(uint32_t lba, void* buffer, uint32_t bufsize) {
  return sd.card()->readSectors(lba, (uint8_t*)buffer, bufsize / 512) ? bufsize : -1;
}
int32_t msc_write_cb(uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
  return sd.card()->writeSectors(lba, buffer, bufsize / 512) ? bufsize : -1;
}
void msc_flush_cb(void) { sd.card()->syncDevice(); }

void setup() {
  Serial.begin(115200);

  // 1. SD 카드 초기화
  if (!sd.begin(SD_CS_PIN, SD_SCK_MHZ(16))) {
    Serial.println("SD 초기화 실패!");
    return;
  }

  // 2. USB MSC 설정 (PC 연결용)
  usb_msc.setID("ESP32-S3", "MP3-Player", "1.0");
  usb_msc.setCapacity(sd.card()->sectorCount(), 512);
  usb_msc.setReadWriteCallback(msc_read_cb, msc_write_cb, msc_flush_cb);
  usb_msc.setUnitReady(true);
  usb_msc.begin();

  // 3. 오디오 재생 설정
  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
  audio.setVolume(12); // 볼륨 0~21 설정

  // 4. SD 카드 내 'test.mp3' 파일 재생 시작
  // 실제 파일명에 맞춰 수정하세요 (예: "/music.mp3")
  audio.connecttoFS(SD, "/test.mp3"); 
}

void loop() {
  // 오디오 데이터 처리를 위해 반드시 지속적으로 호출해야 함
  audio.loop();

  // PC에서 파일이 업로드되는 중에는 재생을 잠시 멈추거나 
  // 별도의 제어 로직을 넣을 수 있습니다.
}

// 오디오 재생이 끝났을 때 자동으로 호출되는 함수
void audio_eof_mp3(const char *info){
    Serial.print("재생 종료: ");
    Serial.println(info);
    // 다음 곡을 재생하거나 반복 재생 로직을 여기에 추가하세요.
}
 
🚀 주요 작동 원리
  1. 동시 작동: PC에 데이터 케이블을 꽂으면 윈도우 탐색기에 폴더가 뜹니다. 파일을 복사해 넣은 후, 코드를 수정하여 해당 파일명을 재생하게 하면 됩니다.
  2. 데이터 무결성: PC가 파일을 쓰고 있을 때 오디오 재생이 끊길 수 있습니다. 이는 SD 카드의 대역폭을 공유하기 때문입니다.
  3. 오디오 엔진: audio.loop()가 핵심입니다. 루프 문 안에서 매우 빠르게 실행되면서 SD 카드의 데이터를 DAC로 넘겨줍니다.

 
🛠️ 추가 최적화 팁
  • 파일 목록 재생: sd.openDir()을 사용하여 폴더 내의 모든 MP3 파일을 검색하고 순차적으로 재생하는 리스트 기능을 추가할 수 있습니다.
  • 볼륨 조절: 가변저항(Potentiometer)이나 버튼 두 개를 연결하여 audio.setVolume()을 실시간으로 바꿀 수 있습니다.
  • 파일 전송 시 중지: PC가 연결되었음을 감지(usb_msc.ready())하면 재생을 중지하고 전송에만 집중하게 설정하면 더 안정적입니다.
혹시 버튼을 눌러 다음 곡으로 넘기기 특정 시간에 알람처럼 재생하는 기능 등 원하시는 구체적인 시나리오가 있나요? 말씀해 주시면 코드를 더 고도화해 드릴 수 있습니다.
 

 

 

이 이미지는 다음과 같은 세 가지 핵심 포인트를 강조하고 있습니다:
1. 하드웨어 연결 (Hardware Setup) 🛠️
  • ESP32-S3: 시스템의 두뇌 역할을 하며, 데이터 케이블 하나로 PC와 연결됩니다.
  • SD 카드 슬롯: SPI 방식으로 연결되어 MP3 파일이 저장되는 공간입니다.
  • MAX98357A & 스피커: I2S 통신을 통해 디지털 신호를 고품질 사운드로 출력합니다.
2. 데이터 케이블의 이중 역할 (Dual Function) 🔌
  • 충전 및 전원: 별도의 배터리 없이 케이블 하나로 모든 모듈에 전원을 공급합니다.
  • 데이터 전송: PC에서 ESP32-S3를 일반 USB 메모리로 인식하여 파일을 자유롭게 업로드/다운로드합니다.
3. 소프트웨어 통합 (Software Integration) 💻
  • USB MSC 모드: PC 연결 시 이동식 디스크로 동작하는 모드입니다.
  • MP3 재생 모드: 내장된 오디오 엔진이 SD 카드의 파일을 읽어 실시간으로 재생하는 모습입니다.
반응형

캐어랩 고객 지원

취업, 창업의 막막함, 외주 관리, 제품 부재!

당신의 고민은 무엇입니까? 현실과 동떨어진 교육, 실패만 반복하는 외주 계약, 아이디어는 있지만 구현할 기술이 없는 막막함.

우리는 알고 있습니다. 문제의 원인은 '명확한 학습, 실전 경험과 신뢰할 수 있는 기술력의 부재'에서 시작됩니다.

이제 고민을 멈추고, 캐어랩을 만나세요!

코딩(펌웨어), 전자부품과 디지털 회로설계, PCB 설계 제작, 고객(시장/수출) 발굴과 마케팅 전략으로 당신을 지원합니다.

제품 설계의 고수는 성공이 만든 게 아니라 실패가 만듭니다. 아이디어를 양산 가능한 제품으로!

귀사의 제품을 만드세요. 교육과 개발 실적으로 신뢰할 수 있는 파트너를 확보하세요.

지난 30년 여정, 캐어랩이 얻은 모든 것을 함께 나누고 싶습니다.

카카오 채널 추가하기

카톡 채팅방에서 무엇이든 물어보세요

당신의 성공을 위해 캐어랩과 함께 하세요.

캐어랩 온라인 채널 바로가기

캐어랩