Each individual object in Control Surface takes up some extra RAM to support things like automatic initialization and updating. When you instantiate 32 or more buttons, this overhead adds up, and this is especially noticeable on an Arduino Uno, which has the least amount of memory of all Arduino boards.
If you want to use many buttons, the trick is to create a single object that reads all 32 buttons instead of 32 separate objects that read one button each.
I imagine your code looking something like this:
CD74HC4067 mux1 {
A0, // Analog input pin
{3, 4, 5, 6} // Address pins S0, S1, S2, S3
};
CD74HC4067 mux2 {
A1, // Analog input pin
{3, 4, 5, 6} // Address pins S0, S1, S2, S3
};
CCButton buttons[] {
{mux1.pin(0), 0},
{mux1.pin(1), 1},
{mux1.pin(2), 2},
{mux1.pin(3), 3},
{mux1.pin(4), 4},
{mux1.pin(5), 5},
{mux1.pin(6), 6},
{mux1.pin(7), 7},
{mux1.pin(8), 8},
{mux1.pin(9), 9},
{mux1.pin(10), 10},
{mux1.pin(11), 11},
{mux1.pin(12), 12},
{mux1.pin(13), 13},
{mux1.pin(14), 14},
{mux1.pin(15), 15},
{mux2.pin(0), 16 + 0},
{mux2.pin(1), 16 + 1},
{mux2.pin(2), 16 + 2},
{mux2.pin(3), 16 + 3},
{mux2.pin(4), 16 + 4},
{mux2.pin(5), 16 + 5},
{mux2.pin(6), 16 + 6},
{mux2.pin(7), 16 + 7},
{mux2.pin(8), 16 + 8},
{mux2.pin(9), 16 + 9},
{mux2.pin(10), 16 + 10},
{mux2.pin(11), 16 + 11},
{mux2.pin(12), 16 + 12},
{mux2.pin(13), 16 + 13},
{mux2.pin(14), 16 + 14},
{mux2.pin(15), 16 + 15},
};
Try replacing it with:
// Instantiate a multiplexer
CD74HC4067 mux1 {
A0, // Analog input pin
{3, 4, 5, 6} // Address pins S0, S1, S2, S3
};
CD74HC4067 mux2 {
A1, // Analog input pin
{3, 4, 5, 6} // Address pins S0, S1, S2, S3
};
CCButtons<32> buttons {
copyAs<Button>(cat(mux1.pins(), mux2.pins())), {0, CHANNEL_1}, {1, 0},
};
The cat
function concatenates the arrays of pins of the two multiplexers into one array of 32 pins, and the copyAs<Button>
function converts this array of pins into an array of buttons, which is what the CCButtons
constructor expects.
This change should save around 17% of RAM.
You can also try disabling functionality you don't need, such as MIDI SysEx input support or being able to invert individual buttons.
I've just added a short FAQ entry about it: https://tttapa.github.io/Control-Surface-doc/new-input/Doxygen/df/df5/md_pages_FAQ.html#faq-save-memory
While it's possible to optimize the memory usage even further, the best solution is usually to upgrade to an Arduino board with more memory. The Arduino Uno is simply not a good choice to build MIDI controllers, it lacks things like USB MIDI support and its 2KiB of RAM is simply not enough for many bigger projects.
Arduino has modern ARM-based boards that are both cheaper than the Uno and have much better features (plenty of RAM, a 32-bit CPU, USB support, faster IO, etc.).
Control Surface will continue to support the Arduino Uno for the foreseeable future (simply because of its popularity), but optimizing the memory usage to be able to add multiple multiplexers and many inputs on an Uno is not a priority, it's much easier to just get a more suitable board, such as an ARM-based Arduino or a Teensy.
Pieter