ESP32 + I2S - Immer nur Brummen zu hören

OP #7883922
Lesenswert?

Hallo,

ich habe mir einen esp32 gekauft weil ich damit ein kleines Synthesizer-Projekt basteln wollte. Leider scheitert es aber schon an der Sound-Ausgabe.

Ich hab als DA einen PCM5102A gekauft. Zudem hab ich noch zwei MAX98357A. Immer nur ein DA angeschlossen. Das ganze über I2S. Ich habe mir von der ESP-IDF das Beispiel heruntergeladen und programmiert.

Mein Problem ist jetzt: Egal was ich ausprobiere, ich höre immer nur Brummen. Nicht immer das gleiche Brummen, hört sich oft unterschiedlich an.

Was ich schon ausprobiert habe:

  • Andere GPIO benutzt
  • Anderen ESP32 benutzt
  • Alle 3 DA, die ich habe, ausprobiert. Beim MAX98357A kann ich nur Messen was rauskommt, da messe ich immer über 1Mhz obwohl ich ein 440Hz Sinus via Code ausgebe.
  • Alles zigmal geprüft ob Kontakt vorhanden ist
  • Zigmal geprüft ob nicht irgendwo ein Kurzschluss ist
  • Mir von ChatGPT mehrere Versionen programmieren lassen
  • Stromversorgung über Steckbrett-Netzteil
  • Arduino probiert, da war gar nichts zu hören

Egal was ich mache, es brummt. Es ist wie verhext. Hat jemand eine Idee? Ich bin mit meinen Ideen am Ende. Schon mal vielen Dank im Voraus!

Gruß Alex

1
/*
2
 * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
3
 *
4
 * SPDX-License-Identifier: Unlicense OR CC0-1.0
5
 */
6

7
#include <stdint.h>
8
#include <stdlib.h>
9
#include "freertos/FreeRTOS.h"
10
#include "freertos/task.h"
11
#include "driver/i2s_std.h"
12
#include "driver/gpio.h"
13
#include "esp_check.h"
14
#include "sdkconfig.h"
15
#include "i2s_example_pins.h"
16
#include <math.h>
17

18

19
/* Set 1 to allocate rx & tx channels in duplex mode on a same I2S controller, they will share the BCLK and WS signal
20
 * Set 0 to allocate rx & tx channels in simplex mode, these two channels will be totally separated,
21
 * Specifically, due to the hardware limitation, the simplex rx & tx channels can't be registered on the same controllers on ESP32 and ESP32-S2,
22
 * and ESP32-S2 has only one I2S controller, so it can't allocate two simplex channels */
23
#define EXAMPLE_I2S_DUPLEX_MODE         CONFIG_USE_DUPLEX
24

25
#define EXAMPLE_STD_BCLK_IO1        EXAMPLE_I2S_BCLK_IO1      // I2S bit clock io number
26
#define EXAMPLE_STD_WS_IO1          EXAMPLE_I2S_WS_IO1      // I2S word select io number
27
#define EXAMPLE_STD_DOUT_IO1        EXAMPLE_I2S_DOUT_IO1     // I2S data out io number
28
#define EXAMPLE_STD_DIN_IO1         EXAMPLE_I2S_DIN_IO1     // I2S data in io number
29
#if !EXAMPLE_I2S_DUPLEX_MODE
30
#define EXAMPLE_STD_BCLK_IO2        EXAMPLE_I2S_BCLK_IO2     // I2S bit clock io number
31
#define EXAMPLE_STD_WS_IO2          EXAMPLE_I2S_WS_IO2     // I2S word select io number
32
#define EXAMPLE_STD_DOUT_IO2        EXAMPLE_I2S_DOUT_IO2     // I2S data out io number
33
#define EXAMPLE_STD_DIN_IO2         EXAMPLE_I2S_DIN_IO2     // I2S data in io number
34
#endif
35

36
#define EXAMPLE_BUFF_SIZE               2048
37
#define SAMPLE_RATE 22050
38

39
static i2s_chan_handle_t                tx_chan;        // I2S tx channel handler
40
static i2s_chan_handle_t                rx_chan;        // I2S rx channel handler
41

