Arduino DUE and ESP32

800 views
Skip to first unread message

zcarlos zc

unread,
Jan 16, 2020, 7:06:16 AM1/16/20
to Mozzi-users
Hi.
Last year I added support for Arduino Due boards because I needed it for a project (a live show with some mozzi machines)
Also tried to include ESP32 boards (i2s DAC) but It wasn't perfect. Now, changing a parameter on I2s declaration and its running ok.
I would like to share it. 
- Arduino Due has a lot of GPIO so I could connect a matrix piano keyboard salvaged from broken MIDI controller.
- ESP32 has a big CPU power. I've been playing with a Akai APC connected to ESP32 through a hacked Mini USB Host Shield and its running very well.
I don't know how to use github to include my modifications.
I you like I can share it but I dont want to violate any license ;)
Tell me what can I do.
Thank you

Martin Gerken

unread,
Jan 16, 2020, 3:18:04 PM1/16/20
to Mozzi-users
Hi, that sounds quite intersting.
Could you just attach the modified files here - maybe someone with more knowledge of github could test&merge them...?
Martin

zcarlos zc

unread,
Jan 20, 2020, 3:20:54 PM1/20/20
to Mozzi-users
Hello.
Attached files are modified version of github release files.
ESP32 output: add "<<8" in updateaudio return
DUE output is OK
DUE needs DueTimer library.
No audio input and no stereo hack avaliable.

May be I'm doing something wrong but it sounds ;)
Hope it helps.
Mozzi_DUE_ESP32.zip
Message has been deleted

pictux

unread,
May 26, 2020, 10:03:56 AM5/26/20
to Mozzi-users
Hi zcarlos, 
thanks for sharing.
A few questions:
1. which is the pin to be used on the ESP32?
2. when you say "add "<<8" in updateaudio return" you mean that the row:
"return out;" should became "return out <<8;"?

Thanks!

zcarlos zc

unread,
May 28, 2020, 6:53:04 AM5/28/20
to Mozzi-users
Hello.

1 Pins are defined at MozziGuts.cpp. You need external i2s dac (PT8211)
i2s_pin_config_t pin_config = {
  .bck_io_num   = 26, 
  .ws_io_num    = 25, 
  .data_out_num = 33, 
  .data_in_num  = -1 
}; 
...

Some weeks ago I also tested esp32 8 bit dac out pin, so no need external i2s dac. I will test again and post here how to do that...I dont remember how I did it :) but I remember it was nice in m5stack stick esp32 board (orange)

2 Yes. You can test AMsynth example return out; to return out<<8; at updateAudio() or fmsynth_32k_hifi example return (int)aCarrier.phMod(modulation)<<6; to return (int)aCarrier.phMod(modulation)<<8;

;)

pictux

unread,
May 28, 2020, 5:10:47 PM5/28/20
to Mozzi-users
Hi zcarlos,
thank for the fast reply and for the info!

Just another question about the i2s dac PT8211: are you using a particular breakout board / module? 
I've found only sop8 ic!

Regards
M

zcarlos zc

unread,
May 29, 2020, 6:19:03 AM5/29/20
to Mozzi-users
Hello. 
You can use a ready to use PCM5102 i2s dac module for about 6$/6€
and some tiny pt8211 chips, so, with capacitors, resistor and audio conector, I made my own modules. Its cheaper ;)

Here you can find more info about diy PT8211 modules: https://www.pjrc.com/store/pt8211_kit.html

About attached picture:
I used a "5v power hacked"mini usb host shield to connect MIDI USB keyboard/controller to test mozzi and it runs quite well
mozzi usb pt8211.jpg

Dieter Vandoren

unread,
Jun 11, 2020, 5:38:12 AM6/11/20
to Mozzi-users
Hi Carlos,

Do you have any more info to share on using the internal DAC of the ESP32? Would be great to not have to use an external DAC!


Best, Dieter


On Thursday, 28 May 2020 12:53:04 UTC+2, zcarlos zc wrote:

Tom Combriat

