Control Surface master
MIDI Control Surface library for Arduino


This example demonstrates the use of push buttons and LEDs and how to use shift registers and analog multiplexers to save pins.

AVR, AVR USB, Nano Every, Nano 33 IoT, Nano 33 BLE, Due, Teensy 3.x, ESP8266, ESP32


Connect 16 momentary push buttons between the input pins of the multiplexer and ground.
The internal pull-up resistor for the buttons will be enabled automatically, so no external resistors are necessary.

Connect 16 LEDs (and series resistors) between the eight outputs of the two shift registers and ground.

Remember to connect the enable pins of both the multiplexer and the shift registers to ground in order to enable them. Also connect the master reset pin of the shift registers to Vcc.
Connect the serial data output of the first shift register (QH' or Q7S) to the serial input of the second shift register.


Pressing the first button will turn on the first LED. Pressing it again will turn it off again. Pressing the second button will turn on the second LED. Pressing it again will turn it off again, and so on.

Written by PieterP, 2018-08-28

#include <Arduino_Helpers.h> // Include the Arduino Helpers library.
// Instantiate a multiplexer
2, // input pin
{3, 4, 5, 6}, // Address pins S0, S1, S2, S3
// 7, // Optionally, specify the enable pin
// Alternatively, if you have a 3-bit mux:
// CD74HC4051 mux {
// 2,
// {3, 4, 5},
// // 7, // Optional
// };
// Instantiate a shift register with the SPI slave select pin as latch pin, most
// significant bit first, and a total of 16 outputs.
SPIShiftRegisterOut<mux.length()> sreg {SPI, SS, MSBFIRST};
// Instantiate an array of momentary push buttons.
// It generates an array of Buttons on pins:
// {, ... }
// For each button it creates, it increments the pin number by 1,
// and it starts counting from
auto buttons = generateIncrementalArray<Button, mux.length()>(;
void setup() { // Initialize everything
for (Button &button : buttons)
void loop() { // Check if a button is pressed, if so toggle the LED
for (uint8_t i = 0; i < mux.length(); ++i)
if (buttons[i].update() == Button::Falling)
sreg.digitalWrite(i, sreg.digitalRead(i) ? LOW : HIGH);
constexpr PinStatus_t LOW
constexpr PinStatus_t HIGH
Dummy header file for Arduino builder.
Array< T, N > generateIncrementalArray(U start=0, V increment=V(1))
Generate an array where the first value is given, and the subsequent values are calculated as the pre...
AnalogMultiplex< 4 > CD74HC4067
An alias for AnalogMultiplex<4> to use with CD74HC4067 analog multiplexers.