XIAO ESP32-C3 MIDI Synthesizer – Part 6

Expanding on my previous posts, I thought it might be interesting to see how I might be able to add some additional IO to the MIDI Synth. This is an exploration of some options there.

  • Part 1 – Getting started and getting code running.
  • Part 2 – Swapping the ESP32-C3 for a SAMD21 to get USB MIDI.
  • Part 3 – Taking a deeper look at the SAM2695 itself.
  • Part 4 – A USB MIDI Synth Module using the SAMD21 again as a USB MIDI Host.
  • Part 5 – A Serial MIDI Synth Module using the original ESP32-C3.
  • Part 6 – Pairs the Synth with a XIAO Expansion board to add display and potentiometers.

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 Synth Grove Connector

One option to immediately explore for me was the Grove connector on the Synth – highlighted by the blue rectangle in the photo below. I’m thinking at this stage of the XIAO Expander Module (more here) and how that might give some options for easily hooking up to the Synth.

There one obvious issue with this, and one not so obvious issue.

First, of course, there is no access to this connector through the case. My initial thought was to simply remove the PCB from the case and use it as a stand-alone board. On initial inspection it seemed that there were two screws holding it down. Not so, a more thorough inspection (after remove the two screws and still not being able to remove it), revealed a third screw underneath the “light pipe” for the LEDs.

Unfortunately that light pipe is pretty well wedged into the case making removal particularly tricky. But without removing the light pipe, it isn’t possible to get to the screw at all.

I did wonder about making a hole in the 3D printed case. A better option might be to get hold of the published 3D print files and add a hole and make my own (they are available via the product page).

But both options would probably end up changing the original case somehow – even if printing my own, I still need to get the original PCB out somehow and that brings me back to the light pipe issue.

The second issue isn’t quite so obvious. In that photo we can see that the pins for the Grove connector are labelled as follows (top to bottom):

  • NC
  • TX
  • 5V
  • GND

The UART on the XIAO expander board, which I’d like to use, is labelled:

  • RX7
  • TX6
  • 3V3
  • GND

Checking in with the Synth schematic, the connector is wired as follows:

SYS_MIDI connects to the MIDI_IN pin of the SAM2695, so actually connecting “TX to TX” in this instance should be ok.

5V might be an issue though, as it really does look like (to me) that it really means 5V – it is the input to the TPL740F33 that generates the 3V3 power signal, as well as feeding the amplifier directly. The datasheet of the TPL740F33 does seem to imply that if receiving 3V3 it can still generate 3V3 so it might be ok? The amplifier obviously won’t be as powerful though running off 3V3.

Anyway, for now, instead I’ve just opted to use the GPIO again, wired into the expansion sockets with the XIAO removed.

At the XIAO expander end, I’ve used the additional pins rather than the Grove connector, as they support a 5V output.

The downsides to this approach:

  • I’m not using the Grove connectors, which would have been really neat.
  • I have no access to the four buttons on the XIAO MIDI Synth.

But I do now have access to two I2C Grove connectors, a GPIO Grove, and the RX part of the UART Grove too as well as the on-board display.

If a XIAO SAMD21 is used, then the previous code for USB to the Synth can be used directly – see XIAO ESP32-C3 MIDI Synthesizer – Part 2.

If the XIAO ESP32-C3 is used, then an additional serial MIDI connection is required. This can be connected to the Grove UART connector (using the RX pin, and leaving TX unconnected) or the RX pin of the additional 8-way pin header on the expansion board. Then the code from this will work directly: XIAO ESP32-C3 MIDI Synthesizer – Part 5.

Adding a Display and Program Control

I already have some code that has done this for a XIAO on an expansion board here XIAO SAMD21, Arduino and MIDI – Part 6.

But for this to work usefully with the Synth module, I need to adjust the routing so that MIDI goes from USB to serial, but the program change messages are also sent via serial to the synth module. That has already been address in previous parts, to I just need to merge the code with that from XIAO ESP32-C3 MIDI Synthesizer – Part 4.

This is the result.

There is a bit of jitter on the analog pot, but that is only because I’m using the original fairly simplified algorithm to detect changes. If I was fussed about it, I’d reuse the averaging class from Arduino MIDI Atari Paddles. And to be honest, a capacitor on the pot would probably go quite a long way too…

