A fader bank and key matrix MIDI controller powered by the STM32F103
If you do orchestral programming, you know that MIDI faders are absolutely essential to achieve a sound that wouldn’t be passed of as “MIDI-like”. What happens when you really, really want a MIDI controller with a bunch of faders, but don’t feel like spending *that much* money on one?
Well, you build one.
In this series of posts, I will present my take on the DIY MIDI controller, which has 4 faders, 4 rotary encoders, and a 4×4 key matrix, all of which are fully programmable via an onboard LCD. Instead of designing a custom PCB for this project, which, in hindsight, would have greatly simplified its development, especially when it came to writing the firmware, I chose to use whatever I had on hand, which meant:
Generic Blue Pill (STM32F103C8T6), which did NOT have nearly enough IO pins
2 MCP23017 I2C IO Expanders: one driving an LCD and the other driving an LED Matrix
2 CD4051 Multiplexers interfacing the 5 rotary encoders
Turns out, not getting a microcontroller that has enough IO pins is really just asking for trouble, as the firmware for this thing could only be described as an abomination. Too many things running concurrently, all having rather strict timing requirements. I will present to you the many challenges I faced trying to get everything to work correctly together while still maintaining the responsiveness of the user interface and inputs, and how I eventually solved all of them.
The hardware is pretty routine stuff: various components connected to a microcontroller dev board in (mostly) the way you’d expect. There are a few interesting bits which arised as a result of me using all those IO expanders though, and I will cover them one by one as the series progresses.
But here is a quick overview:
User Interface
4 faders for individually assignable MIDI CC control
4 pushable rotary encoders to trigger notes and do additional MIDI CC control. All individually assignable, and each accompanied by an LED whose intensity corresponds to the value of the currently assigned CC channel.
4×4 key matrix with Gateron Yellow keyswitches, accompanied by
4×4 bi-color LED matrix to indicate the position of all the C keys
16×2 character LCD for menu and status display
1 pushable rotary encoder to navigate through the menu
Electronics
Microcontroller: STM32F103C8T6 (sorely lacks IO)
Faders are connected directly to analog input pins
Rotary encoder pushbuttons and the key matrix are also directly connected to digital IO
The 4 LED’s are also connected directly, and their brightness is varied using bit angle modulation
2 CD4051 multiplexers, breaking out 2 pins on the micro to the 10 required for the 5 rotary encoders
2 MCP23017 I2C IO Expanders
One drives the LCD. Well, sort of. I initially had the LCD completely driven by it, but turns out that all the I2C commands needed to set the control pins just got in the way, so in its current state this MCP23017 essentially drives the 8-bit data bus only.
The other drives the LCD Matrix. This one is driven by DMA, so its essentially fully autonomous. I’m really excited to share how I pulled it off, as it involved some *ahem* pretty unorthodox (according to ST’s reference manual anyways) ways of driving the micro’s I2C peripheral.
24LC128 EEPROM to store parameters between on-off cycles
Serial over the micro’s USB peripheral to handle the MIDI protocol
Power delivery is handled by a generic 3.3v LDO
3D printed case, keycaps, and fader knobs
Instead of a large schematic with everything on it, I think a better approach would be to break it up into sections: a series of posts each containing the schematic of one particular aspect of the hardware, along with a breakdown of the code required to drive it and chronicles of the many hours I spent banging my head on the table trying to fix issues that cropped up. Then, I’ll cap it off with a summary of how it all comes together, and address the various improvements that I think could be implemented.
Here we go!
STM32 MIDI Controller Part 8: Conclusion and what’s next (potentially)
Finishing this project was a huge relief, to say the least. It is truly my first project in which I designed everything from the ground up instead of just building up schematics from the internet. Thus, it was also my longest running project yet, and the amount of work that has gone into it just blows my previous endeavours out of the water.
It is also my first ever project build log/writeup, so I apologize for any mistakes or shortcomings throughout this series....
STM32 MIDI Controller Part 7: The software
Finally, we are at the end of this series, where I am going to give an overview of the software behind all the menu system and of course, all the handling of user inputs and sending of MIDI messages. We’ve spent so much time configuring the various peripherals and writing driver code to abstract away the nitty-gritty implementation stuff, this is where it all comes together!
For the project files, do check out the Github repo....
STM32 MIDI Controller Part 6: Key Matrix
Yes, this MIDI controller has a 4×4 grid that you have undoubtedly seen way too many times. No, it doesn’t have RGB
Will it actually get used? Probably not. But hey, its a great opportunity to learn some electronics! And implementing key matrices is not as trivial as you might think.
Schematic First off, if you haven’t already, check out this excellent post by Dave Dribin to learn about ghosting and masking....
STM32 MIDI Controller Part 5: Multiplexed Rotary Encoders
I really like rotary encoders as user input devices, they’re free of analog noise shenanigans, have no fixed positions, can be augmented with velocity control… Just a really nice way for the user to navigate around in menus or adjust parameters. That said, they do take up at least one extra pin per encoder compared to potentiometers, and of course, they require either polling or pin change interrupts to react to changes in the states of their pins....
STM32 MIDI Controller Part 4: Bit Angle Modulation LED Dimming
While PWM certainly is a mighty fine option to add dimming control to LEDs in your projects, there may be certain cases where it simply isn’t the best option. Maybe you don’t have enough PWM capable IO pins on your microcontroller? Or maybe manually bit-banging PWM control takes up too much CPU time? And you certainly aren’t about to fork out a bunch of cash for something like a TLC5940, and cheaper chips either are out of stock, are only stocked in pain-in-the-neck QFN packages, or are hopelessly backordered....
STM32 MIDI Controller Part 3: DMA Driven I2C LED Matrix
Staying on the topic of ways to use the I2C peripheral of the STM32F103 microcontroller, today, I’m going to discuss how I implemented a basic bi-color LED matrix based on the MCP23017 I2C I/O expander. This is not a full blown, colorful RGB LED matrix – its literally “monochrome”, but with the massive RAM of these STM32 microcontrollers, a full color LED matrix certainly seems doable with some tweaking, although at that point, I don’t see why wouldn’t you go for WS2812 or its alternatives instead....
STM32 MIDI Controller Part 2: FIFO Buffered I2C EEPROM
Early on in the conceptualization phase of this project, I wanted something that had good customisability on board. That meant that I would need some sort of non-volatile memory to store all user changeable parameters, so I wouldn’t have to set everything up all over again every time I unplugged the thing. Out of all possible solutions, EEPROM would probably be the easiest to implement.
The STM32F103 does not have internal EEPROM (unlike some AVR micros) however, and I really didn’t want to go to all the trouble to decipher ST’s emulated EEPROM library....
The problem with the simple approach In part 1A, I presented a simple approach that did the job quite well. However, since the program has to wait for the slow I2C bus to send more than 30 bytes of data every single time the LCD is fully updated, it simply wouldn’t cut it for a MIDI controller which not only has to send keypresses with as low a latency as possible, but also has to do a whole bunch of timing critical stuff like bit angle modulation, polling five rotary encoders, and multiplexing an LED matrix....
STM32 MIDI Controller Part 1A: Wrestling with I2C, MCP23017, and a 16×2 LCD
This was one hands down the most challenging and frustrating part of the entire project, involving hours of staring at the reference manual for the STM32F103 microcontroller series trying to figure out why the I2C peripheral kept locking up. Maybe its just me, but the diagrams and explanations in the reference manual for the I2C peripheral were not exactly intuitive, especially since they throw in a whole bunch of concurrent events that occur throughout the process of sending/receiving data packets, and the registers you have to read/write to placate the peripheral changes in a kinda confusing way depending on the number of data packets, the speed at which the slaves respond, etc, etc, etc…....
STM32 MIDI Controller Part 0: The case
Going into this project, I had a clear vision of what this MIDI controller would look like, and what functionality it was going to have. So, it made sense to start with CAD, since 3D printing big parts like this takes a huge amount of time, and I needed to wire everything up before I can even start developing the firmware.
I used Solidworks to design the case, keycaps, fader knobs and feet....