#Mozzi

diyelectromusicdiyelectromusic
2025-01-05

First application is now up for my Arduino Nano Mozzi EuroRack module. This is a basic VCO, largely based on HAGIWO's Arduino VCO but reimplemented and with a few extras.

diyelectromusic.com/2025/01/05

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-01-05

EuroRack 6HP Arduino Mozzi Module – Basic VCO

This is the first project based on my EuroRack 6HP Arduino Mozzi Module. It is loosely based on HAGIWO’s Arduino Mozzi VCO Module.

https://makertube.net/w/hnocMAhYkajd8nX2vwuR2u

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

These are some previous posts for the main concepts used in this project:

If you are new to Arduino, see the Getting Started pages.

Parts list

The Circuit

This uses the EuroRack 6HP Arduino Mozzi Module with the pots and jacks assigned as shown below.

The four potentiometers control the following:

  • POT 1 – OSC 1 core frequency offset (from V/Oct CV).
  • POT 2 – OSC 2 frequency ratio OSC1.
  • POT 3 – Waveform for both oscillators: sine, triangle, saw, square.
  • POT 4 – Octave: 1 lower, normal, 1 higher, 2 higher.

There are three CV inputs:

  • V/Octave pitch.
  • OSC1 vs OSC2 gain.
  • Pitch modulation.

The Code

The code is inspired by that of HAGIWO’s Mozzi VCO, in that I’m using Mozzi with two oscillators, with multiple waveforms, and I’m using HAGIWO’s gain profile for CV. But I’ve added a few extras and have rewritten the core Mozzi code to hopefully be a little more optimal.

The main V/Oct calculation has to happen every scan and HAGIWO uses a look-up table in PROGMEM for the fractional voltages that correspond to each value of the ADC and then uses those in the standard Volts to frequency equation:

Freq = BaseFreq . 2^CV

For a 10-bit resolution (the resolution of the Arduino ADCs) this requires 1024 values across the whole 5V range. That equates to 4.8828mV per step (5/1024) and as full octave of 12 steps is 1V that equates to 83.3mV per semitone.

The various CV recommendations I’ve seen suggest using a BaseFreq equal to C4, which is 261.6256 Hz in the calculation unless it is for a LFO or clock in which case a BaseFreq of 2Hz is recommended – which corresponds to 120 bpm if used for a clock. The BaseFreq is the frequency used for 0V. Many analog synths will accept negative voltages to go lower, but as this is an Arduino it only supports 0V to 5V.

HAGIWO uses a table of float values and uses floating point arithmetic to work out the frequency. I’ve opted to use fixed point arithmetic and also rather than store the CV “step” values in the table have pre-calculated the whole 2^CV for each step.

Here is some Arduino code that will output the required look-up table values. My full version will first output the individual voltage steps to 6 decimal places; then for the float version of 2^CV; and finally for the fixed point 16.16 equivalent – that is 16 bits for the integer part and a fixed 16 bits for the binary equivalent of the decimal part.

The code below just does the last part. This is using the FixMath library which was written for use with Mozzi (more here).

#include <FixMath.h>  // Designed for use with Mozzi

int res = 10; // 10-bit resolution
float maxv = 5.0; // Max voltage

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

int max = (1<<res) - 1;
float cvstep = maxv / ((float)max+1.0);

Serial.print("\n\n");
Serial.print("Resolution=");
Serial.print(res);
Serial.print(" bits (0 to ");
Serial.print(max);
Serial.print(")\tV/step=");
Serial.print(cvstep,6);
Serial.print("\n");

float cv = 0.0;
for (int i=0; i<=max; i++) {
if (i%16 == 0) {
Serial.print("\n");
}
float freqpow = pow(2, cv);
UFix<16, 16> q16n16fp = freqpow;
Serial.print("0x");
Serial.print(q16n16fp.asRaw(), HEX);
Serial.print(",");
cv += cvstep;
}
}

void loop() {}

I’ve used this to create the q16n16 version of the 1024 values required to calculate the frequency for each of the 0..1023 values that the 1V/Oct analog input could provide, covering the full 5V range. This is stored in the header file v2voct.h that is part of the code.

This does mean that any calculation of frequency must be done using the FixMath 16.16 values, for example:

UFix<16,16> q16n16potfreq = mozziAnalogRead(POT1);

This code takes the unsigned integer value (0 to 1023) from mozziAnalogRead and automatically turns it into a 16.16 fixed point format value in variable q16n16potfreq – note that in each case the decimal part will be zero as the starting point is an integer between 0 and 1023.

When reading values in from the look-up table, they have to be pulled in “raw” as they are already in the 16.16 format. But as Arduino doesn’t know anything about this format, they have been declared as uint32_t values in the PROGMEM structure, but then need to be read back out and treated as 16.16 values as show below.

#define CVSTEPS 1024
static const uint32_t q16n16fp [CVSTEPS] PROGMEM = {
0x10000,0x100DE,0x101BD,0x1029C,
...
};

UFix<16,16> fpow = UFix<16,16>::fromRaw(pgm_read_dword(&q16n16fp[voct]));

All calculations related to frequencies are performed using 16.16 values. The Mozzi oscillator setFreq function has a version that takes 16.16 values too, making everything actually quite straight forward once you get your head around what its doing.

Other notes on the code:

  • There are two gain values maintained – one for each oscillator. The values used come from another look-up table (that I took from HAGIWO’s original) that allows the CV to pan across from one oscillator to the other. I’m using 7-bit gain values (0..127) so that when the final audio sample is worked out at the end, it should all fit within a 16-bit value give or take.
  • The octave selector changes the octave of both oscillators and is determined by POT 4 and can select from 0V = C3 through to 0V = C6.
  • Oscillator 2 is set to a frequency between 2 octaves below and 1 or 2 octaves above the frequency of oscillator 1 at all times, as determined by POT 2 – quite how to do this was the subject of a bit of experimentation (see below).
  • The frequency of oscillator 1 is given by the setting of POT 1, the V/Oct CV, the mod CV and the octave.

The following code sets up the two frequencies for the oscillators.

UFix<16,16> fpow = UFix<16,16>::fromRaw(pgm_read_dword(&q16n16fp[voct]));

UFix<16,16> q16n16freq1 = q16n16oct * (q16n16c4 + q16n16potfreq + q16n16mod) * fpow;

UFix<16,16> q16n16freq2 = q16n16Mult * q16n16freq1;

aOsc1.setFreq(q16n16freq1);
aOsc2.setFreq(q16n16freq2);