As a test, I also powered the device from the Grove UART port connecting it as follows:

  • Expander GND – GND Synth
  • Expander 3V3 – 5V IN Synth
  • Expander TX – RX/D6 Synth
  • Expander RX – N/C

And this all worked fine. So I think a Grove to Grove lead would work fine if I had access to the Synth’s Grove port.

This does mean that the exact same code can work with the M5 Synth module using a Grove to Grove lead. The downside of this, even though it is a lot simpler in connectivity terms, is that there is now external audio out like there is on the XIAO Synth.

For completeness the same code can be used with the XIAO ESP32-C3 and serial MIDI, see the photo at the start of this blog.

To turn off all USB handling in the code, the following must be commented out:

//#define HAS_USB
//#define SER_TO_USB
//#define MIDI_USB_PCCC

For other parts of the code, the Arduino abstraction for A0 maps over to the ESP32-C3 fine. The only thing to watch out for is the increased analog resolution from 10 to 12 bits, but a call to analogReadResolution(10) drops that back to the expected 10 bits.

Oh and the Serial port to use is different:

  • XIAO SAMD21: Serial1
  • XIAO ESP32-C3: Serial0

Find it on GitHub here.

Closing Thoughts

If I can be bothered, it would be nice to actually display the General MIDI voice name on the display. The SAM2695 also has its MT-32 mode, so having some means of selecting that might be interesting too.

And so far I’ve largely only messed about with driving it on a single MIDI channel, so there is a lot more that could be done there.

Kevin

#controlChange #esp32c3 #midi #programChange #SAM2695 #samd21 #usbMidi #xiao

XIAO ESP32-C3 MIDI Synthesizer – Part 5

So I was somewhat guilty that I’d replaced the XIAO microcontroller in the last couple of parts to get USB MIDI, so in this one I put the original ESP32-C3 back in and now have a version of Part 4 for serial MIDI.

  • Part 1 – Getting started and getting code running.
  • Part 2 – Swapping the ESP32-C3 for a SAMD21 to get USB MIDI.
  • Part 3 – Taking a deeper look at the SAM2695 itself.
  • Part 4 – A USB MIDI Synth Module using the SAMD21 again as a USB MIDI Host.
  • Part 5 – A Serial MIDI Synth Module using the original ESP32-C3.
  • Part 6 – Pairs the Synth with a XIAO Expansion board to add display and potentiometers.

https://makertube.net/w/wez7y8WrxrNgkF1F1QX2AX

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

This goes back to adding a 3V3 compatible serial MIDI board using the XIAO GPIO breakout pins as described in Part 1.

This is powered from 3V3 and GND and connected to D6/RX (which may or may not be GPIO 6).

The Code

This is all the same code from Part 4 but with the USB handling removed and the bespoke serial port writing replaced with calls into the Arduino MIDI Library using Serial0 as the MIDI device:

MIDI_CREATE_INSTANCE(HardwareSerial, Serial0, MIDI);

void midiSendProgram (uint8_t prog) {
MIDI.sendProgramChange(prog, MIDI_CHANNEL);
}

void midiSendControl (uint8_t cmd, uint8_t d) {
MIDI.sendControlChange(cmd, d, MIDI_CHANNEL);
}

void setup() {
MIDI.begin(MIDI_CHANNEL);
...
}

void loop() {
MIDI.read();
...
}

Once again I’m relying on the fact that the serial MIDI transport has an automatic MIDI THRU enabled between RX and TX.

Find it on GitHub here.

Closing Thoughts

Whilst the USB MIDI host solution is a lot more convenient in terms of being able to plug in MIDI controllers, the serial MIDI version is a lot easier when it comes to programming and powering the device.

The video shows a PC streaming a MIDI file to the XIAO Synth whilst I’m changing volume and voice.

Kevin

#controlChange #midi #programChange #SAM2695 #xiao

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.

  • Part 1 – Getting started and getting code running.
  • Part 2 – Swapping the ESP32-C3 for a SAMD21 to get USB MIDI.
  • Part 3 – Taking a deeper look at the SAM2695 itself.
  • Part 4 – A USB MIDI Synth Module using the SAMD21 again as a USB MIDI Host.
  • Part 5 – A Serial MIDI Synth Module using the original ESP32-C3.
  • Part 6 – Pairs the Synth with a XIAO Expansion board to add display and potentiometers.

