Download free music MP3s on genuine quality, the world’s largest online music catalogue, powered by your scrobbles. Free listening, videos, photos, The world’s largest online music catalogue, powered by your scrobbles. Free listening, videos, photos, stats, charts, biographies and concerts. stats, charts, biographies and concerts.
Friday, June 27, 2025
XIAO ESP32-C3 MIDI Synthesizer – Part 4
In Part 2 I looked at how to add USB MIDI to the XIAO MIDI Synthesizer and in Part 3 I looked at some of the properties of the SAM2695 synth chip itself. This post combines the two into a relatively simple, but playable, synth. https://makertube.…
In Part 2 I looked at how to add USB MIDI to the XIAO MIDI Synthesizer and in Part 3 I looked at some of the properties of the SAM2695 synth chip itself. This post combines the two into a relatively simple, but playable, synth.
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.
The Circuit
I'm wanting to plug a USB MIDI keyboard into my XIAO Synth, so I'm going to swap the XIAO ESP32-C3 out once again for a XIAO SAMD21 as described in Part 2. A future post will go back and create a serial MIDI version using the unmodified XIAO Synth.
Recall that a source of 5V power is required, and below I'm just using the 5V USB passthrough from the original XIAO ESP32-C3.
There is one issue to watch out for in this kind of configuration. Depending on how the USB power is provided, there might not be a common ground point between the XIAO's power and any audio amplification used.
Apparently GND is always passed through many USB charger blocks.
To prevent interference and noise, it may be necessary to ground the USB connection providing power.
The Code
I'm using a combination of the SAMD21 USB Host Library "USB MIDI Converter" example and some GPIO and MIDI handling.
The general thread of the code will be as follows:
loop(): Do any USB host processing (e.g. plug-and-play) IF USB MIDI messages received THEN Send to serial MIDI IF any buttons pressed THEN Handle button IO Generate any additional MIDI messages as required Send to serial MIDI
In particular it should be noted that the MIDI "listening" is one-way only USB to serial MIDI; and that any internal control events that generate MIDI are also only going one way - to serial MIDI.
The buttons will be used to do the following:
Button 0 and 1: Program Select Up/Down
Button 2 and 3: Channel Volume Up/Down
A much more sophisticated interface could be developed - e.g. using one of the buttons to change modes for the other buttons, to allow the selection of different things, but for now, this is plenty.
There are several layers to the code to allow this however, so I'll cover them briefly here.
Main Loop button IO: Checks for the main H->L, L->H, L->L, H->H events and calls functions for all but the last (buttons are pulled high so H->H means "nothing happening).
Event functions for Pressed, Released, Hold which call program or volume handling functions as required.
Program/volume handling functions that update the values and then trigger the appropriate MIDI messages to be sent.
Functions to send a MIDI Program Change or Control Change message as required.
In the end I've only triggered events on button Pressed, so the Release and Hold functions don't cause any further action to take place, but the model is there for use in the future if required.
Note: as I'm not using the Arduino MIDI Library, I just build PC or CC messages directly and call out to Serial1.Write as shown below.
Simple, but it works. Note PC are only two bytes in size not three.
If performance seems to be an issue, then I have a few things to adjust in the scheduling:
I can split the digitalRead() of each button over several scans to allow MIDI processing to happen in between.
I can switch to the XIAO equivalent of direct PORT IO to try to read all IO pins at the same time. I don't know what this looks like for the SAMD21 however and it would make it hardware specific, so I'd really rather not do that.
I can remove the waiting of 1mS. This was in the original USB converter, so I kept it in here too. I ought to measure the free running loop() time to see if it is needed.
Find it on GitHub here.
Closing Thoughts
In the video I cycle through a few of the programs whilst controlling the synth from a keyboard.
At one point I remove the external audio connection (yes, I should have turned it down first!) to contrast the sound with the internal speaker. Yes, it is a bit "tinny" but it isn't too bad.
This really is just the very "tip of the iceberg" given the whole range of parameters available that were mentioned in Part 3.
No comments:
Post a Comment