q16n16c4 is the frequency of C4 in fixed point 16.16 format. It is essentially the “BaseFreq” in the original equation. Notice how the base frequency is also affected by POT 1 and the modulation CV. The whole lot is then multiplied by the octave setting, which will be one of 0.5, 1.0, 2.0 or 4.0.

The multiplier used for the second oscillator (q16n16Mult) comes from POT 2. I have included two approaches to using this: discrete values or continuous.

For discrete values, the setting of POT 2 selects one of 8 fixed ratios to use to set the frequency of OSC 2 compared to OSC 1. I’ve chosen the following options (with 0.0 effectively being “off”):

{0.0, 0.25, 0.333333, 0.5, 0.666666, 1.0, 1.333333, 2.0}

For continuous values, I take the raw reading (0..1023) and convert it into a 2.8 fixed point number by shifting left by 8 bits and then treating it as a raw 16.16 value. This works as the number is a 10-bit value, so shifting left 8 bits makes it a 18 bit value – but then when read as a 16.16 bit value, the lowest 16 bits of those 18 are treated as the decimal…

UFix<16,16> q16n16Mult = UFix<16,16>::fromRaw(((uint32_t)mozziAnalogRead(POT2)) << 8);

Note I have to ensure it scales the return value from mozziAnalogRead up to 32-bits first otherwise clipping will occur. This allows me to have fractional octave values for the second oscillator compared to the first.

As the second oscillator starts 2 octaves below the first, this gives a range of multipliers starting from nothing (i.e. “times zero”), to almost two octaves below oscillator 1 (00.01000000 in 2.8 fixed point binary) through to 1 octave below (x0.5 = 00.10000000), to the same as oscillator 1 (x1 = 01.00000000) to 1 octave above (x2 = 0x10.00000000) to almost 2 octaves above (x4 would be 1024, but 1023 is 11.11111111).

The downside of this approach is that the response to the potentiometer setting isn’t linear. Or rather, it is linear, when really I’d like it not to be… I might go back and correct that in software at some point, but it is fine for now.

Note that if POT 2 is set to zero, then oscillator 2 is turned off. One option to always keep it on is to always ensure a minimum POT 2 reading. I’ve included that as an option to have the minimum reading of 64, which when converted to 2.8 format is 00.01000000 or 0.25 in decimal – hence a multiplier that gives “two octaves below”.

The final calculation that is performed for each audio sample is given by:

AudioOutput updateAudio(){
return MonoOutput::from16Bit(bOsc1Gain*aOsc1.next()+bOsc2Gain*aOsc2.next());
}

This combines the audio samples of each of the oscillators, multiplies them by the 7-bit gain value and then tells Mozzi to take this as a 16-bit value to be turned into a Mono output value.

Right at the start, I’ve told Mozzi to use “HiFi” mode, which should give me 10 bits of PWM output range using D9 and D10. I’ve also used a slightly higher MOZZI_CONTROL_RATE to help with scanning the IO.

Find it on GitHub here.

Closing Thoughts

As can be seen from the video, I don’t really anything much to use this with yet, but I’ve driven it from my “Baby8” CV Step Sequencer and the LFO from my Educational DIY Synth Thing and I think it seems to work ok. The video includes the following:

  • Changing basic OSC 1 frequency via POT 1.
  • Changing OSC 2 ratio compared to OSC 1 via POT 2.
  • Chaning the octave via POT 4.
  • Chaning the waveforms via POT 3.
  • Generating a V/Oct CV from the Baby 8.
  • Setting a low sweep of CV1 to control the relative gain of OSC 1 vs OSC 2.
  • Swapping to CV2 to provide additional pitch modulation to the oscillators.

This isn’t quite using the final version of the code, but gives an idea.

Note that the V/Oct input won’t work at true audio frequencies, so it can’t be used for frequency modulation, but otherwise I’m quite pleased with the performance considering it is updating from three CVs and four potentiometers each scan.

It might be possible to up the MOZZI_CONTROL_RATE even more and scan the CVs more frequently than the pots, but for now they are all scanned at the same time using a MOZZI_CONTROL_RATE of 128 (twice the default 64).

The output seems pretty clean to me too, but that is really thanks to HAGIWO’s original PWM output stage.

I’m just waiting for some spray-on adhesive so I can make a simple panel for it now.

Kevin

#arduinoNano #define #HAGIWO #include #mozzi #oscillator #vco

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-01-03

EuroRack 6HP Arduino Mozzi Module

This project uses my EuroRack 6HP MCU Experimenter Module to implement HAGIWO’s Arduino Nano based VCO.

This post describes how to put it together and test the basic functionality. Future posts will look at some code that can run on the module (see the “Sample Applications” section).

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

These are the key tutorials for the main concepts used in this project:

If you are new to Arduino, see the Getting Started pages.

Parts list

For the IO board:

  • 1x MCP6232 or equivalent OpAmp.
  • 8x BAT43 Schottky diodes.
  • Normal resistors: 1x 100Ω, 1x 200Ω, 4x 1kΩ, 1x 330kΩ, 2x 100kΩ.
  • Higher accuracy resistors (1% or better): 2x 3.9kΩ, 1x499kΩ.
  • Ceramic Capacitors: 4x 100pF, 1x 4.7nF, 1x 10nF, 3x 68nF, 1x 100nF.
  • Electrolytic Capacitors: 1x 4.7uF.

Note: it is worth measuring a range of 499K and 3.9K resistors and finding the best ones. In my case I only had 500K resistors, so found the closest to 499K I had. I ended up with two 3.88K and one 498K.

For the Pots and Jacks board:

  • 4x 10kΩ or 100kΩ PCB mount potentiometers.
  • 4x “Thonkiconn” jack sockets.
  • Header pins.
  • Jumper wires

The IO Board

Here is how the various sub-circuits of the IO board will be used:

Circuit ElementIO Board ConnectionFunctionR/C 40xCV_IN 1Control Voltage 1R/C 45xCV_IN 2Control Voltage 2R/C 30xGATE_IN 1Potentiometer Input 1R/C 35xGATE_IN 2Potentiometer Input 2R/C 65xOUT 4Potentiometer Input 4R/C 60xOUT 3Potentiometer Input 3R/C 55xOUT 2Not usedR/C 50xOUT 11V/Oct Control VoltageR/C 10xPWM 1Audio outputR/C 20xPWM 2Not used

Notice that the GATE and OUT circuits are being used in “alternative” modes as additional inputs (see the Usage Notes for more details). In particular the transistors on the GATE circuits are not used.

