4x4 button pad and shift registers

This may be basic, but I don’t really care. Please help if you can.

I am building a Monome style MIDI controller with Arduino and the 4x4 button pad and pcb. I plan to decode the switches using the Keyboard library from Arduino and two shift in and shift out registers to run all LEDs and buttons through my Arduino Uno. What I want to happen is that when I press a button the LED for that button will turn on and a MIDI “notein” message is sent to the computer. I want the LED to remain on until I press the button again (which will send a MIDI “noteoff” message). I have an idea about how to program the MIDI and decode the buttons, some idea of how to program the shift registers, I know how to turn on the LED run a counter then turn it off again after a second press, but I have no idea how to put all of these together. Can anyone help me work this out?

The best peace of information that anyone can give you is to get ONE item on your list to work first. Once you have a button to work like you want, then add more. Once you get a shift register to work, then add more if needed. The main advice here is to get each individual piece of your project working FIRST. Then start adding another piece. Once you have 2 parts working, add a third and so on…

But if you are asking for code, you will be waiting a long time. We are not here to hand things to you. Once you have a piece of code for a certain piece and you are having problems, then you can ask and we will help. Or maybe you have got 2 things to work but having trouble adding a third, then ask here with too much info in your post. The more info we have the better we can help.

I would advise you now to start searching Google. There are literally millions of code examples for all aspects of the project you described.

Good luck!

At this point I could use some advice on wiring the device into my arduino even one button at a time then getting readings.

Never mind the last post I got that

You might start here …

http://oneelectricsheep.tumblr.com/post … utton-pads

https://learn.sparkfun.com/tutorials/shift-registers

http://arduino.cc/en/Reference/ShiftIn

http://arduino.cc/en/Tutorial/RowColumnScanning

Bear in mind that there’s often many ways to accomplish the same end goal.

Ok:

I am sending midi data and reading it in Logic Pro. Yay! I think I need an LED matrix chip to run the lights when buttons are pushed (though a suggestion to make this work in both wiring and coding would be awesome, I’m not using RGB LEDs since I wanted specific colors) and I have researched and think I understand the shift register. What I could use some help with now is making the keypad interact with the shift in register. Below is my code (I am experimenting a little with the MIDI data to have the note hold as long as the key is depressed):

#include <Keypad.h>

byte noteON = 144;

const byte ROWS = 4;

const byte COLS = 4;