42
static void i2s_example_read_task(void *args)
43
{
44
    uint8_t *r_buf = (uint8_t *)calloc(1, EXAMPLE_BUFF_SIZE);
45
    assert(r_buf); // Check if r_buf allocation success
46
    size_t r_bytes = 0;
47

48
    /* Enable the RX channel */
49
    ESP_ERROR_CHECK(i2s_channel_enable(rx_chan));
50

51
    /* ATTENTION: The print and delay in the read task only for monitoring the data by human,
52
     * Normally there shouldn't be any delays to ensure a short polling time,
53
     * Otherwise the dma buffer will overflow and lead to the data lost */
54
    while (1) {
55
        /* Read i2s data */
56
        if (i2s_channel_read(rx_chan, r_buf, EXAMPLE_BUFF_SIZE, &r_bytes, 1000) == ESP_OK) {
57
            printf("Read Task: i2s read %d bytes\n-----------------------------------\n", r_bytes);
58
            printf("[0] %x [1] %x [2] %x [3] %x\n[4] %x [5] %x [6] %x [7] %x\n\n",
59
                   r_buf[0], r_buf[1], r_buf[2], r_buf[3], r_buf[4], r_buf[5], r_buf[6], r_buf[7]);
60
        } else {
61
            printf("Read Task: i2s read failed\n");
62
        }
63
        vTaskDelay(pdMS_TO_TICKS(200));
64
    }
65
    free(r_buf);
66
    vTaskDelete(NULL);
67
}
68

69
static void i2s_example_write_task(void *args)
70
{
71
    uint8_t *w_buf = (uint8_t *)calloc(1, EXAMPLE_BUFF_SIZE);
72
    assert(w_buf); // Check if w_buf allocation success
73

74
    for (int i = 0; i < EXAMPLE_BUFF_SIZE / 2; i++) {
75
        float phase = (2.0f * M_PI * i) / (SAMPLE_RATE / 220);
76
        int16_t sample = (int16_t)(127 * sinf(phase));
77
        w_buf[i] = sample;  // Kein MSB nötig bei 8 Bit
78
        w_buf[2 * i + 1] = (sample >> 8) & 0xFF; // MSB
79
}
80

81

82
    size_t w_bytes = EXAMPLE_BUFF_SIZE;
83

84
    /* (Optional) Preload the data before enabling the TX channel, so that the valid data can be transmitted immediately */
85
    while (w_bytes == EXAMPLE_BUFF_SIZE) {
86
        /* Here we load the target buffer repeatedly, until all the DMA buffers are preloaded */
87
        ESP_ERROR_CHECK(i2s_channel_preload_data(tx_chan, w_buf, EXAMPLE_BUFF_SIZE, &w_bytes));
88
    }
89

90
    /* Enable the TX channel */
91
    ESP_ERROR_CHECK(i2s_channel_enable(tx_chan));
92
    while (1) {
93
        /* Write i2s data */
94
        if (i2s_channel_write(tx_chan, w_buf, EXAMPLE_BUFF_SIZE, &w_bytes, 1000) == ESP_OK) {
95
            printf("Write Task: i2s write %d bytes\n", w_bytes);
96
        } else {
97
            printf("Write Task: i2s write failed\n");
98
        }
99
        vTaskDelay(pdMS_TO_TICKS(200));
100
    }
101
    free(w_buf);
102
    vTaskDelete(NULL);
103
}
104

105
static void i2s_example_init_std_simplex(void)
106
{
107
    /* Setp 1: Determine the I2S channel configuration and allocate two channels one by one
108
     * The default configuration can be generated by the helper macro,
109
     * it only requires the I2S controller id and I2S role
110
     * The tx and rx channels here are registered on different I2S controller,
111
     * Except ESP32 and ESP32-S2, others allow to register two separate tx & rx channels on a same controller */
112
    i2s_chan_config_t tx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
113
    ESP_ERROR_CHECK(i2s_new_channel(&tx_chan_cfg, &tx_chan, NULL));
114
    i2s_chan_config_t rx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
115
    ESP_ERROR_CHECK(i2s_new_channel(&rx_chan_cfg, NULL, &rx_chan));
116

117
    /* Step 2: Setting the configurations of standard mode and initialize each channels one by one
118
     * The slot configuration and clock configuration can be generated by the macros
119
     * These two helper macros is defined in 'i2s_std.h' which can only be used in STD mode.
120
     * They can help to specify the slot and clock configurations for initialization or re-configuring */
121

122
     
123

124

125
i2s_std_config_t std_cfg = {
126
    .clk_cfg = {
127
        .sample_rate_hz = SAMPLE_RATE,
128
        .clk_src = I2S_CLK_SRC_DEFAULT,
129
        .mclk_multiple = I2S_MCLK_MULTIPLE_256
130
    },
131
   .slot_cfg = {
132
    .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT,
133
    .slot_bit_width = I2S_SLOT_BIT_WIDTH_16BIT,
134
    .slot_mode = I2S_SLOT_MODE_STEREO,
135
    .slot_mask = I2S_STD_SLOT_BOTH,
136
    .ws_width = I2S_DATA_BIT_WIDTH_16BIT,
137
    .ws_pol = false,
138
    .bit_shift = true,
139
    .msb_right = false
140
    },
141
    .gpio_cfg = {
142
        .mclk = I2S_GPIO_UNUSED,
143
        .bclk = GPIO_NUM_5,
144
        .ws   = GPIO_NUM_25,
145
        .dout = GPIO_NUM_26,
146
        .din  = I2S_GPIO_UNUSED,
147
        .invert_flags = {
148
            .mclk_inv = false,
149
            .bclk_inv = false,
150
            .ws_inv   = false
151
        }
152
    }
153
};
154

155
   ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &std_cfg));