The following shows which components of the PCB will be populated (yellow), which will be changed for other components (blue), which wire links are required (red) and which connectors will be used for linking to the Pots and Jacks board (green) and MCU (purple).

Here is the list of components required for the above:

Resistors:

  • R100: 499K
  • R101, R102: 3.9K
  • R105: 200Ω
  • R300, R350, R400, R450, R600, R650: 1K
  • R401, R451: 100K
  • R500: 100Ω
  • R501: 330K

Capacitors

  • C100: 4.7nF
  • C101: 10nF
  • C102: 4.7uF electrolytic
  • R301, R351, C400, C450, C600, C650: 100pF (yes, two resistor slots are capacitors).
  • C400, C450, C500: 68nF

Other:

  • D100, D101, D400, D401, D450, D451, D500, D501: BAT43 Schottky Diodes
  • MCP6243

The mapping between IO connections and MCU IO pins is as follows (all other IO pins are not used):

MCU Connection PointMCU IO LinkFunctionMCU PWM 1H9Audio OUTMCU PWM 1L10Audio OUTMCU IN CV 2A7CV2MCU IN CV 1A6CV1MCU IN GATE 2A5Pot 2MCU IN GATE 1A4Pot 1MCU OUT 4A3Pot 4MCU OUT 3A2Pot 3MCU OUT 1A01V/Oct CV

Note: the order of the Gate/CV is (from top to bottom): CV 2, CV 1, G2, G1. The ordering of the OUT connections is the same for both sets of pin headers: 1 on the left, through to 4 on the right.

Build Order and Photos

This is the suggested build order:

  • Diodes.
  • Resistors.
  • Small capacitors.
  • Header sockets (assuming PH5 and PH3.5 sockets).
  • Capacitor on the rear of the board.
  • OpAmp.
  • Larger capacitors.
  • MCU board header sockets on rear of the board.
  • Jumper wires.

When installing R501, I’ve opted to make the fix described in the EuroRack 6HP MCU Experimenter Module Usage Notes and swap its position to the other side of R500 as shown below.

Otherwise the build proceeding pretty much as suggested.

Note that the OpAmp’s capacitor must be soldered to the rear of the board prior to fixing the OpAmp.

The install the OpAmp, smaller headers and larger capacitors.

Finally the longer headers for the MCU board can be installed on the rear of the board.

Finally the patch links can be installed as described previously (including the links instead of R104 and the transistors).

The Pots and Jacks Board

These functions will map onto the following potentiometers and jacks (and connections) from the EuroRack 6HP MCU Pots and Jacks PCB:

Pot/JackFunctionConnectionRV1Potentiometer 1GATE 1RV2Potentiometer 2GATE 2RV3Potentiometer 3OUT 3RV4Potentiometer 4OUT 4IN1V/Octave CV INOUT 1IN2CV 1 INCV 1IN3Not usedIN4Not usedOUT1Audio OUTPWM 1OUT2CV 2 INCV 2OUT3Not usedOUT4Not used

The pots and jacks PCB should be wired up to the interconnecting headers as follows:

Optionally, it might be useful to connect from the GND header pin to the panel once fitted.

It is suggested the Jacks and Pots PCB is built in the following order:

  • Small header pins on the underside of the board.
  • Long header pins (if used) on the underside of the board.
  • Jacks.
  • Potentiometers.
  • Link wires.

The Panel

This is the panel design required.

The measurements are all detailed in the EuroRack 6HP MCU Pots and Jacks PCB Build Guide, but crucially the pot holes are M7 and the jack holes are M6. I found they needed a 7.5mm and 6.5mm drill respectively to allow for a bit of flex when fitting the panel.

I’ve used M2 mounting posts, screws and nuts between the boards. In particularly, I found that the spacing required a 6mm spacer with an additional nut added as shown below.

I also had to break off the alignment lugs on the potentiometers to allow the panel to fit snugly.

Once all together, you can see it needs around 45 to 50 mm clearance behind the panel for the whole thing.

Testing and Basic Code

I recommend performing the general tests described here: PCBs.

Then it can be connected to an Arduino Nano MCU board an a basic analogRead test can be performed to check the pots and input jacks.

void setup() {
Serial.begin(9600);
}

void loop() {
for (int i=0; i<8; i++) {
int aval = analogRead(A0+i);
Serial.print(aval);
Serial.print("\t");
}
Serial.print("\n");
delay(100);
}

An external potentiometer can be connected to a mono patch lead (GND and signal) and VCC to test the CV IN jacks (IN1, IN2, OUT2).

The order should be as follows:

A0IN 1 (1V/Oct)A1Not used, floatingA2POT 3A3POT 4A4POT 1A5POT 2A6IN 2 (CV1)A7OUT 2 (CV2)

The (dual) PWM output can be tested using the basic Mozzi “Hi-Fi” sinewave test which can be found in the examples here:

  • Examples -> Mozzi -> 01.Basics -> Sinewave_HIFI

Sample Applications

Here are other posts describing some sample applications for this module.

Closing Thoughts

I have to be honest – working out which parts of the circuits to use, then referring back to them to populate the PCBs, then soldering on the intra-board links and finally fiddling with the panel was actually quite a lot of work.

I don’t know if I’ve saved anything compared to just building the circuit from scratch on a piece of protoboard.

It is also going to be quite likely that any issues might be hard to trace too.

I might find that as I use more of these boards, (assuming I build some more of course), then I get to know the layout and circuits and won’t be referring back to the designs so much. I’ll have to see how it goes.

But for now, if all you want is a single Arduino Nano HAGIWO circuit, then you’re probably better off just making it up on protoboard…

But I think the whole board “sandwich” once complete does look pretty good!

I’ll have to see if I can get a bit of a “production line” going and make up a few more. And now I have to get on with some code…

Kevin

#arduinoNano #EuroRack #HAGIWO #mozzi

diyelectromusicdiyelectromusic
2025-01-03

Ok, so first module has been put together. This is Nano-based and I'll probably set it up as a oscillator.

But tbh, I'm still deciding if this is really worth the effort in the end - it was quite a faff...

But then I've nothing else to compare it with, having not built anything from just protoboard either.

I now need to decide what to do about labelling - it would be nice to get a proper printed label done somehow.

Write-up on its way once I've done some code.

Photo of a DIY EuroRack 6HP module with three PCBs sandwiched behind a white PCB-front panel.  The panel has four potentiometers and four jacks and is currently blank.
Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2024-12-09

ESP32 WROOM Mozzi Experimenter PCB Build Guide

Here are the build notes for my ESP32 WROOM Mozzi Experimenter PCB Design.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

If you are new to electronics and microcontrollers, see the Getting Started pages.