unread,
Jun 11, 2020, 1:40:36 PM6/11/20
to Mozzi-users
Just to mention it: Mozzi now has the possibility to use an "user defined output" function (see https://github.com/sensorium/Mozzi/pull/87). So, if you can use this internal DAC using one of the ESP32 API functions then you can use this to output Mozzi on this pin.
Best,

zcarlos zc

unread,
Jun 17, 2020, 5:15:41 PM6/17/20
to Mozzi-users
Hi Dieter.
Sorry, I was busy. 

I've just tested example FmSynth sketch with m5Stick-C, that has a dac out at exposed pin GPIO26 (DAC2)


Lines not needed related to i2s (I didn't notice any change if i don't comment these lines)
File MozziGuts.cpp, comment lines from 107 to 126 (i2s configuration)
File MozziGuts.cpp, comment lines from 587 to 592 (i2s driver)

Change ouput
File MozziGuts.cpp, comment line 521 i2s_write_bytes((i2s_port_t)i2s_num, (const char *)&out32, sizeof(uint32_t), 0);
File MozziGuts.cpp, new line 522 dacWrite(26, out32);

Volume is very loud. Sound is a bit dirty.
I'm not and expert. May be somebody can do this thing sound much better. It would be nice.

Hope it helps

;)

Dieter Vandoren

unread,
Jun 18, 2020, 6:49:02 AM6/18/20
to Mozzi-users
Hi zcarlos and Tom Combriat,

Thank you very much for your inputs!


Tom: I hope we get to a level where we can embed our ESP32 progress in a user defined output. For now I'm hacking and fiddling away to get a useable signal out. Complexity is a little over my head but getting there step by step.


zcarlos: I 'm trying your code edits for both the PT8211 external DAC and the internal DAC (using Lolin D32 board). I'm embedding those in the Mozzi lib repository state from januay 2020, not the current version as I'm afraid there could be changes since that make your edits nonfunctional.

From both edits I get a signal out but it doesn't sound quite right yet. I'm also looking at it with a scope and see anomalies.

Internal DAC : seems terribly clipped. Running the sine example I get square waves, no matter how much I bitshift down in updateAudio().

PT8211 : I get a very small amplitude signal from the DAC output, about 0.1V, It does look like a nice sine BUT there is a horizontal (DC) signal running through it at 0V. Meaning it 's constantly flipping between the sine signal and 0V, as if it's multiplexing 2 signals in 1 output. See attached pic. It sounds very gritty too, unsurprisingly.


I'm now delving into this further. If anyone has advices and/or ideas they are much welcome!


Best regards, Dieter & Matteo   
PT8211 double signals.JPG

Dieter Vandoren

unread,
Jun 18, 2020, 11:31:05 AM6/18/20
to Mozzi-users
Hi all,

So I took zcarlos' code for the external PT8211 DAC and modified that to work with the internal DAC, following the ESP32 API reference (https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/i2s.html). I went this route because it gives us control over all parameters, which the dacWrite() route does not. I got it to output but with issues.

I also set the AUDIO_BIAS to << 19 and combined with a << 12 in updateAudio() I get a nice 2V amplitude. 

The stray DC line at 0V is still in the signal, and the sine is choppy. See attachment. I'm sure this can be resolved with a correct combination of timing and/or buffer parameters, but I haven't been able to crack it. Any ideas?

Other oddity: signal outputs on both pin 26 and 27.

Code snippets from MozziGuts.cpp:

[...]

// ESP32
#if IS_ESP32()
    #include <driver/i2s.h>
    #include "freertos/queue.h"   
    hw_timer_t * timer = NULL;
    int i2s_num = 0;
    i2s_config_t i2s_config = {
        .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN),
        .sample_rate = 44100,
        .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
        .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
        .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S_MSB),
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
        .dma_buf_count = 8,
        .dma_buf_len = 8,
        .use_apll = 0
    };
#endif

[...]