https://makertube.net/w/kaZT6zPjKUmGQp17J15fMM

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.

void midiSendControl (uint8_t cmd, uint8_t d) {
uint8_t buf[3];
buf[0] = MIDI_CC | (MIDI_CHANNEL-1);
buf[1] = cmd;
buf[2] = d;
Serial1.write(buf, 3);
}

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.

Kevin

#controlChange #midi #programChange #SAM2695 #samd21 #usbHost #xiao

Duppa I2C MIDI Controller 3D Print Case

This is a simple 3D printed case for my Duppa I2C MIDI Controller PCB.

https://makertube.net/w/nf7u1sYBRRzj2TUBRduQC2

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.

Parts list

OpenSCAD Design

This uses some of the techniques from my Raspberry Pi 2,3,4 A+/B+ Synth Cases to define a basic box, then some cut-outs, and then to split the box and add some overlapping “lips” for a snap-fit.

There a number of functions to achieve this, but some of them are just collecting together the others in the right sequence.

  • rounded – a basic “rounded” box module.
  • standoff – the PCB supports.
  • build_lips/build_lip – as expected, creates the overlapping lips. There is a parameter (solid) which determines if the lip is added to or subtracted from the case.
  • base – the main box shape, less the actual top.
  • top – the top plate that includes holes for the potentiometer and the LED ring.
  • box – uses base() and top() to build a complete box.
  • box_base/box_top – uses box and an intersection to produce the two halves of the main box.

At the top level box_base, box_top and standoff (four times) actually builds the complete case.

In terms of assumptions about the build:

  • Most importantly, this assumes the use of PH5.0 headers to mount the Waveshare Zero device.
  • It also assumes the use of a serial MIDI TRS socket.
  • It should allow for M3 spaces and is build to assume two sets of 10mm spacers as described in the Build Guide.

Notes on printing:

  • I found getting adhesion for the top with all those circular holes quite a challenge. In the end I increased the bed temperature and slowed the print right down to around 40% for the first layer and that seemed to improve thing quite a bit.
  • Once complete I had to tidy up the LED holes a little by hand with a 2.5mm drill bit.
  • The additional tag above the USB socket is quite delicate, so care is needed when snapping the case together.

Errata/Improvements:

  • For my own build, the potentiometer shaft doesn’t stick out as much as I’d like. It is hard to find a knob that doesn’t have to be altered to fit and stay in place.
  • I did wonder about using a thinner layer of 3D print over the LEDs rather than complete holes. I might still try that as an option to see how it works.

Find it on GitHub here.

Closing Thoughts

This is a little tall, but I’m not sure what, in reality I could do about that. There might be some option for shrinking it a little, especially if the Waveshare Zero RP2040 is soldered directly to the PCB. But it would only save, maybe up to 6 mm in height, so it is probably not worth the effort.

But apart from that, this seems to have come out really well. The holes the LEDs I thought were perhaps a bit of a compromise, but actually they seem to work fine.

Kevin

#controlChange #duppa #midi #potentiometer #WaveshareZero

Duppa I2C MIDI Controller PCB Build Guide

Here are the build notes for my Duppa I2C MIDI Controller PCB.

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.

Bill of Materials

  • Duppa I2C MIDI Controller PCB (GitHub link below)
  • Waveshare Zero format dev board
  • 1x Duppa Small RGB LED Ring
  • 10KΩ potentiometer
  • 5-pin plug and lead (see photo).
  • 1x 100nF ceramic capacitor
  • Optional: 1×10Ω, 1×33Ω resistor
  • Optional: 1x 3.5mm stereo TRS socket – PCB mount (see footprint and photos)
  • Optional: 2x 9-way header sockets. Ideally low-profile, PH5.0 sockets.

There are a range of possibilities for the potentiometer, so one has to consider if mountings are required or if a knob will be used. These are some of the pots I could have used:

I used the one with a nut in the end and plan to add a knob at some point.