Bill of Materials

  • ESP32 WROOM Mozzi Experimenter PCB (GitHub link below)
  • ESP32 WROOM 32-D DevKit (see photos and PCB for pinout – in particular note position of 3V3 and GND pins)
  • 1x H11L1 optoisolator
  • 1x 1N4148 or 1N914 signal diode
  • 1x 10Ω, 1x 33Ω, 1×220Ω, 1×470Ω, 2x1K, 2x2K resistors
  • 8x 10K potentiometers (PCB mount, see PCB and photos for footprint)
  • 2x 100nF ceramic capacitors
  • 2x 10uF non-polar capacitors (electrolytics probably fine too)
  • 1x 100uF electrolytic capacitor
  • 1x 3.5mm stereo TRS socket (PCB mount – see photos/PCB)
  • Either 2x 180 degree DIN sockets (PCB mount – see photos/PCB)
  • Or 2x 3.5mm stereo TRS sockets
  • 1x 2.1mm barrel jack socket (PCB mount – see photos/PCB)
  • Optional: 2x or 4x 15-pin header sockets
  • Optional: 1x 6 way DIP socket
  • Optional: pin headers
  • Optional: jumpers
  • Optional: SPDT slider switch, 2.54mm pitch connections (see photos/PCB)

Build Steps

Taking a typical “low to high” soldering approach, this is the suggested order of assembly:

  • All resistors and diode.
  • DIP socket (if used) and TRS socket(s).
  • Disc capacitors.
  • Headers.
  • Switch (if used).
  • Barrel jack.
  • Non-polar and electrolytic capacitors.
  • DIN sockets (if used).
  • Potentiometers.

Here are some build photos.

There are several options for headers – there is an additional breakout of all the pins of the ESP32 module and these can be populated with sockets, pins or just left unpopulated as shown below.

And finally adding the potentiometers.

Configuration Options

Two of the potentiometers, RV1 and RV2, have configurable GPIO connections, which are selected by solder jumpers on the rear of the board. The default has them mapped as follows:

RV1GPIO 13RV2GPIO 12

The alternative is configured by cutting the default track between the top solder pads and re-soldering to the bottom pads:

Only one can be changed if required. The alternative configurations are:

RV1GPIO 39RV2GPIO 36

Testing

I recommend performing the general tests described here: PCBs.

Functionality testing is covered by the Sample Applications given below.

PCB Errata

There are the following issues with this PCB:

  • The UART jumper is labelled UART0 and UART1, but in actually, UART1 is almost certainly going to end up being UART2 as UART1 is typically used for onboard flash memory.

Enhancements:

  •  I could add a slightly larger prototyping area, perhaps mirroring the layout of a mini solderless breadboard and still keep within a 100x100mm footprint.

Find it on GitHub here.

Sample Applications

Recall that the GPIO used can be found listed in the ESP32 WROOM Mozzi Experimenter PCB Design.

Potentiometer Analog Read Test

The following code will echo the values from all 8 potentiometers to the serial monitor.

#define NUM_POTS 8
int potpins[NUM_POTS] = {
13, 12, 14, 27, // ADC 2.4, 2.5, 2.6, 2.7
33, 32, 35, 34 // ADC 1.4, 1.5, 1.7, 1.6
};

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

void loop() {
for (int i=0; i<NUM_POTS; i++) {
int aval = analogRead(potpins[i]);
Serial.print(aval);
Serial.print("\t");
}
Serial.print("\n");
delay(100);
}

DAC Write Test

The following code will generate two sawtooth waveforms on the two DAC pins, GPIO25 and GPIO26, which are connected to the audio output L and R channels.

GPIO 25 will generate a 440Hz saw tone, and GPIO26 will generate a 880Hz saw tone.

This works, as the code generates a 6-bit (i.e. 0 to 63) value saw wave, updating the value every time through the loop() function. The value is effectively scaled up to 8-bits (0 to 255) by multiplying by 4. The frequency is doubled for pin 26 by multiplying by 8.

In reality, I’m actually taking advantage of the fact that “count” is a uint8_t – i.e. only an 8-bit value – and will automatically wrap around back to zero when the value gets to 255. So in the code, every time the actual “count” variable wraps (0 to 255), the multiplied by 4 version will have wrapped 4 times (i.e. 0 to 63 four times – well, actually it is going 0 to 255, but in steps of 4 at a time, so it will do that 4 times). Similarly the multiplied by 8 version will have wrapped 8 times.

The code has to output these 64 values, 440 times a second, to generate the 440Hz saw tone – so 64 x 440 = 28,160 values a second. That means there is one value required every 35 uS or so. I use the ESP32 microsecond timer to manage this.

uint8_t count;
uint32_t timer;
void setup() {
count = 0;
timer = 0;
}

void loop() {
uint32_t newtime = esp_timer_get_time();
if (newtime >= timer) {
dacWrite(25, count*4); // Auto wraps at 256
dacWrite(26, count*8); // Twice frequency of wrapping...
count++;
timer = newtime + 35; // 35 uS in future of last timer read
}
}

MIDI Test

The ESP32 Simple MIDI Monitor code can be used for a simple MIDI test. The code is configurable for either UART0 or UART1 (in reality mapped onto UART2 in the ESP32) for MIDI.

In use, on reception of any NoteOn message the onboard LED will light up. Also, any MIDI data received over MIDI IN is software-THRU echoed to MIDI OUT.

When using UART1 (UART2) then there will also be a MIDI message dump to the serial monitor.

Closing Thoughts

This board seems to work well. But I have a bit of a problem at the moment. There seems to be a problem with the current (at the time of writing) Mozzi library and the ESP32. There is an incompatibility with the I2S driver used for streaming data out to the DAC.

So at the time of writing, as a Mozzi experimenter board, my options are a little limited. But as soon as Mozzi is updated to the latest ESP32 SDK I2S interfaces, hopefully I’ll be able to properly get going. Watch this space.

Kevin

#dac #esp32 #midi #mozzi #pcb #potentiometer

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2024-12-07

ESP32 WROOM Mozzi Experimenter PCB Design

Before building my Educational DIY Synth Thing I was playing with the ESP32 WROOM dev boards I’d found and was thinking about doing some Mozzi experiments. This post started to document some of the things I’d found out about the boards, but never made it to a complete post.

I’ve now gone back and finished off the design for an experimenter pcb using the dev boards to allow me to do some more playing around with Mozzi and synthesis.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

If you are new to microcontrollers, see the Getting Started pages.

Background Information

I’m using an entire ESP32 WROOM 32-D DevKit (as shown above) and not just the module itself. This isn’t the official DevKit (note the VIN/3V3/GND pins are different I believe) but it is widely available.

Using the DevKit means I get a few extras “for free”, namely:

  • Onboard voltage regulation to 3V3 via a NCP1117.
  • USB serial interface via a CH340.
  • Reset (EN) and Boot buttons.
  • Onboard LED on D2.
  • Normal pin headers including extra pins for additional GND connections and VIN.
  • USB C connector.

Power Supply

Power is provided via USB or VIN. According to the schematics I’ve found online (which seem to agree with what I can trace out on my board) the power circuit is as follows:

I’ve found some discrepancy in the capacitors values – another schematic suggests C1 here is 100nF. I also found one schematic that shows VCCUSB connected directly to VIN on the NCP1117 rather than via a diode, but my board seems to match the above.

Taking VIN on the module pinout as being the input to the NCP1117 and with a maximum dropout voltage of 1.2V (as per the NCP1117 spec) then the input range for VIN should be 4.5V up to 20V.

As already mentioned, there is an officially documented Espressif ESP32 DevKit (details here and here) but the pinout for this is different to the modules I’ve found that seem pretty common online.

Audio Output

In an effort to keep things relatively simple, I’m keeping with the on-board (internal) DAC of the ESP32. Marcel Licence has a great video (“ESP32 synthesizer with NODAC”) showing how to hook up the two internal DAC channels to an external line out, so I’m going with essentially the same design here.

From Marcel’s video:

  • “The max voltage of 3.3V will be reduced by the voltage divider (R4+R5, R6+R7)”
  • C1 and C2 remove the DC bias as usual.
  • “R8, R9 are not really necessary but I added them to avoid an open output when the ESP32 is powered down”.

The Circuit

The PCB will support the following:

  • 8 potentiometer inputs.
  • Audio out from the two DAC channels.
  • MIDI IN and OUT (selectable UART 0 or 1).
  • Small prototyping area.
  • Direct power in (5-12V) to the on-board regulator.

I’ve used Marcel’s DAC output circuit but omitted R8, R9 and adjusted the values of R4, R5 to keep the same ratio for the divider but with slightly adjusted values:

  • 220 / (220+560) ~= 0.28
  • 1K / (1K + 2K) ~= 0.33

So a 0 to 3.3V signal becomes +/- 550mV.

One thing I wasn’t sure about was the use of the strapping pins, so I’ve included solder bridge options to allow the re-patching (or even disconnecting) of two of the pots if required.

The pin mapping used is as follows:

2GPIO36 / ADC1_CH0RV2 option3GPIO39 / ADC1_CH3RV1 option4GPIO34 / ADC1_CH6RV85GPIO35 / ADC1_CH7RV76GPIO32 / ADC1_CH4RV67GPIO33 / ADC1_CH5RV58GPIO25 / DAC 1Audio Output9GPIO26 / DAC 2Audio Output10GPIO27 / ADC2_CH7RV411GPIO14 / ADC2_CH6RV312GPIO12 / ADC2_CH5RV2 default13GPIO13 / ADC2_CH4RV1 default21GPIO16 / UART1 RXMIDI IN option22GPIO17 / UART1 TXMIDI OUT option27GPIO3 / UART0 RXMIDI IN option28GPIO1 / UART0 TXMIDI OUT option

All non-used GPIO pins will also be broken out to additional prototyping headers.

PCB Design

The PCB includes additional header pin connections for all pins of the DevKit and also breaks out the unused GPIO pins to a header row near the prototyping area. There is also a row of 3V3 and GND next to the prototyping area.

I’ve used solder jumpers on the underside of the board to change the GPIO option for RV1 and RV2.

There is also a jumper header to allow the selection of UART 0 or UART 1 for the MIDI links and MIDI supports either TRS or DIN sockets.

There is a stereo TRS for audio output connected to the two DAC outputs. With hindsight, I should have allowed a jumper option for a single DAC to drive both audio channels, but that could be easily supported with an additional jumper wire.

Closing Thoughts

Whilst a bit late for my main experiments with the ESP32, there are still plenty of things I’d like to do with them, and I’ve really not done very much with Mozzi itself, so I think this will end up being really quite handy.

Kevin

#esp32 #mozzi #pcb

Tod Kurt (todbot)todbot
2024-07-07

Finally getting back to playing with pico_test_synth project, this time in Arduino. Working on a new simple handmade GUI after failing to find a GUI widget toolkit for Adafruit_GFX or U8g2 that offered anything beyond text boxes

diyelectromusicdiyelectromusic
2024-06-22

Hmm... Installing Mozzi v2 - a pretty big update! Wish me luck :)

And it might be time to get back to my Nano Every port I started some 18 months or so ago...

Tod Kurt (todbot)todbot
2024-04-17

I’m pretty proud of my THX Deep Note sound recreation attempt, which I realized I only posted on Twitter (RIP). So I upload it to Youtube & here. The Mozzi synth library is great and it was fun getting it to do this. And thanks to Mike Rugnetta for getting me near the rabbit hole of the THX sound!
Code: github.com/todbot/mozzi_experi
Youtube: youtube.com/watch?v=7fX8cBwbOmU

2024-04-07

I’m continuing my series of experiments with the ESP32 by considering how I might use the twin DACs onboard the WROOM module as a Lo-Fi, 8-bit envelope generator. I’ve not looked at envelope generation before, so this is a good excuse to see what it is all about.

Important Note: This is NOT an envelope generator circuit or standalone device at present. It just outputs the waveform to the DAC. There is no electronics here that would make that a usable signal in any kind of controlling manner at present. This is mostly thinking about the code to produce the waveforms.

In short, don’t hook this up to anything else unless you really know what you are doing (unlike me).

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

These are the key tutorials for the main concepts used in this project:

If you are new to microcontrollers, see the Getting Started pages.

Parts list

  • ESP32 WROOM DevKit
  • 4x or 8x 10kΩ potentiometers
  • 2x 1kΩ resistors
  • 2x push/toggle switches
  • Breadboard and jumper wires

The Circuit

I’ve ended up wiring potentiometers to eight analog inputs, buttons to two digital inputs and put my oscilloscope on each of the DACs to see the output.

The potentiometers are wired in the usual VCC-signal-GND manner (although only one is shown above). The buttons are pulled down as the signals are meant to be active HIGH signals.

The Trigger input is a pulse indicating when a key would be pressed and signifying the start of the envelope generation. When triggered the Attack stage of the envelope will begin immediately followed by the Delay phase. The Gate input is held and meant to indicate while the key is pressed and when it is released. Whilst on, the envelope will remain in the Sustain phase. On removal of the Gate signal the Release stage of the envelope will start.