#if !IS_AVR()
static void startAudioStandard() {
[...]
#elif IS_ESP32()
  #ifdef DO_NOT_INIT_ESP32_I2S
  #else
    i2s_driver_install((i2s_port_t)i2s_num, &i2s_config, 0, NULL);
    i2s_set_pin((i2s_port_t)i2s_num, NULL);
    i2s_set_sample_rates((i2s_port_t)i2s_num, 44100);   
    // i2s_set_clk((i2s_port_t)i2s_num, 44100, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO); // this line seems useless
    i2s_zero_dma_buffer((i2s_port_t)i2s_num);
    i2s_set_dac_mode(I2S_DAC_CHANNEL_RIGHT_EN);
    timer = timerBegin(0, 80, true);
    timerAttachInterrupt(timer, &esp32AudioOutput, true);
        // zc - 30 microseconds is ok for now 
    timerAlarmWrite(timer, 30, true);
    timerAlarmEnable(timer);
  #endif 



Best, Dieter
internal double choppy signals .JPG

Dieter Vandoren

unread,
Jun 23, 2020, 6:18:35 AM6/23/20
to Mozzi-users
Hi all,

Still trying to crack this, but I'm a bit lost. I have it hooked up to a digital scope now and the issue is now very visible. See attachment. The sine is interleaved with 0's. I feel we're real close to smoothing this out but the variations of settings I'm (mostly blindly) trying have some effects on the waveform, but I haven't managed to find the magic combo that creates a full sine. I have too little knowledge of both the Mozzi guts and I2S/DAC intricacies.

Any pointers in the right direction are very much appreciated!


Best, Dieter
internal_sine_choppy_3.bmp

Tom Combriat

unread,
Jun 23, 2020, 6:30:53 AM6/23/20
to mozzi...@googlegroups.com

Hey,

Just a quick comment (which might prove useful or not). The I2S DAC for the ESP port is a stereo DAC if I'm not wrong. Could it be that you are outputting the two channels on the same pin, and not feeding anything into that second channel?

Best,

--
You received this message because you are subscribed to a topic in the Google Groups "Mozzi-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mozzi-users/qw2nIkcVaZE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mozzi-users...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/mozzi-users/17500991-b964-433f-98bb-4543be4c34f3o%40googlegroups.com.

Dieter Vandoren

unread,
Jun 23, 2020, 7:17:57 AM6/23/20
to Mozzi-users
Bingo! This does the trick:

.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,

Tom you are my hero :)


I'm going to test and tweak this further, then see if I can package it neatly (user defined output) and share. If anyone needs this right now feel free to email me.

Best, Dieter
internal_sine.bmp

dtr....@gmail.com

unread,
Aug 16, 2020, 8:27:45 AM8/16/20
to Mozzi-users
Hi all,

I left the modded library alone for a while and worked on other aspects of the project. Closing in on completion but having sound quality issues. The output from the ESP32 DAC is markedly more noisy and distorted than the unmodified lib running on an Uno PWM output. I'm also experiencing trouble fading out a sound. When using byte gain multipliers and going from a minimal gain of 1 to 0, there is a very big jump in volume. At 1 it's still pretty loud and the step to 0/off is very drastic. The original lib fades out nicely on PWM.

I'm trying to find where to improve sound quality. I have a suspicion I'm doing something wrong that requires me to have very large bitshifting operations to get sound output, but also causes sound quality degradation.

In  AudioConfigESP32.h I have the following to center the signal in the middle of the available 3.3V range: (ESP32 DAC is 8bit)

#define AUDIO_BIAS ((uint16_t) 1<<(19))

In my code and any of the Mozzi examples I have to bitshift up the output immensely: about 11 steps, to get a useable output signal amplitude. So if a standard example has  >> 3 I have to change it to << 8. Does this sound logical to you? Or is it a sign something is off? 


Best, Dieter

dtr....@gmail.com

unread,
Aug 16, 2020, 9:04:30 AM8/16/20
to Mozzi-users
In addition to my previous message, hereby a screenshot of a scope readout. That's a sin2048_int8 with a p2p amplitude of a little under 1V. There is obvious stepping (about 10 steps from minimum to maximum). I'd expect better resolution from an 8bit DAC output.

Any ideas?



stepped_sine.jpeg

Martin Gerken

unread,
Aug 16, 2020, 5:27:38 PM8/16/20
to Mozzi-users
The DAC is not great, but OK, according to: https://www.xtronical.com/basics/audio/dacs-on-esp32/
I think the excessive shifting is the problem; you may just have eaten up the 16bits available...
If you cannot find an error here then:
How about using an external DAC or the ESP32-A1S, which includes a DAC: https://www.exp-tech.de/en/platforms/esp32/9180/esp32-a1s-wi-fi-bt-soc-audio-module
Best, Martin

dtr....@gmail.com

unread,
Aug 18, 2020, 6:53:20 AM8/18/20
to Mozzi-users
Hi Martin,

Why internal DAC? We have 50 Wemos D32 boards for this project and prefer no to add 50 extra components :) External DAC can be an option for future projects.

I also have a suspicion that there might be a mismatch problem with bit resolutions. The DAC is 8bit but the I2S communication is 16bit and it is supposed to take the MSB to generate output. I found a stray bitshift >>4 in the modded mozzi lib. With that removed I can set AUDIO_BIAS to ((uint16_t) 1<<(15)), which would match 16bit resolution. But that doesn't improve the low resolution of the output.