char keys [ROWS][COLS] = {

{‘1’,‘2’,‘3’,‘A’},

{‘4’,‘5’,‘6’,‘B’},

{‘7’,‘8’,‘9’,‘C’},

{‘#’,‘0’,‘*’,‘D’}

};

byte rowPins [ROWS] = {11,10,9,8};

byte colPins [COLS] = {5,4,3,2};

Keypad kpd = Keypad(makeKeymap(keys),rowPins,colPins,ROWS,COLS);

#define ledpin 13

void setup()

{

pinMode(ledpin, OUTPUT);

digitalWrite(ledpin, HIGH);

Serial.begin(115200); //higher number for integration with hairless midi

}

void loop()

{

char key = kpd.getKey();

if(key)

{

switch (key)

{

case ‘1’:

while(kpd.getState()==HOLD){

MIDImessage(noteON, 60, 127);

}

delay(2);

break;

case ‘2’:

MIDImessage(noteON, 61, 127);

delay(2);

MIDImessage(noteON, 61, 0);

break;

case ‘3’:

MIDImessage(noteON, 62, 127);

delay(2);

MIDImessage(noteON, 62, 0);

break;

case ‘A’:

MIDImessage(noteON, 63, 127);

delay(2);

MIDImessage(noteON, 63, 0);

break;

case ‘4’:

MIDImessage(noteON, 64, 127);

delay(2);

MIDImessage(noteON, 64, 0);

break;

case ‘5’:

MIDImessage(noteON, 65, 127);

delay(2);

MIDImessage(noteON, 65, 0);

break;

case ‘6’:

MIDImessage(noteON, 66, 127);

delay(2);

MIDImessage(noteON, 66, 0);

break;

case ‘B’:

MIDImessage(noteON, 67, 127);

delay(2);

MIDImessage(noteON, 67, 0);

break;

case ‘7’:

MIDImessage(noteON, 68, 127);

delay(2);

MIDImessage(noteON, 68, 0);

break;

case ‘8’:

MIDImessage(noteON, 69, 127);

delay(2);

MIDImessage(noteON, 69, 0);

break;

case ‘9’:

MIDImessage(noteON, 70, 127);

delay(2);

MIDImessage(noteON, 70, 0);

break;

case ‘C’:

MIDImessage(noteON, 71, 127);

delay(2);

MIDImessage(noteON, 71, 0);

break;

case ‘#’:

MIDImessage(noteON, 72, 127);

delay(2);

MIDImessage(noteON, 72, 0);

break;

case ‘0’:

MIDImessage(noteON, 73, 127);

delay(2);

MIDImessage(noteON, 73, 0);

break;

case ‘*’:

MIDImessage(noteON, 74, 127);

delay(2);

MIDImessage(noteON, 74, 0);

break;

case ‘D’:

MIDImessage(noteON, 75, 127);

delay(2);

MIDImessage(noteON, 75, 0);

break;

}

}

}

void MIDImessage(byte command, byte data1, byte data2) {

Serial.write(command);

Serial.write(data1);

Serial.write(data2);

}

Ok, I have successfully gotten the buttons to send midi noteon/off messages and have realized that I need an LED matrix to control the lights. My controller has potentiometers on it and I can even successfully read and send midi cc messages, but it creates a constantly running read of the potentiometer state and I can’t use any of the buttons. Any thoughts (see code below),

#include <Keypad.h>

byte val = 0;

int vol = A0;

const byte ROWS = 4;

const byte COLS = 4;

char keys [ROWS][COLS] = {

{‘1’,‘2’,‘3’,‘A’},

{‘4’,‘5’,‘6’,‘B’},

{‘7’,‘8’,‘9’,‘C’},

{‘#’,‘0’,‘*’,‘D’}

};

byte rowPins [ROWS] = {11,10,9,8};

byte colPins [COLS] = {2,3,4,5};

Keypad kpd = Keypad(makeKeymap(keys),rowPins,colPins,ROWS,COLS);

void setup()

{

Serial.begin(115200);

kpd.addEventListener(keypadEvent);

}

void loop(){

char key = kpd.getKey();

if(key) {

}

val = analogRead(vol);

MIDImessage(0xB0, 7, val);

}

void keypadEvent(KeypadEvent key){

switch(kpd.getState()){

case PRESSED:

if (key == ‘1’) {

MIDImessage(0x90, 60, 127);}

break;

case RELEASED:

if (key == ‘1’) {

MIDImessage(0x80, 60, 0);}

break;

}

switch(kpd.getState()){

case PRESSED:

if (key == ‘2’) {

MIDImessage(0x91, 61, 127);}

break;

case RELEASED:

if (key == ‘2’) {

MIDImessage(0x81, 61, 0);}

break;

}

switch(kpd.getState()){

case PRESSED:

if (key == ‘3’) {

MIDImessage(0x92, 62, 127);}

break;

case RELEASED:

if (key == ‘3’) {

MIDImessage(0x82, 62, 0);}

break;

}

switch(kpd.getState()){

case PRESSED:

if (key == ‘A’) {

MIDImessage(0x93, 63, 127);}

break;

case RELEASED:

if (key == ‘A’) {

MIDImessage(0x83, 63, 0);}

break;

}

switch(kpd.getState()){

case PRESSED:

if (key == ‘4’) {

MIDImessage(0x94, 64, 127);}

break;

case RELEASED:

if (key == ‘4’) {

MIDImessage(0x84, 64, 0);}

break;

}

switch(kpd.getState()){

case PRESSED:

if (key == ‘5’) {

MIDImessage(0x95, 65, 127);}

break;

case RELEASED:

if (key == ‘5’) {

MIDImessage(0x85, 65, 0);}

break;

}

switch(kpd.getState()){

case PRESSED:

if (key == ‘6’) {

MIDImessage(0x96, 66, 127);}

break;

case RELEASED:

if (key == ‘6’) {

MIDImessage(0x86, 66, 0);}

break;

}

switch(kpd.getState()){

case PRESSED:

if (key == ‘B’) {

MIDImessage(0x97, 67, 127);}

break;

case RELEASED:

if (key == ‘B’) {

MIDImessage(0x87, 67, 0);}

break;

}

switch(kpd.getState()){

case PRESSED:

if (key == ‘7’) {

MIDImessage(0x98, 68, 127);}

break;

case RELEASED:

if (key == ‘7’) {

MIDImessage(0x88, 68, 0);}

break;

}

switch(kpd.getState()){

case PRESSED:

if (key == ‘8’) {

MIDImessage(0x99, 69, 127);}

break;

case RELEASED:

if (key == ‘8’) {

MIDImessage(0x89, 69, 0);}

break;

}

switch(kpd.getState()){

case PRESSED:

if (key == ‘9’) {

MIDImessage(0x9A, 70, 127);}

break;

case RELEASED:

if (key == ‘9’) {

MIDImessage(0x8A, 70, 0);}

break;

}

switch(kpd.getState()){

case PRESSED:

if (key == ‘C’) {

MIDImessage(0x9B, 71, 127);}

break;

case RELEASED:

if (key == ‘C’) {

MIDImessage(0x8B, 71, 0);}

break;

}

switch(kpd.getState()){

case PRESSED:

if (key == ‘#’) {

MIDImessage(0x9C, 72, 127);}

break;

case RELEASED:

if (key == ‘#’) {

MIDImessage(0x8C, 72, 0);}

break;

}

switch(kpd.getState()){

case PRESSED:

if (key == ‘0’) {

MIDImessage(0x9D, 73, 127);}

break;

case RELEASED:

if (key == ‘0’) {

MIDImessage(0x8D, 73, 0);}

break;

}

switch(kpd.getState()){

case PRESSED:

if (key == ‘*’) {

MIDImessage(0x9E, 74, 127);}

break;

case RELEASED:

if (key == ‘*’) {

MIDImessage(0x8E, 74, 0);}

break;

}

switch(kpd.getState()){

case PRESSED:

if (key == ‘D’) {

MIDImessage(0x9F, 75, 127);}

break;

case RELEASED:

if (key == ‘#’) {

MIDImessage(0x8F, 75, 0);}

break;

}

}

void MIDImessage(byte command, byte data1, byte data2) {

Serial.write(command);

Serial.write(data1);

Serial.write(data2);

}

You’ll get more help if your posted code is more readable, as it is in the code editor window. Use the code tags to preserve the indentation.

(click on to enlarge)

Well let’s try this code setup and let me update what I can do and what I still want to do. With the code as is I am able to read multiple button presses from the keypad as midi note on messages, sustain those notes until I release, and then send a midi note off messages. I can run four traditional potentiometers as volume cc messages mapped as values 0 - 127. I also have two maxbotix ultrasonic range finders plugged into A5 and A6 that I want to be able to read and send messages within a range. I have tried using basic code, but the sensors constantly read and I cannot use any other buttons or pots while it is reading the input from the maxbotix. Any suggestions on that code would be great. I also want to run the lights so that they turn on when the key is pressed and off when it is pressed again. I think I need a display driver for this, but I did not buy one when I started this project (I wasn’t sure I needed one). Is it possible to run the matrix with a shift register? Currently when I ground the entire matrix and run power through a 220 ohm I loose half my LEDs instead of all of them just turning on. The lights that come on are red and yellow and the ones that don’t are blue and green (single color lights not rgb). If I unplug two grounds then the blues and greens in the grounded columns light up, but the same won’t happen if I unplug two rows. Any thoughts? Also, I have been looking at the shift in register coding and I think I get it, but I’m not sure how to integrate it with the keypad code.

#include <Keypad.h>

byte val = 0;
int old_vol; //stored voltage data from pots
const byte ROWS = 4;
const byte COLS = 4;
char keys [ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'#','0','*','D'}
};

byte rowPins [ROWS] = {8, 9, 10, 11};
byte colPins [COLS] = {5, 4, 3, 2};

Keypad kpd = Keypad(makeKeymap(keys),rowPins,colPins,ROWS,COLS);


void setup()
{
  Serial.begin(115200); //set this high for connection with "Hairless MIDI"
  kpd.addEventListener(keypadEvent); //Event Listener for keypad
  
}

void loop(){ 
  char key = kpd.getKeys();
  
  if(key) {
  }
  for(int i = 0; i < 4; i ++){ //reads analog inputs 0-3
  val = map(analogRead(i), 0, 1023, 0, 127);
  if(val != old_vol) {
    old_vol = val;
  MIDImessage(0xB0 + i, 7, val);} //MIDI command change message
  }
}

void keypadEvent(KeypadEvent key){
  switch(kpd.getState()){
    case PRESSED:
        if (key == '1') {
          MIDImessage(0x90, 60, 127);}
        break;
        
    case RELEASED:
        if (key == '1') {
          MIDImessage(0x80, 60, 0);}
        break;
  }
  switch(kpd.getState()){
    case PRESSED:
        if (key == '2') {
          MIDImessage(0x91, 61, 127);}
        break;
        
    case RELEASED:
        if (key == '2') {
          MIDImessage(0x81, 61, 0);}
        break;
  }
  switch(kpd.getState()){
    case PRESSED:
        if (key == '3') {
          MIDImessage(0x92, 62, 127);}
        break;
        
    case RELEASED:
        if (key == '3') {
          MIDImessage(0x82, 62, 0);}
        break;
  }
  switch(kpd.getState()){
    case PRESSED:
        if (key == 'A') {
          MIDImessage(0x93, 63, 127);}
        break;
        
    case RELEASED:
        if (key == 'A') {
          MIDImessage(0x83, 63, 0);}
        break;
  }
  switch(kpd.getState()){
    case PRESSED:
        if (key == '4') {
          MIDImessage(0x94, 64, 127);}
        break;
        
    case RELEASED:
        if (key == '4') {
          MIDImessage(0x84, 64, 0);}
        break;
  }
  switch(kpd.getState()){
    case PRESSED:
        if (key == '5') {
          MIDImessage(0x95, 65, 127);}
        break;
        
    case RELEASED:
        if (key == '5') {
          MIDImessage(0x85, 65, 0);}
        break;
  }
  switch(kpd.getState()){
    case PRESSED:
        if (key == '6') {
          MIDImessage(0x96, 66, 127);}
        break;
        
    case RELEASED:
        if (key == '6') {
          MIDImessage(0x86, 66, 0);}
        break;
  }
  switch(kpd.getState()){
    case PRESSED:
        if (key == 'B') {
          MIDImessage(0x97, 67, 127);}
        break;
        
    case RELEASED:
        if (key == 'B') {
          MIDImessage(0x87, 67, 0);}
        break;
  }
  switch(kpd.getState()){
    case PRESSED:
        if (key == '7') {
          MIDImessage(0x98, 68, 127);}
        break;
        
    case RELEASED:
        if (key == '7') {
          MIDImessage(0x88, 68, 0);}
        break;
  }
  switch(kpd.getState()){
    case PRESSED:
        if (key == '8') {
          MIDImessage(0x99, 69, 127);}
        break;
        
    case RELEASED:
        if (key == '8') {
          MIDImessage(0x89, 69, 0);}
        break;
  }
  switch(kpd.getState()){
    case PRESSED:
        if (key == '9') {
          MIDImessage(0x9A, 70, 127);}
        break;
        
    case RELEASED:
        if (key == '9') {
          MIDImessage(0x8A, 70, 0);}
        break;
  }
  switch(kpd.getState()){
    case PRESSED:
        if (key == 'C') {
          MIDImessage(0x9B, 71, 127);}
        break;
        
    case RELEASED:
        if (key == 'C') {
          MIDImessage(0x8B, 71, 0);}
        break;
  }
  switch(kpd.getState()){
    case PRESSED:
        if (key == '#') {
          MIDImessage(0x9C, 72, 127);}
        break;
        
    case RELEASED:
        if (key == '#') {
          MIDImessage(0x8C, 72, 0);}
        break;
  }
  switch(kpd.getState()){
    case PRESSED:
        if (key == '0') {
          MIDImessage(0x9D, 73, 127);}
        break;
        
    case RELEASED:
        if (key == '0') {
          MIDImessage(0x8D, 73, 0);}
        break;
  }
  switch(kpd.getState()){
    case PRESSED:
        if (key == '*') {
          MIDImessage(0x9E, 74, 127);}
        break;
        
    case RELEASED:
        if (key == '*') {
          MIDImessage(0x8E, 74, 0);}
        break;
  }
  switch(kpd.getState()){
    case PRESSED:
        if (key == 'D') {
          MIDImessage(0x9F, 75, 127);}
        break;
        
    case RELEASED:
        if (key == 'D') {
          MIDImessage(0x8F, 75, 0);}
        break;
  }
}

  void MIDImessage(byte command, byte data1, byte data2) {
    Serial.write(command);
    Serial.write(data1);
    Serial.write(data2);
  }

Just looking at this snippet …

  for (int i = 0; i < 4; i ++) { //reads analog inputs 0-3
    val = map(analogRead(i), 0, 1023, 0, 127);
    if (val != old_vol) {
      old_vol = val;
      MIDImessage(0xB0 + i, 7, val);
    } //MIDI command change message
  }

Shouldn’t val and old_val be arrays (val, old_val) ? Right now I think you might be comparing a val reading from one analog input to an old_val from another analog input. While it’s unlikely (perhaps not possible in your application) that any two pins will have the same value, it’s takes only a little to preclude the possibility.
I believe the ultrasonic sensors can be set to continuously measure and change their analog output. Once configured that way I don’t see why you couldn’t put two more analog reads after the above snippet. Or is the problem that you want to read them while a key/button is being pushed ?
I can’t help you re: the LED oddness as I haven’t a clue as to how you have them wired or are controlling them.
Lastly I think you’ve got the } in the wrong place below.

*_ <em>* if (key) { }*</em> _*
My guess is that it’s supposed to go after the snippet above. Like …
*_ <em>* if (key) { for (int i = 0; i < 4; i ++) { //reads analog inputs 0-3 val[i] = map(analogRead(i), 0, 1023, 0, 127); if (val[i] != old_vol[i]) { old_vol[i] = val[i]; MIDImessage(0xB0 + i, 7, val[i]); } //MIDI command change message } }*</em> _*