Note that the plan is for the Trigger to allow retriggering of the envelope at any time and that for removal of the Gate can also happen at any time and start Release. It is also quite possible for there to be several triggers whilst the gate is still active.

It is also possible for the trigger and gate pin to be the same in which case trigger happens on the rising edge along with gate ON and gate OFF will happen on the falling edge.

Here is the full GPIO list for this experiment.

GPIO 25DAC – Envelope 1 outGPIO 26DAC – Envelope 2 outGPIO 12Trigger inputGPIO 13Gate inputGPIO 14Env 1 AttackGPIO 27Env 1 DelayGPIO 33Env 1 SustainGPIO 32Env 1 ReleaseGPIO 35Env 2 AttackGPIO 34Env 2 DelayGPIO 39Env 2 SustainGPIO 36Env 2 Release3V3Pot VCCGNDPot GND

I’ve used the same GATE and TRIGGER signals for both envelope generators, but it would be quite happy with four independent inputs.

Everything here is working with 3V3 logic levels, including the envelope voltages produced.

In the photo below I’ve simplified my wiring by using my Analog IO Board PCB to give me eight potentiometers directly wired into the ESP32.

Envelopes in Mozzi

I’ve already used envelopes in my experiments with ESP32 and Mozzi, but they are applied in software to modulate the amplitude of the Mozzi synthesized output. And really, if using a microcontroller for synthesis this is the natural way to do things.

By way of an example, in Mozzi, envelopes are created on startup, have their parameters changed as part of the control loop, are triggered on and off usually in response to note events, and then have each instantaneous value calculated as part of the audio loop an applied to the sample value.

The essence of their use in Mozzi is as follows:

#include <ADSR.h>

ADSR <CONTROL_RATE, AUDIO_RATE> envelope;

void HandleNoteOn(byte channel, byte note, byte velocity) {
envelope.noteOn();
}

void HandleNoteOff(byte channel, byte note, byte velocity) {
envelope.noteOff();
}

void setup () {
envelope.setADLevels(ADSR_ALVL, ADSR_DLVL);
envelope.setTimes(ADSR_A, ADSR_D, ADSR_S, ADSR_R);
}

void updateControl(){
IF ADSR values have changed THEN
call setADLevels and setTimes again as required
}

AudioOutput_t updateAudio(){
Calculate new 8-bit sample
return MonoOutput::from16Bit(envelope.next() * sample);
}

All that would be required to get this to output just the envelope would be to change the return statement in updateAudio to return the envelope value directly.

AudioOutput_t updateAudio(){
return MonoOutput::from8Bit(envelope.next());
}

There are several more example sketches in Examples->Mozzi->07.Envelopes.

There are several issues with this approach that stop me using this for what I want to do:

  • This only supports one output. I might be able to configure two envelopes and get one output on the “left” channel and one on the “right” channel, which I think then map onto the two DACS…
  • I want to integrate this with some of my ESP32 PWM messing around too, which isn’t easy when Mozzi is determining all the outputs. There is an option to use a user-defined function for the output, but at this point I’m doing a lot more myself anyway…

And anyway, I wanted to work out how an envelope generator could be implemented myself. So I didn’t use Mozzi and got to work on my own implementation.

DIY Envelope Generation using Timers

I had an initial look around at any existing envelope generator implementations for Arduino, having a look at both ADSRduino and the Mozzi ADSR implementation.

In the end I opted for a simpler design of my own, deciding to manage the ADSR as a state machine in code with calculations for how much the envelope level needs to change per tick of a timer. I’m just implementing simple linear updates for each stage.

Setting up the timer is the same as for PWM, but this time I’m using a 100kHz timer with an alarm every 10kHz. This gives me a 0.1mS “tick” which is more than adequate for generating an envelope.

I’ve opted to map the potentiometers onto the ADSR parameters as follows:

  • ADR are mapped using: 1 + potval * 2.
  • S is mapped directly to a value in the 0..255 range, reflecting the 8-bit DAC output.

The time values are in units of 0.1mS so can specify a duration for any of the three stages between 0.1 and 819.1 mS. For pragmatic reasons, when using these values in calculations, I always add 1 so I don’t ever have a divide by zero (which causes the ESP32 to reset).

All values relating to a level are in 8.8 fixed point format, so are essentially 256 times larger than they need to be to give more accuracy in calculations.

The ADSR state machine has the following functionality:

Idle:
Do nothing

Trigger:
Start Attack

Attack:
Increase level to maximum from current level one step at a time
IF level reaches maximum:
Move to Delay

Delay:
Decrease level to sustain level one step at a time
IF level reaches sustain level:
Move to Sustain

Sustain:
Stay at same level while Gate is ON
IF Gate is OFF
Move to Release

Release:
Decrease level down to 0 one step at a time
IF level reaches zero
Move back to Idle

For each stage I maintain a step value, which is how much the level has to change for that specific step. This is calculated as follows:

Num of Steps for this stage = Time of the stage / SAMPLE RATE

Usefully, if I’m measuring the time of the stage in mS then I can use a SAMPLE RATE in kHz and the calculation still works. So the step increment itself can be found by:

Step increment = (Required end level – Starting level) / Num steps

Step increments can be positive or negative of course depending on whether the output is rising or falling.

As already mentioned I’m using 8.8 fixed point arithmetic for the levels. The biggest concern was watching out for automatic wrapping of the 16-bit values whilst performing calculations, so I’ve removed that as a possibility by using signed, 32-bit values for the step increment and stored level.

All the parameters associated with an envelope are stored in a structure:

struct adsrEnv_s {
int32_t env_l;
int32_t steps;
uint16_t attack_ms;
uint16_t attack_l;
uint16_t delay_ms;
uint16_t sustain_l;
uint16_t release_ms;
bool gate;
adsr_t state;
} env[NUM_DAC_PINS];

And there are a number of functions for manipulating the envelope. This is the point where really I ought to be branching over into “proper” C++ and making this an object, but I’ve stuck with C, structures and arrays for now.

The final implementation has a few extra steps in the state machine corresponding to the transitions between stages. This just makes calculating the new step values clearer at the expense of adding an extra timer “tick”‘s worth of processing time to each stage.

Two complications come from how the gate and trigger need to be handled.

The gate has to be checked in each of the stages and if the gate goes to OFF then the state needs to switch over to Release.