On that lead… The Duppa ring is described as requiring a “5-way Molex Picoblade, 1.25mm pitch” connector. The lead I ended up with was described on an online, overseas marketplace, as “JST 1.25mm” which I’m not sure is strictly a thing, but that is what worked for me.

Build Steps

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

  • Resistors and diode.
  • Disc capacitors.
  • TRS socket (if used).
  • If using headers for the devboard, now is a good time to solder those.
  • Potentiometer.
  • Duppa connector cable.

Be sure to get the connector cable the right way round. For the colouring of the cable above, and orientation of the pins, the I2C connectors ended up being the red and black ones for me. More about that in a moment.

Here are some build photos.

The cable has to be cut and then positioned to correctly align with the positions of the wires on the Duppa connector. The following shows which wires align to which solder pads and the position in the connector.

Once all soldering is complete, I used 8x 10mm M3 spacers as shown below.

I’m planning on designing an enclosure that the above posts will slot into. You may need different senses and sizes of spacers depending on your final arrangements.

Testing

I recommend performing the general tests described here: PCBs.

Note that the LED ring is configured using solder jumpers as described previously, for S1, S5 and to use pull-ups, as shown below.

PCB Errata

There are the following issues with this PCB:

  •  None at this time.

Enhancements:

  • The schematic already supports MIDI IN in addition to MIDI OUT, so at some point I could add that too. 

Find it on GitHub here.

Sample Applications

This is designed for use with my Duppa I2C MIDI Controller – Part 4. The Arduino code for that works directly when used with a Waveshare Zero RP2040 with the following configuration:

#define WAVESHARE_RP2040

#define MIDI_USB
#define MIDI_SER

#define LED_PER_CC
#define LED_SCALE_TO_RING

#define CC_POTENTIOMETER
#define PIN_ALG A3
#define MAX_POT_VALUE 1023

The full code is available on Github here.

Closing Thoughts

I’m really pleased with how this turned out. These LED rings are really neat!

Now on to that case…

Kevin

#controlChange #define #midi #pcb #potentiometer #WaveshareZero

Duppa I2C MIDI Controller PCB Design

This is the design for a simple carrier PCB for a Waveshare Zero format microcontroller and a Duppa small LED Ring. It is essentially a PCB version of Duppa I2C MIDI Controller – Part 4. Warning! I…

Simple DIY Electronic Music Projects

Duppa I2C MIDI Controller PCB Design

This is the design for a simple carrier PCB for a Waveshare Zero format microcontroller and a Duppa small LED Ring. It is essentially a PCB version of Duppa I2C MIDI Controller – Part 4.

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.

The Circuit

This connects a Waveshare Zero format board to a MIDI IN and OUT interface and a potentiometer. There is a header required to connect to the Duppa Small LED ring.

The following IO pins are used:

Physical PinGPIO: C3, S3, RP2040Function1Power5V2GroundGND3Power3V34GP0, GP1, A3Potentiometer13GP9, GP10, GP5LED SCL14GP10, GP11, GP4LED SDA17GP20, RX, GP1MIDI RX18GP21, TX, GP0MIDI TX

For the RP2040 this is using I2C0 and UART0.

PCB Design

I’ve actually opted not to include MIDI IN functionality in order to keep within a minimal PCB footprint. I’m aiming to have it occupy essentially the same space as one of the small Duppa LED rings itself. I’m also only support MIDI OUT via a TRS jack.

But I have attempted to ensure that both the Waveshare USB socket and TRS socket will protrude enough to be brought out to the edge of a case.

I’ve included a 2.54mm pitch set of header pads that I plan to solder a connecting wire to for the Duppa ring.

Closing Thoughts

I was in two minds about including MIDI IN. It is nice to be able to use this to merge into an existing MIDI stream, but then I also considered that it would probably be used just as a controller in most cases, so went with the small PCB footprint.

I also considered the four control options I’ve experimented with so far. In the end I decided I still liked having an absolute-value potentiometer for a MIDI Controller like this over either a rotary encoder or an endless potentiometer, so that is what I’ve used.

Kevin

#controlChange #midi #pcb #potentiometer #WaveshareZero

Duppa I2C MIDI Controller – Part 4

This is revisiting my Duppa I2C MIDI Controller this time using a Waveshare Zero format device. Part 1 – getting to know the devices and testing them out. Part 2 – adding MIDI…

