Arduino의 ESP32 I2S 버그??

4068 단어 ArduinoESP32I2S
ESP32를 I2S 경유로 외부 DAC와 연결하고, Arduino IDE로 쓴 코드로 예상대로 소리가 나지 않는(더러운 소리가 나오는) 상황이었으므로 조사해 보았다.

Arduino IDE에서 ESP32 사용



Arduino IDE : 1.8.15
ESP32 플랫폼: 1.0.6
그리고 현재로서는 최신이어야합니다.

ESP32를 I2S를 통해 외부 DAC에 연결



ESP32에서 I2S 인터페이스 (BCLK, DOUT, LRCK 또는 이름을 SCLK, SD, WS)를 외부 DAC (PCM5102)로 연결합니다. 16bit 이상의 해상도로 울리고 싶었던 것이다. ESP32 내장 DAC는 해상도 8bit 밖에 없기 때문이다.

풀 스윙의 사인파 소리가 왜곡됩니다.



16bit분, 즉 -32768~+32767 (0x08000~0x07fff; I2S는 signed int로 표현한다) 눈 가득 흔들리는 정현파를 생성시켰는데, 소리가 더럽다. PCM5102인데?
출력 레벨이 높고, 머리와 다리가 끊어졌을지도 모르기 때문에, 간이 오실로로 보면, 아래와 같이 되어 있었다.

이 파형은 그러한 왜곡 방법이 아닙니다. unsigned/signed를 잘못 했습니까? 라고 생각했지만 그렇지 않았다. 좌우 채널의 소리가 다르고 다른 쪽에서는 다른 고조파 같은 것이 들리고 있다. 이것은 전송 데이터를 끌어 올리는 것일지도 모른다.

사실은 ↓ 같은 파형을 기대하고 있는데.


I2S의 신호가 어떻게 되었는지 로직 애널라이저로 확인한다.



확인을 위해 왼쪽 채널에 1(0x0001), 오른쪽 채널에 2(0x0002)를 출력시켜 보았다.
사용한 코드는 아래. GPIO 25, 26, 27 번 핀을 외부 DAC의 DIN, LRCK, BCLK에 연결한다.
#include <driver/i2s.h>
#define I2S_BCLK  27 
#define I2S_LRCK  26
#define I2S_DOUT  25
#define I2S_SAMPLE_RATE     44100
uint16_t wave[2] ;
static const i2s_port_t i2s_num = I2S_NUM_0 ; // i2s port number
static const i2s_pin_config_t pin_config = {
    .bck_io_num   = I2S_BCLK,
    .ws_io_num    = I2S_LRCK,
    .data_out_num = I2S_DOUT,
    .data_in_num  = I2S_PIN_NO_CHANGE
};
static const i2s_config_t i2s_config = {
    .mode                 = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_TX),
    .sample_rate          = I2S_SAMPLE_RATE,
    .bits_per_sample      = I2S_BITS_PER_SAMPLE_16BIT,
    .channel_format       = I2S_CHANNEL_FMT_RIGHT_LEFT,
    .communication_format = I2S_COMM_FORMAT_I2S_MSB,
    .intr_alloc_flags     = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count        = 4,
    .dma_buf_len          = 1024,
    .use_apll             = false,
    .tx_desc_auto_clear   = true
};
void setup() {
  i2s_driver_install(i2s_num, &i2s_config, 0, NULL);
  i2s_set_pin(i2s_num, &pin_config);
  i2s_zero_dma_buffer(i2s_num);
  wave[0] = 0x0001 ; // Lch 
  wave[1] = 0x0002 ; // Rch 
}

void loop() {
  size_t written ;
  i2s_write(I2S_NUM_0, wave, sizeof(wave), &written, portMAX_DELAY) ;
}

wave[]가 출력하는 값이다. 이 경우, 정수치를 계속 내기 때문에 「파」는 되지 않고 소리는 울리지 않지만 I2S상은 어디에서 캡쳐해도 같은 값을 취할 것.



왼쪽 채널, 오른쪽 채널 모두 값이 2배로 되어 있다. LSB의 위치가 이상해 보인다.
본래의 I2S의 규격이라면 또 1 클락 오른쪽에 LSB 가 올 것이다. 예를 들어, 왼쪽 채널의 LSB는 LRCK의 상승 에지의 다음 BCLK에서 출력되어야 한다.

By wdwd - Own work, CC BY 3.0 , 링크

(WIKIPEDIA에서 인용)

결론



MSB도 본래의 위치보다 1클럭 왼쪽으로 출력되고 있었다. DOUT (SD)는 전체적으로 1clock 이른 것이다. 즉 LRCK (WS)가 1 clock 느린 것이다.

버그?



ESP32의 Errata는 그렇게 말하지 않았기 때문에 하드웨어가 아닌 라이브러리에 문제가있을 수 있습니다.
ESP32-IDF는 사용하지 않으므로 알 수 없지만 Arduino IDE i2s.h ("C:\Users\%USER%\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\tools\sdk\include\driver\driver\i2s.h")를 보면 2016년이라든가 되어 있기 때문에, 혹시 Arduino의 ESP32 SDK 환경만은 낡을지도 모른다.

좋은 웹페이지 즐겨찾기