The trigger needs to come externally to the main state machine, but in order to ensure I’m not attempting to update variables at the same time that that they are being manipulated by the interrupt-driven state machine function, the trigger just updates the state to a “trigger” state so that on the next tick, the state machine will update itself.

The full set of states recognised now stands as follows (stored roughly in the order they progress through):

// ADSR state machine
enum adsr_t {
adsrIdle=0,
adsrTrigger,
toAttack,
adsrAttack,
toDelay,
adsrDelay,
toSustain,
adsrSustain,
toRelease,
adsrRelease,
adsrReset
};

There is the option of configuring a timing pin so that both the time within the interrupt handler, and the period of the timer can be checked.

There is also a TEST option that manually triggers different stages of the ADSR and dumps the level of one of the envelope generators out to the serial console. This makes tweaking and debugging a bit easier.

The main loop handles the IO updates:

Loop:
FOREACH DAC/EG:
Read Trigger pin
IF Trigger pin goes LOW->HIGH THEN
Trigger ADSR

Read Gate pin
IF Gate pin goes LOW->HIGH THEN
Turn on ADSR Gate
IF Gate pin goes HIGH->LOW THEN
Turn off ADSR Gate

Scan each pot and update ADSR if changed

Here is a trace of both envelopes with different ADSR values running off the same trigger and gate:

Find it on GitHub here.

Closing Thoughts

To get any practical use out of this will require some electronics. I can’t just hook the DAC up to something else and expect everything to place nicely, so that is something to consider next.

But for now, although the code is more complex than I original thought, thanks to having to handle the interplay of triggers and gates, it seems to work pretty well.

Kevin

https://diyelectromusic.wordpress.com/2024/04/07/esp32-dac-envelope-generator/

#dac #envelopeGenerator #esp32 #mozzi

diyelectromusicdiyelectromusic
2024-03-19

Something else I've been meaning to do for ages - I've started playing with some ESP32 modules. This is how I got up and running to the point of running one of my Mozzi sketches on an ESP32-WROOM-32D using the ADC inputs and the DAC output.

diyelectromusic.wordpress.com/

Photo of a cheap ESP32-WROOM-32D DevKit on a solderless breadboard with some passive circuitry linking it to a TRS socket and a potentiometer plugged into one of the IO connections.
2024-03-19

I’ve been meaning to do something with the ESP32 for some time. I have some general ESP32-C3 devices, and a range of XIAO ESP32 (S2 and C3) devices too, but what I was particularly interested in was the original ESP32 as it includes two 8-bit DACs.

This is my first set of experiments using a cheap ESP32-WROOM-32D devkit available from various online sites.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

If you are new to microcontrollers, see the Getting Started pages.

ESP32 WROOM DevKit

The ESP32 is a whole range of powerful 32-bit microcontrollers that include Wi-Fi and Bluetooth. They can be programmed via the Arduino IDE using an ESP32 core from Espressif.

I was particularly after the original ESP32, so not one qualified with a S2, S3, C3, or similar reference. This is based on the dual-core Xtensa 32-bit LX6, running between 80 and 240 MHz. As well as Wi-Fi and Bluetooth there is a full range of embedded peripherals, including two 8-bit DAC outputs alongside a number of ADC inputs, and built-in 4Mb SPI flash.

Note: these are not recommended for new designs now, as updated and more powerful devices are available, but they are still readily available in a range of formats.

It should also be noted that 8-bit isn’t particularly great for a DAC for audio. For a more useful audio quality resolution really an I2S peripheral and higher resolution DAC would be much better, but for my messing around, having no additional components is worth it for me.

Here are the basic references required to get going:

To install via the Arduino board manager, add in the board URL as described in the installation guide, then when searching for ESP32 the Espressif core should be listed.

There are a range of devkits around and not all the pinouts are the same. There is an official Espressif DevKit (V4 at the time of writing), but I ended up with one including a ESP32-WROOM-32D module which the listing suggests has the following pinout:

Warning: I’m not convinced of the accuracy of that pinout! For one thing, there are two sets of pins apparently linked to ADC 1.4 and 1.5. From other pinout diagrams I’ve seen, and going back to the datasheet for the ESP32, the labels for ADC 1.4 to 1.9 on the bottom left should read ADC 2.4 to 2.9.

I’m now wondering if the one here is more accurate: https://mischianti.org/doit-esp32-dev-kit-v1-high-resolution-pinout-and-specs/. Basically, the GPIO numbers should be checked off against the datasheet when it comes to additional functions. The DAC does appear to be on GPIO 25 and 26 though.

As a test, once the ESP32 core is installed, select the ESP32-WROOM-DA module from the Arduino board menu, open the blink application and add the following line at the top of the file:

#define LED_BUILTIN 2

This is because my DevKit has an LED on D2 (there are two surface mount LEDs labelled PWR and D2 as per the diagram above) but LED_BUILTIN is generally undefined by default.

The code should build, download, and run and result in the on-board LED flashing as expected.

Parts list

  • ESP32-WROOM-32D DevKit
  • 1x 10uF electrolytic or non-polar capacitor
  • 2x 1KΩ resistors
  • 1x TRS breakout
  • Breadboard and jumper wires
  • Optional: Several 10KΩ potentiometers

The Circuit

These modules are pretty wide, so only just fit onto a solderless breadboard and then only with one row of holes down one side exposed, so they aren’t particularly practical on that front! But that is enough for some simple tests.

The DAC outputs can be found on GPIO25 and 26. Mozzi treats them both the same when in mono mode. The output of the DAC will be just over 0V to just under 3.3V. Using a coupling capacitor to remove the DC bias could get this to be approx +/- 1.6V. That is a little high for a line level signal so I use a 1K/1K potential divider to half that to around +/- 800mV.

I believe the current limit for GPIO pins on the ESP32 is 40mA, but a line input should be fairly high impedance anyway so that shouldn’t be an issue as I understand things.

Pretty much every audio circuit I’ve seen hanging off the DAC pins, pipes them into a small audio amplifier, but with the above circuit, I feel relatively happy plugging it into my sacrificial line-level mini amplifier.

As an additional test, potentiometers can be connected up to 3V3 and GND and with the wiper easily connected to any of the following pins: GPIO 13, 12, 14, 27. Connecting to 3V3 is a bit more of a challenge, but I used a jumper wire from beneath the ESP32 to connect round to the breadboard’s power rails.

Note: they must NOT be connected to VIN which is sitting at the USB 5V level.

The following diagram shows one potentiometer connected to GPIO 13, with extension wires for other pots on 12, 14 and 27.

The Code