Simple DIY Electronic Music Projects

Duppa I2C MIDI Controller – Part 4

This is revisiting my Duppa I2C MIDI Controller this time using a Waveshare Zero format device.

  • Part 1 – getting to know the devices and testing them out.
  • Part 2 – adding MIDI to the LED ring and I2C encoder.
  • Part 3 – adding normal encoder, plain potentiometer, and endless potentiometer control.
  • Part 4 – revisits the idea with Waveshare Zero format devices and adds USB MIDI.

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 Arduino, see the Getting Started pages.

Parts list

  • Waveshare Zero ESP32-S3 or RP2040.
  • DuPPa small RGB LED Ring.
  • 10K potentiometer.
  • Bespoke hook-up wires (available from duppa.net).
  • Optional: 3V3 MIDI Interface.
  • Breadboard and jumper wires.

Waveshare Zero, Duppa LED Ring, Potentiometers

I’m planning on being able to use any Waveshare Zero format board that I have (so that includes ESP32-S3, ESP32-C3 and RP2040) with the Duppa Ring so that means finding common pins to support I2C.

From the various pinouts (see Waveshare Zero, Pimoroni Tiny, and Neopixels) I can see I can use two pins in the bottom right-hand (with the USB connector at the top) corner of the board.

I’ll also need an analog connection and potentially connecting RX/TX to MIDI.

The various pins I’ll be using are as follows:

PinFunctionESP32-S3ESP32-C3RP204015V2GND33V34ADCGP1GP0GP29/A313SCLGP10GP9GP514SDAGP11GP10GP417RXGP44GP20GP118TXGP43GP21GP0

Note, I’m not using physical pins 11 and 12, even though they also support I2C, as for the RP2040, these are on I2C bus 1, not 0 (see note later).

As the Pimoroni Tiny2040 is largely compatible too, that could also be used, but it will be physical pins 11 and 12, corresponding to GP5 and GP4, and 15 and 16 for GP1, GP0 (RX,TX).

The LEDs on the LED ring are powered from 5V, which comes directly off the Waveshare Zero USB port. The logic “VIO” is powered from 3V3.

The Code

I2C LED Ring

As the I2C pins to be used are configurable, this means changing the Duppa example code (and any other Arduino code) to initialise the I2C bus on specific pins as follows:

Wire.begin(11,10); // SDA, SCL for ESP32-S3
Wire.begin(10,9); // SDA, SCL for ESP32-C3

Using the ESP32 Arduino Core, there is a specific board entry for the Waveshare Zero ESP32-S3. There isn’t one for the ESP32-C3 so I just used “ESP32C3 Dev Module”.

I used the Arduino core for RP2040 from here rather than the official core: https://github.com/earlephilhower/arduino-pico

But the I2C initialisation is a little different.

Wire.setSDA(4);
Wire.setSCL(5);
Wire.begin();

If I’d have been using GP6 and GP7, then these would have required the initialisation of Wire1 rather than Wire with the RP2040 core.

Note: to use the serial port once a sketch has been loaded onto the board, requires the following to be set (via the Arduino Tools menu):

USB CDC On Boot -> Enabled

Once again, I’ve soldered the jumpers on the LED ring to enable pull-ups and set the address for S1 and S5, so that has to be changed in the demo code too.

Analog Potentiometer

In terms of analog read, the ESP32 has a resolution of 0..4095 compared to the Arduino’s 0..1023, so that has to be taken into account when calculating the MIDI CC values.

To do this, the reading has to be divided by the ratio of Pot Range / 128.

int newpot = algpot.avgeAnalogRead(PIN_ALG) / ((MAX_POT_VALUE+1)/128);

Serial MIDI

For these boards, the serial port has to be specified. There are different options depending on the board being used (more here).

To use the pins nominally designated as RX/TX on all of these boards, use:

// ESP32-S3 GP43,GP44 or ESP32-C3 GP20,GP21
MIDI_CREATE_INSTANCE(HardwareSerial, Serial0, MIDI);
// RP2040 GP1,GP0
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);

It is a quirk of the RP2040 Arduino core that UART0 appears on Serial1 and UART1 on Serial2. Serial0 does not exist but USB is Serial (more here).