I had seen the resources at https://www.xtronical.com/basics/audio/dacs-on-esp32/ and tried their sound library. They use the standard dacWrite() to generate output. I tried that route with Mozzi's new user defined external output mechanism but I don't manage to get output from it. I posted about it here: https://groups.google.com/g/mozzi-users/c/OJsX6s6Vdco

Any ideas appreciated!

Best, Dieter

dtr....@gmail.com

unread,
Aug 18, 2020, 11:46:52 AM8/18/20
to Mozzi-users
I went through it again and reviewed the data ranges. AUDIO_BIAS is now at << 7 to match the 8bit DAC resolution and I've added a << 8 to the output to shift to the 16bit MSB that the DAC is expecting. Standard examples (and my code) now don't require crazy bitshifts anymore and it matches the technical docs of the ESP32 DAC.

It hasn't improved resolution though, and I've noticed something else: I now actually think the stepping is in the time domain, not amplitude. 

Looking at attached scope graphs, I think I see the amplitude steps varying, which is not expected if we're dealing with low resolution stepping, and the time steps are always equal. This leads me to think the issue is with bad timing of output to the DAC. Any ideas?

D.
stepped_sine6.jpg
stepped_sine4.jpg
stepped_sine5.jpg

dtr....@gmail.com

unread,
Aug 19, 2020, 12:05:54 PM8/19/20
to Mozzi-users
I've reviewed MozziGuts.cpp and all the tech docs I could find many times but I don't manage to find what 's messing with output timing. Zcarlos put the first version of this in place and I worked from there. The output timer is set up like this:

    timer = timerBegin(0, 80, true); // 80Mhz / 80 = 1Mhz
    timerAttachInterrupt(timer, &esp32AudioOutput, true);
    timerAlarmWrite(timer, 30, true); // 1.000.000 / 32768 = 30.5176 usec
    timerAlarmEnable(timer);

Attached function is :

static void IRAM_ATTR esp32AudioOutput() {
    uint32_t outputEsp32=(uint32_t)output_buffer.read()<<8; // shift to MSB
    i2s_write_bytes((i2s_port_t)i2s_num, (const char *)&outputEsp32, sizeof(uint32_t), 0);
}

Is this the correct way to read the output_buffer?

Changing the timer parameters makes for a chopped up signal, like it gets out of sync with Mozzi's signal generation. Nothing I tried there improves the output sample rate.

dtr....@gmail.com

unread,
Oct 22, 2020, 8:48:00 AM10/22/20
to Mozzi-users
Hi,

I've moved on quite a bit in the project since my last post. ESP32 internal DAC support is at the same stage as then (not sure if it's optimal like this). In the meantime I've also worked on ESP32+PT8211 DAC and found issues in the solution given earlier in this thread by zcarlos. When looking at the output with a scope it turns out to be interleaved with a zero signal just like what I encountered with the internal DAC, creating a lot of unnecessary distortion. These I2S settings in MozziGuts.cpp remediate that.

    #include <driver/i2s.h>
    #include "freertos/queue.h"   
    hw_timer_t * timer = NULL;
    int i2s_num = 0;
    i2s_config_t i2s_config = {
        .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
        .sample_rate = AUDIO_RATE,
        .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
        .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
        .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_LSB),

        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
        .dma_buf_count = 8,
        .dma_buf_len = 8,
        .use_apll = 0 // Use audio PLL
    };

    i2s_pin_config_t pin_config = {
      .bck_io_num = 26,
      .ws_io_num = 25,
      .data_out_num = 33,
      .data_in_num = -1
    };



Further down in startAudioStandard():

    i2s_driver_install((i2s_port_t)i2s_num, &i2s_config, 0, NULL);
    i2s_set_pin((i2s_port_t)i2s_num, &pin_config);
    i2s_set_sample_rates((i2s_port_t)i2s_num, AUDIO_RATE);   
    
    i2s_zero_dma_buffer((i2s_port_t)i2s_num);

    timer = timerBegin(0, 80, true);
    timerAttachInterrupt(timer, &esp32AudioOutput, true);
        // zc - 30 microseconds is ok for now
    timerAlarmWrite(timer, 30, true);
    timerAlarmEnable(timer);


I slso modified: esp32AudioOutput() {
    uint32_t out32=(uint32_t)output_buffer.read();

    i2s_write_bytes((i2s_port_t)i2s_num, (const char *)&out32, sizeof(uint32_t), 0);
}


I intend to properly package these ESP32+PT8211 fixes in the current Mozzi branch and commit it to the GitHub soon.

Best, Dieter
Reply all
Reply to author
Forward
0 new messages