Closed cicciocb closed 2 years ago
PTAL, @PilnyTomas.
relates to: https://github.com/espressif/esp-idf/issues/7684
It did work until V2.0.0-rc2
Do you have news for this @PilnyTomas ?
Hi, sorry for the late response - I was working on other tasks. I can confirm that in version 2.0.1 and newer it doesn't work and that version 2.0.0. does work. I will investigate to pinpoint the breaking commit and find the reason for this issue.
I found the braking commit, from Oct 1, 2021: 00214d5c2a1c2b1904f2caf6f0d5ddfe952331ff
We are now discussing the issue with ESP-IDF team, we will let you know about the update.
Maybe this https://www.esp32.com/viewtopic.php?t=6025
I did some more tests, on ESP32 Rev1 and Pico D4. Actually the DAC output works, but the speed is 11x more than real time. I.e. I sent PCM at 16K samples/s, and it was played at ~176K samples/s.
Original waveform is 660ms long
The signal recorded on GPIO26 is playing in 60ms
Maybe this could be related to ? https://github.com/espressif/esp-idf/commit/1d02e638bd05b80d6fd648d51c14a8ecd6c2dbdc
I doubt. I did some detour on i2s_hal_tx_clock_config()
to check what clock values were calculated, and force-injected some different clock values until the sound was good again. I will work backwards to see why these values are wrong in the first place.
@s-hadinger What is the version of the arduino core that you are using?
I use 2.0.2 with IDF 4.4. I believe the problem is in idf, not Arduino Core.
One highly possible cause is that the calculated mclk_div
is 1250 when using 16000Hz audio on DAC. I'm not sure yet what are the values of a
and b
divider, but I realize now that mclk_div
is 8-bit long. 1250 is clearly an overflow.
Values calculated by IDF 4.4 for 16000Hz audio, DAC, 2 channels
sclk=160000000 mclk=128000 bclk=64000 mclk_div=1250 bclk_div=2
Hardware registers:
union {
struct {
uint32_t clkm_div_num: 8;
uint32_t clkm_div_b: 6;
uint32_t clkm_div_a: 6;
uint32_t clk_en: 1;
uint32_t clka_en: 1;
uint32_t reserved22: 10;
};
uint32_t val;
} clkm_conf;
The overflow may explain why I got random results, and why I only could get something to work by increasing bclk_div
Edit: for information, bclk_div
uses 6 bits
uint32_t tx_bck_div_num: 6;
uint32_t rx_bck_div_num: 6;
Edit2: 1250 (0x4E2) would be truncated to 226 (0xE2) which could explain why the playback was 11x times the normal rate.
I have now confirmation. For 16000Hz, 2 channels, internal DAC is 8 bits.
Knowing that the sclk
is 160MHz
esp-idf
set the following mclk_div=1250
and bclk_div=2
which makes an overall divider around at 1250*2 = 2500, i.e. a bit frequency of 160000000/2500 = 64000 bps. But the problem is that mclk
is overflowing the 8 bits.
My working version sets: mclk_div=156
, bclk_div=32
, so the overall divider is 15632 = 4992. So the bit frequency is 160000000/4992 = 32051 bps, which is in line with 16000 2 (for 2 channels).
I'm still unclear whether a and b factors have an influence.
I opened a new issue with these information https://github.com/espressif/esp-idf/issues/8326
Recompiling esp-idf with the fix above(thanks @Jason2866) makes Audio DAC working again.
Here are the new values computed:
sclk=160000000 mclk=1024000 bclk=32000 mclk_div=156 bclk_div=32
The framework with the idf i2s fix is here if anyone wants to try.
There are some different sdkconfig settings choosen to optimize for our needs.
The build can directly used with platformio using platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.2/platform-tasmota-espressif32-2.0.2.zip
@Jason2866 Thanks for your framework but what is exactly the fix done inside the idf? Thanks
Not sure to understand your question. The proposed fixed was shared with idf team yesterday. Jason backported this fix into a custom version of IDF4.4.
This is the one we're using in Tasmota and proved to fix the Audio DAC issue described earlier.
@s-hadinger Thanks for your answer, I found the fix that is here https://github.com/espressif/esp-idf/pull/8327/files
@Jason2866 I tried but I still have the same issue, works well with external DAC or PDM but not with the internal DAC @s-hadinger Could you publish the source code that you are using for the test?
@cicciocb Used with Tasmota ;-) Are you sure you have used latest version?
To be sure you have to delete the hidden folder .platformio
@Jason2866 Yes, unfortunately I'm sure, it works rolling back to a previous version. Could you just publish your test case?
@cicciocb You can use this setup https://github.com/arendst/Tasmota/pull/12795
@Jason2866 Still not working, at least for me. Maybe someone else could confirm if working or not
@cicciocb Can you publish your test case?
Fixed, will be available in 2.0.3 release. Related fix https://github.com/espressif/esp-idf/issues/8326.
@cicciocb Wil you be able to retest this with v2.0.3-RC1? It should be already fixed :) Thank you.
Closing as solved, if you still face problems, please reopen this.
This is still broken (I2S using I2S_MODE_DAC_BUILT_IN) - it still does not work for Arduino ESP32 core v. 2.0.3
This is still broken (I2S using I2S_MODE_DAC_BUILT_IN) - it still does not work for Arduino ESP32 core v. 2.0.3
@pjmi1 Please open a new issue with specifications for your problem. Please include a complete sketch that demonstrates the issue.
I can confirm this is still broken in Arduino 2.0.4, IDF 4.4.1
Not sure why we need to open a new bug for this @PilnyTomas?
Here is the sketch I used. If I change from internal DAC to PDM it works although really noisy.
// Arduino Zero / Feather M0 I2S audio tone generation example.
// Author: Tony DiCola
//
// Connect an I2S DAC or amp (like the UDA1334A) to the Arduino Zero
// and play back simple sine, sawtooth, triangle, and square waves.
// Makes your Zero sound like a NES!
//
// NOTE: The I2S signal generated by the Zero does NOT have a MCLK /
// master clock signal. You must use an I2S receiver that can operate
// without a MCLK signal (like the UDA1334A).
//
// For an Arduino Zero / Feather M0 connect it to you I2S hardware as follows:
// - Digital 0 -> I2S LRCLK / FS (left/right / frame select clock)
// - Digital 1 -> I2S BCLK / SCLK (bit / serial clock)
// - Digital 9 -> I2S DIN / SD (data output)
// - Ground
//
// Released under a MIT license: https://opensource.org/licenses/MIT
//modified for M5Stack Gray Core
#include <M5Stack.h>
#include <driver/i2s.h>
#define SPEAKER_I2S_NUMBER I2S_NUM_0
#define SAMPLERATE_HZ 44100 // The sample rate of the audio. Higher sample rates have better fidelity,
// but these tones are so simple it won't make a difference. 44.1khz is
// standard CD quality sound.
#define AMPLITUDE ((1<<31)-1) // Set the amplitude of generated waveforms. This controls how loud
// the signals are, and can be any value from 0 to 2**31 - 1. Start with
// a low value to prevent damaging speakers!
#define WAV_SIZE 256 // The size of each generated waveform. The larger the size the higher
// quality the signal. A size of 256 is more than enough for these simple
// waveforms.
// Define the frequency of music notes (from http://www.phy.mtu.edu/~suits/notefreqs.html):
#define C4_HZ 261.63
#define D4_HZ 293.66
#define E4_HZ 329.63
#define F4_HZ 349.23
#define G4_HZ 392.00
#define A4_HZ 440.00
#define B4_HZ 493.88
// Define a C-major scale to play all the notes up and down.
float scale[] = { C4_HZ, D4_HZ, E4_HZ, F4_HZ, G4_HZ, A4_HZ, B4_HZ, A4_HZ, G4_HZ, F4_HZ, E4_HZ, D4_HZ, C4_HZ };
// Store basic waveforms in memory.
int32_t sine[WAV_SIZE] = {0};
int32_t sawtooth[WAV_SIZE] = {0};
int32_t triangle[WAV_SIZE] = {0};
int32_t square[WAV_SIZE] = {0};
size_t writeSize;
// Create I2S audio transmitter object.
//Adafruit_ZeroI2S i2s;
#define Serial Serial
void generateSine(int32_t amplitude, int32_t* buffer, uint16_t length) {
// Generate a sine wave signal with the provided amplitude and store it in
// the provided buffer of size length.
for (int i=0; i<length; ++i) {
buffer[i] = int32_t(float(amplitude)*sin(2.0*PI*(1.0/length)*i));
}
}
void generateSawtooth(int32_t amplitude, int32_t* buffer, uint16_t length) {
// Generate a sawtooth signal that goes from -amplitude/2 to amplitude/2
// and store it in the provided buffer of size length.
float delta = float(amplitude)/float(length);
for (int i=0; i<length; ++i) {
buffer[i] = -(amplitude/2)+delta*i;
}
}
void generateTriangle(int32_t amplitude, int32_t* buffer, uint16_t length) {
// Generate a triangle wave signal with the provided amplitude and store it in
// the provided buffer of size length.
float delta = float(amplitude)/float(length);
for (int i=0; i<length/2; ++i) {
buffer[i] = -(amplitude/2)+delta*i;
}
for (int i=length/2; i<length; ++i) {
buffer[i] = (amplitude/2)-delta*(i-length/2);
}
}
void generateSquare(int32_t amplitude, int32_t* buffer, uint16_t length) {
// Generate a square wave signal with the provided amplitude and store it in
// the provided buffer of size length.
for (int i=0; i<length/2; ++i) {
buffer[i] = -(amplitude/2);
}
for (int i=length/2; i<length; ++i) {
buffer[i] = (amplitude/2);
}
}
void playWave(int32_t* buffer, uint16_t length, float frequency, float seconds) {
// Play back the provided waveform buffer for the specified
// amount of seconds.
// First calculate how many samples need to play back to run
// for the desired amount of seconds.
uint32_t iterations = seconds*SAMPLERATE_HZ;
// Then calculate the 'speed' at which we move through the wave
// buffer based on the frequency of the tone being played.
float delta = (frequency*length)/float(SAMPLERATE_HZ);
// Now loop through all the samples and play them, calculating the
// position within the wave buffer for each moment in time.
for (uint32_t i=0; i<iterations; ++i) {
uint16_t pos = uint32_t(i*delta) % length;
int32_t sample = buffer[pos];
// Duplicate the sample so it's sent to both the left and right channel.
// It appears the order is right channel, left channel if you want to write
// stereo sound.
i2s_write(SPEAKER_I2S_NUMBER, &sample, sizeof(sample), &writeSize, portMAX_DELAY);
}
}
void setup() {
// Configure serial port.
Serial.begin(115200);
Serial.printf("ESP-IDF Version %d.%d.%d \r\n", ESP_IDF_VERSION_MAJOR, ESP_IDF_VERSION_MINOR, ESP_IDF_VERSION_PATCH);
Serial.printf("Ardunio Version %d.%d.%d \r\n", ESP_ARDUINO_VERSION_MAJOR, ESP_ARDUINO_VERSION_MINOR, ESP_ARDUINO_VERSION_PATCH);
M5.begin(true, true, true, true);
Serial.println("Audio Tone Generator");
// Initialize the I2S transmitter.
esp_err_t err = ESP_OK;
//i2s_driver_uninstall(SPEAKER_I2S_NUMBER);
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN),
.sample_rate = SAMPLERATE_HZ ,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // is fixed at 12bit, stereo, MSB
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S,
.intr_alloc_flags = 0,
.dma_buf_count = 2,
.dma_buf_len = 256
};
i2s_config.use_apll = false;
i2s_config.tx_desc_auto_clear = true;
err += i2s_driver_install(SPEAKER_I2S_NUMBER, &i2s_config, 0, NULL);
i2s_pin_config_t tx_pin_config;
tx_pin_config.mck_io_num = 0;
tx_pin_config.bck_io_num = 12;
tx_pin_config.ws_io_num = 13;
tx_pin_config.data_out_num = 15;
tx_pin_config.data_in_num = 34;
err += i2s_set_pin(SPEAKER_I2S_NUMBER, NULL);
err += i2s_set_clk(SPEAKER_I2S_NUMBER, SAMPLERATE_HZ, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO);
// Generate waveforms.
generateSine(AMPLITUDE, sine, WAV_SIZE);
generateSawtooth(AMPLITUDE, sawtooth, WAV_SIZE);
generateTriangle(AMPLITUDE, triangle, WAV_SIZE);
generateSquare(AMPLITUDE, square, WAV_SIZE);
}
void loop() {
Serial.println("Sine wave");
for (int i=0; i<sizeof(scale)/sizeof(float); ++i) {
// Play the note for a quarter of a second.
playWave(sine, WAV_SIZE, scale[i], 0.25);
// Pause for a tenth of a second between notes.
delay(100);
}
Serial.println("Sawtooth wave");
for (int i=0; i<sizeof(scale)/sizeof(float); ++i) {
// Play the note for a quarter of a second.
playWave(sawtooth, WAV_SIZE, scale[i], 0.25);
// Pause for a tenth of a second between notes.
delay(100);
}
Serial.println("Triangle wave");
for (int i=0; i<sizeof(scale)/sizeof(float); ++i) {
// Play the note for a quarter of a second.
playWave(triangle, WAV_SIZE, scale[i], 0.25);
// Pause for a tenth of a second between notes.
delay(100);
}
Serial.println("Square wave");
for (int i=0; i<sizeof(scale)/sizeof(float); ++i) {
// Play the note for a quarter of a second.
playWave(square, WAV_SIZE, scale[i], 1.0);
// Pause for a tenth of a second between notes.
//delay(1);
delay(100);
}
}
Hi @ifrew I tried your code and it takes 110 seconds to generate that 0.25sec tone. Please try improving tone generation.
@PilnyTomas It isn't actually my code, I was just using an example I found to show the potential issue. However, I did find the issue in the example. as I stated in #6856. Thanks for getting back though.
I have tried IDF example and the output is very laggy, so I opened an issue for the IDF team https://github.com/espressif/esp-idf/issues/9389
The esp32 I2s internal DAC output is NOT working with the release 2.0.5
I tested yesterday the last Board Manager release 2.0.5 and a sketch to generate a sinus signal with I2S and the internal DAC output. Same result: Not Working!
HW: Adafruit ESP32 feather and an oscilloscope
With the Board Manager 2.0.0 the sketch works but all the Board Manager > 2.0.0 have same bug
Is there any work around?
Note: I discovered the bug trying to evaluate the Adafruit ESP32 feather V2. You need to upgrade the Board Manager to 2.0.4 Same issue is shown in both boards Adafruit ESP32 feather and Adafruit ESP32 feather V2
@cicciocb, @ifrew, @pjmi1, can you please try this sketch if it works for you? It does for me.
this sketch https://github.com/PilnyTomas/issues/blob/4b5315b5547165c9f080fd3e993dce24bf0fe7bf/issue_7252B/issue_7252B.ino is also working for me
But:
.use_apll = 1
produces sporadic glitches with the Arduino Board Manager 2.0.5 . See: https://github.com/espressif/esp-idf/issues/9321
Alternatives:
.use_apll = 0 (For my application is fine)
or
Arduino Board Manager 1.0.6 .use_apll = 1 does not produce glitches
Best whishes
De: Tomáš Pilný @.*** Enviado el: lunes, 17 de octubre de 2022 17:12 Para: espressif/arduino-esp32 CC: JoseEnriqueFA; Comment Asunto: Re: [espressif/arduino-esp32] The esp32 i2s internal DAC output is not working with the release 2.0.1 (Issue #5938)
Can you please try this sketch https://github.com/PilnyTomas/issues/blob/4b5315b5547165c9f080fd3e993dce24bf0fe7bf/issue_7252B/issue_7252B.ino if it works for you? It does for me.
— Reply to this email directly, view it on GitHub https://github.com/espressif/arduino-esp32/issues/5938#issuecomment-1281027915 , or unsubscribe https://github.com/notifications/unsubscribe-auth/AML3OVBGNJP7I5XPRQY2PR3WDVUFBANCNFSM5I5BQEUQ . You are receiving this because you commented. https://github.com/notifications/beacon/AML3OVDEOLFN733AH3RD6MTWDVUFBA5CNFSM5I5BQEU2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOJRNO6SY.gif Message ID: @.***>
The topic seems to be dead, so I am closing it.
Hi, I ran into this issue yesterday. Took me hours of testing different boards and max chips, checking wiring and pin layout etc. to finally come to the conclusion that the only difference of my hitherto working code vs. non working code and device was 1.0.6 vs 2.0.6 esp32 framework.
Arduino 1.8.6, esp32 2.0.6 framework, esp32 dev board, max dac chip.
Downgraded to 1.0.6, dac works again immediately.
Hi, After many hours used in this issue .... You have to init I2S depending the Board Manager you are using, see my code bellow In summary with Adafruit feather I follow using B.M. 1.0.6 with Adafruit feather v2 I use B.M. 2.0.4 Nevertheless take care of 1- if you change use_apll = false, to true with B.M. 2.0.4 you will get glitches It does not happen with B.M. 1.0.6 2- In my application I cannot use B.M. 2.0.5 because there are other issues related SPIFFS ... I should investigate .... 3- I have not tested B.M. 2.0.6 Good luck
//////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
void i2sInit()
{
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN),
.sample_rate = I2S_SAMPLE_RATE_LOW, // The format of the signal using ADC_BUILT_IN
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // is fixed at 12bit, stereo, MSB
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 64,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); //install and start i2s driver
i2s_set_pin(I2S_NUM_0, NULL); //for internal DAC, this will enable both of the internal channels
}
//////////////////////////////////////////////////////////////////////////////////////////////////// // Board Manager superior a 2.0.4 needs for ADAFRUIT ESP32 feather V2 ///////////////////////////////////////////////////////////////////////////////////////////////////
void i2sInit()
{
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN),
.sample_rate = I2S_SAMPLE_RATE_LOW, // The format of the signal using ADC_BUILT_IN
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // is fixed at 12bit, stereo, MSB
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_MSB, // B.M. 2.0.4
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 64,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); //install and start i2s driver
i2s_set_pin(I2S_NUM_0, NULL); //for internal DAC, this will enable both of the internal channels
}
De: McMornan @.*** Enviado el: miércoles, 09 de noviembre de 2022 18:13 Para: espressif/arduino-esp32 CC: JoseEnriqueFA; Comment Asunto: Re: [espressif/arduino-esp32] The esp32 i2s internal DAC output is not working with the release 2.0.1 (Issue #5938)
Hi, I ran into this issue yesterday. Took me hours of testing different boards and max chips, checking wiring and pin layout etc. to finally come to the conclusion that the only difference of my hitherto working code vs. non working code and device was 1.0.6 vs 2.0.6 esp32 framework.
Arduino 1.8.6, esp32 2.0.6 framework, esp32 dev board, max dac chip.
Downgraded to 1.0.6, dac works again immediately.
— Reply to this email directly, view it on GitHub https://github.com/espressif/arduino-esp32/issues/5938#issuecomment-1309077652 , or unsubscribe https://github.com/notifications/unsubscribe-auth/AML3OVE75QDJFXPZNP6GKUDWHPLRRANCNFSM5I5BQEUQ . You are receiving this because you commented. https://github.com/notifications/beacon/AML3OVHCU7WC7XW4GQXHGLLWHPLRRA5CNFSM5I5BQEU2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOJYDPBFA.gif Message ID: @.***>
Please understand the difference between IDF and arduino-esp32.
The function i2s_driver_install
is IDF (please read the documentation) - if something doesn't work, please report it to IDF repository
From version 2.0.3 of arduino-esp32 there is I2S library using Arduino API (Arduino Documentation) I am currently working on some fixes and updates for this library - you can follow them in PR #7117
Arduino-esp32 is based on IDF so you can always use IDF functions and combine them with Arduino API. We pull updates done in IDF from time to time, which could cause breaking changes or introduce bugs, but most of the time they are fixing previous bugs.
The audio output using I2S works both with an external DAC or in PDM mode but not using the internal DAC. This seems to be related to the ESP-IDF https://github.com/espressif/esp-idf/issues/7684