Arduino Pro Micro MIDI messages with push buttons and Shift Registers

I am trying to build a 4x4 launch pad(multiple buttons will be pressed at the same time) as part of a MIDI controller with Arduino Pro Micro and Control Surface library (https://tttapa.github.io/Control-Surface/Doc/Doxygen/index.html)
The problem is that I cannot get MIDI messages to be send through the push buttons.....
I know I am missing something here for sure..

I want to save arduino pins, that is why I chose to use the shift register 74HC165 in order to connect the 16 push buttons to arduino by using only 3 of the arduino pins. The problem is that although the Control Surface library ROCKS! it is still not finished and it is not compatible with shift registers like 74hc165 but only with those that you can use to increase the outputs(74hc595).

So...I had to figure sth out.

I figured a way to take the incoming 8-bit data from the shift register,representing the state of the push buttons and store each of the push button states separately inside the "buttons[8]" array through the bitRead() function so I can access every button state independently.

I faced a problem when trying to declare the buttons with the Control Surface library with each button declared as an element of the buttons[8] array instead of declaring the ard. pin the button is supposed to be hooked.

the following is supposed to convert the byte type variable that stores the state of the buttons in the buttons array, into an integer. Maybe this is completely wrong...I am not entirely sure..

for(int i = 0; i < 8; i++){
    if(buttons[i] == 0){
      buttons[i] = 0;
    }
    else if(buttons[i] == 1){
      buttons[i] = 1;
    }
  }

In the code there are 8 push buttons as a proof of concept.

#include <Control_Surface.h>

USBMIDI_Interface midi;


//pl pin num.1 in the shift reg.
int load = 7;

//CE pin 15
int clockEnablePin = 8;

//Q7 pin7 inverted data
int dataIn = 5;

//CP pin 2
int clockIn = 6;

byte incoming = 0;
int buttons[8]; 

/*declare the buttons somehow

*/
 NoteButton btn[8] {
  {buttons[0], MIDI_Notes::C(4)},
  {buttons[1], MIDI_Notes::C(3)},
  {buttons[2], MIDI_Notes::C(5)},
  {buttons[3], MIDI_Notes::C(6)},
  {buttons[4], MIDI_Notes::C(7)},
  {buttons[5], MIDI_Notes::C(8)},
  {buttons[6], MIDI_Notes::E(4)},
  {buttons[7], MIDI_Notes::E(3)},
};


void shiftRegister(){
  //write the pulse to load pin
  digitalWrite(load, LOW);
  delayMicroseconds(5);
  digitalWrite(load, HIGH);
  delayMicroseconds(5);

  //Get data from the shift register
  digitalWrite(clockIn, HIGH);
  digitalWrite(clockEnablePin, LOW);

  incoming = shiftIn(dataIn, clockIn, MSBFIRST);

  digitalWrite(clockEnablePin, HIGH);

  for (int bits = 0; bits < 8; bits++) {
    buttons[bits] = bitRead(incoming, bits);
  }
 
  for(int i = 0; i < 8; i++){
    if(buttons[i] == 0){
      buttons[i] = 0;
    }
    else if(buttons[i] == 1){
      buttons[i] = 1;
    }
  }
 
  delay(700);



}



void setup() {
  Control_Surface.begin();
  //Serial.begin(115200);
  

  //setup shift regs connections
  pinMode(load, OUTPUT);
  pinMode(clockEnablePin, OUTPUT);
  pinMode(clockIn, OUTPUT);
  pinMode(dataIn, INPUT);
}

void loop() {
  shiftRegister();
  Control_Surface.loop();
  
  
}

I have managed to send MIDI messages and use knobs,faders and LEDs so that is not the problem here, but the code.....

Any help is highly appreciated!!!! Bare in mind that I am still new to this so brutal code mistakes may exist^^

The first argument of the NoteButton constructor is the pin number. The library will internally perform a digitalRead(pin_number).
In the code you posted, all NoteButton objects are initialized with pin number 0. After the initialization, changing the values in the buttons array cannot possibly affect the state of the NoteButton objects, you're only using the values of the buttons array to initialize the NoteButtons, it does not cause any automatic link between the two variables. Consider:

int a = 42;
int b = a + 1; // b == 43
a = 5;
// b == 43, it doesn't automagically become 6

// similarly:
int buttonpin = 2;
NoteButton btn {buttonpin, MIDI_Notes::C(4)};
// btn.pin == 2;
buttonpin = 3;
// btn.pin == 2, not 3

You basically have two options, implement a ShiftRegisterIn class so that Control Surface knows how to perform a digitalRead for the 74HC165, or handle the button state change detection and MIDI sending logic manually in your sketch.

For the former, have a look at the following files for inspiration:

Instead of using updateBufferedOutputs(), override updateBufferedInputs() and use shiftIn() there, writing the result to the bit buffer using buffer.setByte(index, shiftInValue).
Since you're only concerned about inputs, you can leave the digitalWrite() and pinMode() functions and their buffered versions empty.

To learn how to send MIDI messages yourself, see:

This has no effect whatsoever. What was the intention here? Data types are determined at compile time, assignment at run time has no effect on the type of a variable. buttons[i] will always be of type int.

Why?


Do you have pull-up/down resistors on the shift register inputs? This requirement is why I often prefer a port expander with built-in pull-ups like the MCP23017 rather than a shift register, and this is also the reason why Control Surface supports the 74HC595 and MCP23017 out of the box, but not the 74HC165.

Thank you so much both for the marvelous Library and for suck a quick reply!!!!This is a side project so I am not spending much time on it, that is why the delayed answer.

It seems that MCP23017 are a bit hard to find them right now or find them ridiculously expensive,sth like 11.20€ (low production they told me due to covid and environmental hour-restrictions...).
Could I instead of using the MPC23017, to use the I/O MCP23008? This one has 8-bit remote bidirectional I/O port instead of 16-bit that the MCP23017 has. I am not entirely sure how is that differentiating it from 23017 besides providing you with 8 pins I/O instead of 16.

Thank you so much:)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.