Once the blink test is successful, then a simple Mozzi test can be performed. By default, Mozzi will output to the DAC with a mono feed going to both pins, so the starting point would be to try the following:

  • Examples/Mozzi/01.Basics/Sinewave
  • Examples/Mozzi/06.Synthesis/FMSynth

Note that there are a whole lot of additional Arduino examples to explore the capabilities of the ESP32 before getting to Mozzi if required. These are found under the “Examples for ESP32” sub-menu once the core is installed, as detailed here: https://github.com/espressif/arduino-esp32/tree/master/libraries

To run a potentiometer test requires the use of analogRead with the GPIO pin number. So if the easily accessible GPIOs are used as described previously, then the following code could test that.

#define NUM_POTS 4
int potpins[NUM_POTS] = {
13, 12, 14, 27 // ADC 2.4, 2.5, 2.6, 2.7
};

void setup() {
Serial.begin(9600);
}

void loop() {
for (int i=0; i<NUM_POTS; i++) {
int aval = analogRead(potpins[i]);

Serial.print(aval);
Serial.print("\t");
}
Serial.print("\n");
delay(100);
}

The analog to digital converters are 12-bit compared to the Arduino Uno’s 10-bit. This means that the values range from 0..4095 rather than 0..1023.

Assuming everything is successful so far then it should be possible to use the code from Arduino Multi-pot Mozzi FM Synthesis – Revisited and related projects, but the scaling of the potentiometer will have to reflect the additional range of values.

One example configuration could be:

//#define WAVT_PIN 1  // Wavetable
#define INTS_PIN 13 // FM intensity
#define RATE_PIN 12 // Modulation Rate
#define MODR_PIN 14 // Modulation Ratio
//#define AD_A_PIN 5 // ADSR Attack
//#define AD_D_PIN 8 // ADSR Delay
#define FREQ_PIN 27 // Optional Frequency Control

As mentioned, all the calls to analogRead will need to be shifted down by an extra 2, but as in later versions of the code I’ve used a myAnalogRead function, I can do this all in one place with the following implementation for the ESP32:

int myAnalogRead (int pot) {
#ifdef POT_REVERSE
return 1023 - (mozziAnalogRead(pot)>>2);
#else
return mozziAnalogRead(pot)>>2;
#endif
}

One final update once again is to define the MIDI LED to use D2 rather than LED_BUILTIN.

Adding MIDI

To add serial MIDI (USB MIDI is not supported on the original ESP32) requires a 3V3 compatible MIDI module (see here, here or here for some options).

Once again I’ve made connections beneath the ESP32 board for GND, RXD and TXD.

I’ve used GPIO 3 and 1 which are RXD0 and TXD0 respectively. These are shared with the USB interface, so links here must be removed when reprogramming the ESP32 (just like with an Arduino Uno or Nano). There is a second hardware UART on GPIO 16 and 17 (RXD, TXD) which could be used instead (or in addition to) if required.

I’ve also highlighted above where additional potentiometers could be added – a further six on GPIO 33, 32, 35, 34, 39 and 36. Consequently an alternative pot configuration using six pots for a fuller synth with MIDI could be:

#define WAVT_PIN 33  // Wavetable
#define INTS_PIN 32 // FM intensity
#define RATE_PIN 35 // Modulation Rate
#define MODR_PIN 34 // Modulation Ratio
#define AD_A_PIN 39 // ADSR Attack
#define AD_D_PIN 36 // ADSR Delay

The photo at the top of this post shows my Analog IO Board and 3V3 MIDI Module hooked up to provide a nice little MIDI FM synth.

Find it on GitHub here.

Closing Thoughts

This is a really good starting point with a relatively new (to me) architecture. There is a lot of potential use here, with so many ADC inputs, two DAC outputs and even the Wi-Fi for future use. It will also be interesting to see how the dual cores could be used too.

To really do some more complex experiments though I think I’ll need a ESP32 audio/mozzi experimenter PCB along the lines of my Nano and XIAO boards, especially as these modules are quite wide. If I was feeling really brave, I could even design around the actual EP32-WROOM module itself rather than one of these DevKits…

But this all proved relatively straight forward to get set up and running so far.

Kevin

https://diyelectromusic.wordpress.com/2024/03/19/esp32-and-mozzi/

#analog #dac #define #else #endif #esp32 #ifdef #mozzi

2023-01-10

A fun but challenging model kit I've been working on and off on and adding to for a while.

Paperboard kit of the Hogwarts Express train plus station, Harry, Ron, and flying car:

https://www.4dmodelkit.com/products/harry-potter-hogwarts-express

The train and tracks are almost 3 feet long.

I added an
#Arduino Nano with the #Adafruit #Neopixel, #Mozzi, and #Talkie libraries, piezo speakers, and #WS2812 LEDs to give it music, sounds, and flickering engine, coalbox, and passenger compartment lights.

2023-01-10

A fun but challenging model kit I've been working on and off on and adding to for a while.

Paperboard kit of the Hogwarts Express train plus station, Harry, Ron, and flying car:

https://www.4dmodelkit.com/products/harry-potter-hogwarts-express

The train and tracks are almost 3 feet long.

I added an
#Arduino Nano with the #Adafruit #Neopixel, #Mozzi, and #Talkie libraries, piezo speakers, and #WS2812 LEDs to give it music, sounds, and flickering engine, coalbox, and passenger compartment lights.

r41n3r burkh4rd7 ❌logorok@social.tchncs.de
2023-03-05

I found a forgotten #frontpanel for #Hagiwo FM and Chords #VCO in my drawer, so I built it.

#Arduino #Nano #Mozzi #Library #DIY #synthesizer

#synthdiy @synthdiy

Synthesizermodul mit zwei Arduino Nano. BestückungsseiteFrontplatte eines Synthesizermoduls, weiß mit blauer Beschriftung im Buchla 100 StyleSynthesizermodul, Lötseite der Platine
Tod Kurt (todbot)todbot
2023-02-11

@davedarko @adafruit oh and if you like droning wub, then you might like the "eighties_dystopia.ino" that should work on your setup too. No UI! github.com/todbot/mozzi_experi
Here's what it sounds like

diyelectromusicdiyelectromusic
2023-01-12

Here is the last part of my @arduino Make Your Uno series for the time being - putting everything together for a MIDI Mozzi FM synth using the Synth Shield.

diyelectromusic.wordpress.com/

Photo of a MIDI keyboard connected via a DIY MIDI interface to an Arduino Make Your Uno Synth Shield.

Client Info

Server: https://mastodon.social
Version: 2025.04
Repository: https://github.com/cyevgeniy/lmst