Also, for the RP2040 the pins can be changed prior to calling MIDI.begin() if required as follows:

Serial1.setRX(rxpin);
Serial1.setTX(txpin);
MIDI.begin();

MIDI USB

I want to make this a fairly stand-alone MIDI USB device, so for the ESP32 and RP2040 this means using the TinyUSB stack. There is an Adafruit library for Arduino that supports both and also works with the Arduino MIDI Library. References:

I’ve cribbed most of the code from: https://github.com/adafruit/Adafruit_TinyUSB_Arduino/blob/master/examples/MIDI/midi_test/midi_test.ino

And added the appropriate parts to my own midiSetup() and midiLoop() functions.

MIDI USB – ESP32-S3

For this to work on the ESP32-S3, the board settings (via the Arduino Tools menu) need to be changed as follows:

USB CDC On Boot -> Enabled
USB Mode -> USB-OTG (TinyUSB)
USB Firmware MSC On Boot=Disabled
USB DFU On Boot=Disabled

Naturally this means USB can’t be used for serial output anymore.

It also means that automatic sketch reset and download often didn’t work for me. It was quite normal to now have to use the BOOT and RESET buttons to get the ESP32 back into listening for a new sketch – not always, but also not uncommon. But this might be some serial port remapping weirdness that often occurs when the USB stack is running on the same microprocessor as the main code…

MIDI USB – RP2040

For the RP2040, the USB stack needs to be changed from the Pico SDK to TinyUSB, so in the Tools menu:

USB Stack -> Adafruit TinyUSB

There are some other RP2040 specific notes here, but I don’t believe they apply unless one is interested in rebuilding the core, default TinyUSB support directly.

USB MIDI – ESP32-C3

I don’t believe USB MIDI works on the ESP32-C3

Adafruit TinyUSB doesn’t seem to anyway and I haven’t looked into what the options might be yet.

Other Notes

I’ve left in all the conditional compilation from Duppa I2C MIDI Controller – Part 3 but for now am just working with potentiometer control.

Pretty much everything is configurable, but the most important config option is to specify the board at the top:

//#define WAVESHARE_ESP32S3
//#define WAVESHARE_ESP32C3
#define WAVESHARE_RP2040

I could probably auto detect from the build settings but for now, this will do.

Other options include GPIO pins, whether to include serial or USB MIDI (or both), and whether to enable MIDI THRU or not.

Find it on GitHub here.

Closing Thoughts

This is the first go at getting my Duppa controller working on 3V3 Waveshare Zero format boards, and so far it looks pretty good.

For the ESP32-S3 and RP2040 being able to enable MIDI USB is particularly useful. I might see if I can support MIDI THRU across the interfaces, which might be handy for a built-in USB to serial MIDI converter, but for now MIDI THRU is on the same port only.

I’ve not tested this with encoders or the endless potentiometer, but in theory it ought to work. I’d have to add some conditional compilation for GPIO numbers if I want to keep the same physical pins again.

Kevin

#controlChange #duppa #endlessPotentiometer #esp32c3 #ESP32s3 #i2c #midi #potentiometer #rgbLed #rotaryEncoder #rp2040 #WaveshareZero

Duppa I2C MIDI Controller – Part 3

This is a follow up post to Part 2 expanding on the code and adding in some of the alternative control options I mentioned. Warning! I strongly recommend using old or second hand equipment for…

Simple DIY Electronic Music Projects

Vintage Rotary Phone MIDI Controller – Part 7

Having built my adaptor into a small box, I’ve gone back to add a mode button so I can include all the different applications into a single sketch.

This builds on the previous parts in this series.

  • Part 1 – Understanding the telephone hardware and interfacing to an Arduino.
  • Part 2 – Decoding the rotary dial from the Arduino.
  • Part 3 – Rotary phone MIDI note controller.
  • Part 4 – Rotary phone MIDI program change.
  • Part 5 – Rotary phone MIDI random note sequencer.
  • Part 6 – Rotary phone to MIDI adaptor.
  • Part 7 – Rotary phone multi-mode applications.

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 Arduino, see the Getting Started pages.

Parts list

  • Arduino 5V Pro Mini (as I’m soldering it in, I’m using a cheap clone)
  • “GPO” or “BT” original 746 rotary telephone
  • Scrap ADSL filter
  • 120kΩ resistor
  • 2x 220Ω resistors
  • Chassis mount 5-pin DIN socket
  • RJ11 telephone cable (cut in half) – this is the “handset” cable or possibly a “modem” cable
  • USB cable (cut in half)
  • MIDI sound module

The Circuit

The idea is to simply add a push-button switch to the build from part 6, so I’m taking that as my starting point.  I’m adding a button between D3 and GND, using it in INPUT_PULLUP mode.

I made a hole in the case and made a small cut-out in the PCB to hold the button relatively firmly in place, then connected it as shown below.

Aside: I somehow managed to break the leg off the resistor between 5V and the MIDI socket, but didn’t notice until I tried it and nothing worked – so that was a bit of a pain, as I needed to gently prize everything apart enough to get a new resistor soldered in place!

The Code

So, the main idea is to use the button to change between the various modes of the phone.  I’ve implemented the following:

  • Mode 1 – Send MIDI Control Change 16 – General Purpose Controller 1 – with the digit as the value (0 to 9).
  • Mode 2 – Play NoteOn messages for C major, starting with MIDI note 60 (C4) for 0.
  • Mode 3 – Play NoteOn messages for a pentatonic scale, as described in the “simple mode” from part 3.
  • Mode 4 – Play NoteOn messages for several pentatonic scales, as described in the “complex mode” from part 3.
  • Mode 5 – Send MIDI Program Change messages as described in part 4.

Note that I haven’t implemented the sequencer as described in part 5 as the code structure is quite different to the other modes.

Also note, if you examine the code, the modes are encoded as 0 to 4 within the code itself.

The main logic is as follows:

Loop:IF button pressed THEN switch to the next modeIF there is a new digit read THEN IF in Control Change mode THEN Send MIDI General Purpose Controller 1 CC Message with value "digit" ELSE IF in Program Change mode THEN Update the program change number ELSE Check which scale we're using AND Send the associated MIDI NoteOn message for that digit in that scaleIF phone is placed back on the hook THEN IF in Control Change mode THEN nothing to do ELSE IF in Program Change mode THEN Send the MIDI Program Change message ELSE Send a MIDI NoteOff message for all notes from all scale modes, for all digits

Once again I’ve implemented it so that all notes sustain until the phone is placed back “on hook” when I simply cycle through all notes in all scales sending NoteOff messages.  This is a little redundant but does mean that if the mode had changed after notes started playing, then all notes will eventually be turned off properly.

The last thing I’ve added was some indication of which mode we’re in.  When the button is pressed and the mode changed, it will play a few notes from the C major scale starting on C5 to indicate the number of the mode (1 to 5).

Find it on GitHub here.

Closing Thoughts

I’m still wondering if it would be better to have specific MIDI messages defined for the different events within the phone, and I’m part way there with the use of the first general purpose CC message.  It might be useful to also have a CC message defined for on-hook and off-hook too.

I’ve also wondered if I should have a mode that plays proper NoteOn/NoteOff messages when dialing.  I might still implement that for the C major scale mode – I’m still deciding!  I also use the built-in LED to indicate a button press, but I might update it to flash to indicate the mode too, again I’m not sure yet.

The MIDI channel is still hard-coded to 1, and to be honest that is fine for me for now.  I would like to find a way to get the sequencer functionality in there somehow, but need to think about that a little more. I was also wondering if I should generate MIDI real-time clock messages in response to the pulses, but again I’m still chewing that over too.  I have plenty of IO pins on the Arduino spare, but not a lot of space in the casing.

I have managed to pick up a second phone and on simple inspection it appears to be wired up the same as my original phone – but for some reason it isn’t reliably detecting pulses, so I need to look at that at some point too.

So there are still plenty of things I could do next!

Kevin

#arduino #arduinoProMini #controlChange #midi #midiController #programChange #rotaryDial #telephone

Vintage Rotary Phone MIDI Controller

I’ve wanted to do something musical with a vintage rotary telephone for a while now, so when I happened to come across one in a charity shop, I jumped at the chance to have a go! Be warned: t…

Simple DIY Electronic Music Projects