Arduino MPR121 MIDI Touch Piano

A comment on the Arduino MPR121 Touch Piano pointed out that I never went as far as building a 48-note MIDI touch piano.  In principle all the bits are there between that post and the Arduino MIDI Touch Piano so this post brings the two together to do just that.

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

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

Parts list

The Circuit

ArduinoMPR121MIDITouchPiano_bb

This is the same circuit from the “advanced” discussion of the Arduino MPR121 Touch Piano project.  It uses four MPR121 breakout boards all set to different I2C addresses with the I2C signals going through a 5V to 3.3V level shifter.  I’ve used a really cheap one that looks like this.

IMG_5225

This provides four HV to LV (5V to 3.3V) shifts and needs 5V connected to HV and 3.3V connected to LV. I only need two in this project, one for SDA and one for SCL.  Note that these work well for I2C but aren’t very good for higher speed protocols (I’ve seen quite a bit of discussion about how they mess up SPI for example).

Recall that for the breakout boards I’m using, ADDR is tied to GND by default via solder-pad jumpers.  This must be gently cut to allow ADDR to then be tied to 3.3V, SDA or SCL as required.  The addressing is as follows:

  • ADDR = GND – I2C address 0x5A
  • ADDR = 3.3V – I2C address 0x5B
  • ADDR = SDA – I2C address 0x5C
  • ADDR = SCL – I2C address 0x5D

This project needs a MIDI OUT circuit linked up to the Arduino TX pin.  I’ve used one of my Ready-Made MIDI Modules but any of the Arduino MIDI Interfaces would be fine.

IMG_5223

The Code

Once again the core of the module is the code from the Arduino MPR121 Touch Piano which is using the Adafruit library for the MPR121 boards.

It has been updated to support MIDI.  The key functionality is provided by two arrays – playing[] and lastplaying[].  There is one entry for each possible MIDI note that can be played – so 48 in total.  The playing[] array is updated based on the outputs of reading the four MPR121 boards, then the code looks for playing to not-playing or not-playing to playing transitions and sends the appropriate MIDI Note Off or On messages as required. It is thus full 48-note polyphonic in operation.

On power up, as I no longer have the serial port (although I’ve added a “serial port, not MIDI” test mode) I’ve used the build-in LED, which I’m also using as a MIDI indicator, to indicate which MPR121 boards are found.  It flashes on start up in response to which MPR121 boards are detected – once for the first; twice for the second; etc. If it continually flashes and does nothing else, then it hasn’t found any MPR121 boards.

The capacitive sensor handling itself is exactly the same as before.

Find it on GitHub here.

Closing Thoughts

The sensors are pretty sensitive, so it might be worth building in some “debouncing”, but as you can see from the video I haven’t built a keyboard itself – I’ve just show the principles by touching the sensor connections themselves.  But you can see it seems to have a full range and supports polyphony.  Notice that I should have arranged the boards in the opposite order as they are decoded “low to high” but I’ve wired them up “high to low”. Oh well, you get the idea.

It is connected to my MT-32 synth module, playing one of the Synth Brass sounds.

It might be that with some proper touch surfaces attached, the sensitivity is more useful.  I expect it is the kind of thing that will need tuning to your specific surfaces when you’ve chosen them.

Kevin

5 thoughts on “Arduino MPR121 MIDI Touch Piano

  1. Hi, really nice project!

    Can this be adapted to ESP32 over BLE?

    Something like the Lolin 32 lite, that has a built in battery charger would be perfect and will make it portable.

    Like

    1. In principle I guess it could, but I’ve not really done anything with an ESP32 or BLE so don’t really know what would be required. I know Adafruit have done quite a lot with CircuitPython on boards like this and touch-based MIDI controllers are a common application in their tutorials, so it might be worth have a browse there?

      Good luck!

      Like

  2. This looks good Kevin. I work with alternate tunings – mainly 21 notes per octave where each note has a natural,flat and sharp, so for example C# is a different frequency than Db, and so on. Technically I am using 21 out of 55 Equal Temperament, which is also known as Mozart’s orchestral tuning, also called 1/6 comma meantone.

    So, for six octaves I will need 126 keys +1 . Could your design architecture be used for this ?
    Also I would like to use Midi 2.0 if that is possible.

    Best regards

    Like

    1. If I’m totally honest – I’m not sure! I suspect starting to handle more than a few of these off the same I2C bus might start pushing things, but it might be worth a try… But IIRC there are only four selectable address lines so the maximum number of notes off one I2C link will be 48 anyway. There are I2C bus expanders that might allow eight (e.g.

      It may be that performance wise you’re better off treating each octave almost as an independent unit with its own microcontroller and then merging the MIDI messages together.

      Or it might be possible to use an alternative microcontroller that allows several I2C buses or something like the Raspberry Pi Pico with its programmable IO that may allow it to implement several I2C links on the same microcontroller. It is possible to add extra I2C buses to an Arduino but it uses a software implementation rather than hardware, so I can’t imagine the performance being that great.

      Another option might be using an I2C multiplexer such as the TCA9548A. This would allow (in theory) up to 8 separate I2C buses, each (in theory) supporting 4 MPR modules. Assuming the Arduino can cope with scanning all that and that the “main” Arduino’s I2C bus that has to tie them all together can keep up, that /might/ allow up to 32 MPR modules, each with 12 inputs so again, in theory, up to 384 inputs… But I seriously doubt that would all work in practice! You’re going to need 11 modules to cover 127 keys, so you might get away with three sets of four… but I’ve never pushed anything that far…

      It might be possible to implement “DIY touch sensitivity” on a microcontroller with a larger number of pins, such as one of the ATmega2560 based boards…

      MIDI 2.0 will almost certainly be an issue though – I’ve not used it myself and don’t tend to come across it to be perfectly honest in microcontrollers.

      There is a development platform available based on the Pico: https://amenote.com/?page_id=74
      And I’ve seen an Arduino MIDI 2.0 library: https://github.com/starfishmod/MIDI2_CPP but don’t know anything about it myself.

      And I haven’t even started on the microtuning aspects. I assume that is supported in MIDI 2.0 – is that why you want it? I guess the only way to do it in MIDI 1.0 is with continued pitch bend events…

      Nothing is impossible of course, but I suspect this would be quite a lot of work and would require a few iterations of different ideas to find the thing that works best for you. It may well be at this point that it is worth investigating a dedicated audio/MIDI controller platform for these kinds of more expressive interfaces, such as the Bela platform and its Trill sensors – see https://bela.io/. But of course that won’t be cheap! 🙂

      Kevin

      Like

Leave a comment