156

157

158
    i2s_std_config_t rx_std_cfg = {
159
        .clk_cfg  = I2S_STD_CLK_DEFAULT_CONFIG(22050),
160
        .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO),
161
        .gpio_cfg = {
162
            .mclk = I2S_GPIO_UNUSED,    // some codecs may require mclk signal, this example doesn't need it
163
            .bclk = EXAMPLE_STD_BCLK_IO2,
164
            .ws   = EXAMPLE_STD_WS_IO2,
165
            .dout = EXAMPLE_STD_DOUT_IO2,
166
            .din  = EXAMPLE_STD_DIN_IO2,
167
            .invert_flags = {
168
                .mclk_inv = false,
169
                .bclk_inv = false,
170
                .ws_inv   = false,
171
            },
172
        },
173
    };
174
    /* Default is only receiving left slot in mono mode,
175
     * update to right here to show how to change the default configuration */
176
    rx_std_cfg.slot_cfg.slot_mask = I2S_STD_SLOT_RIGHT;
177
    ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_chan, &rx_std_cfg));
178
}
179

180

181
extern "C" void app_main(void)
182
{
183
#if EXAMPLE_I2S_DUPLEX_MODE
184
    i2s_example_init_std_duplex();
185
#else
186
    i2s_example_init_std_simplex();
187
#endif
188

189
    /* Step 3: Create writing and reading task, enable and start the channels */
190
    xTaskCreate(i2s_example_read_task, "i2s_example_read_task", 4096, NULL, 5, NULL);
191
    xTaskCreate(i2s_example_write_task, "i2s_example_write_task", 4096, NULL, 5,
OP #7884053
Lesenswert?

Ok entschuldigt wegen dem längeren Source-Code. Kann es jetzt leider nicht mehr ändern. Werde nächstes Mal dran denken!

Ein Oszilloskop habe ich noch nicht verwendet weil UPS es nicht schafft es zu liefern. Aber am Montag hole ich es ab und dann werde ich es mir darauf mal ansehen. Werde berichten!

Gruß Alex

OP #7884689
Lesenswert?

Ok es lag anscheinend an dem Steckbrett und auch an den Kabeln. Jetzt mit anderen Kabeln und ohne Steckbrett funktioniert es.

Ich musste allerdings noch einige Stunden rumbasteln bis dann auch ein Ton herauskam. Mit dem Beispiel von ESP-IDF hörte ich nichts. Habs es aber irgendwie hinbekommen das ein Ton zu hören ist. Keine Ahnung wie aber Hauptsache es geht jetzt weiter.

Ich hänge den Quellcode an für andere die auch da vielleicht auch drüber stolpern. Der Code ist für die Kombi ESP32 + PCM5102A

Gruß Alex

Update: Hab dem Code noch unnötige Zeilen entfernt. Weiß leider nicht wie das andere File entfernen kann. Nehmt den kleineren Quellcode, das ist der neue.

Angehängte Dateien:
#7885132
Lesenswert?

Thorsten S. schrieb:

Wer löten gelernt hat, braucht keine Frickelbretter.

So kann man das auch formulieren. Zwar habe ich ein Frickelbrett (das war mal irgendwoe mit dabei), aber ich habe schon Jahrzehnte vorher gelötet.

So sah das bei mir in der Anfangszeit aus:: Beitrag "Re: Basteln für Alt und Jung"

Man kann aber das Frickelbrett auch als Chance begreifen. Als Chance, zu verstehen, warum man Löten lernen sollte.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren