Simple 16 push buttons MIDI issue with button/pull up resistors

Building a simple MIDI controller with 16 buttons and 4 potentiometers. The potentiometers work fine but I’m having issues with the buttons. Each button seems to be triggering a midi note even when they are not initialized in my code. When I initialize the code for each button, with each button meant to play different notes, each button ends up playing all 16 notes at the same time. I currently have wired one leg of each button together, to GND, with the other legs going to separate digital inputs. I have initialized the pull up resistors for each of the digital pins. While troubleshooting, I even disconnected all the buttons from their respective inputs, except for one and the same issue (every button registering a LOW when pressed, and playing the specified midi note) occurred. I’m not sure if the issue lies in my code or the wiring, but I am attaching the code I have so far. Any help would be appreciated, as I have searched through the forums and could not find any help within the similar issues being discussed. Thanks a lot in advance :slight_smile: .

#include <NESpad.h>

int ndelay = 200;

byte state = 0;

int p1 = 0;
int Lp1 = 0;
int s1 = 0;
int Sp1 = 0;

int pS1 = 0;
int pS2 = 0;
int sS1 = 0;
int sS2 = 0;

int pp1 = A13;
int ss1 = A15;

const int b1 = 22;
const int b2 = 24;
const int b3 = 26;
const int b4 = 28;
const int b5 = 30;
const int b6 = 32;
const int b7 = 34;
const int b8 = 36;
const int b9 = 31;
const int b10 = 33;
const int b11 = 35;
const int b12 = 37;
const int b13 = 42;
const int b14 = 46;
const int b15 = 52;
const int b16 = 17;

boolean lastState = HIGH;
boolean lastState2 = HIGH;
boolean lastState3 = HIGH;
boolean lastState4 = HIGH;
boolean lastState5 = HIGH;
boolean lastState6 = HIGH;
boolean lastState7 = HIGH;
boolean lastState8 = HIGH;
boolean lastState9 = HIGH;
boolean lastState10 = HIGH;
boolean lastState11 = HIGH;
boolean lastState12 = HIGH;
boolean lastState13 = HIGH;
boolean lastState14 = HIGH;
boolean lastState15 = HIGH;
boolean lastState16 = HIGH;

NESpad port1 = NESpad(4,2,7); //strobe, clock, data

void setup() {
Serial.begin(57600);
pinMode(b1, INPUT_PULLUP);
pinMode(b2, INPUT_PULLUP);
pinMode(b3, INPUT_PULLUP);
pinMode(b4, INPUT_PULLUP);
pinMode(b5, INPUT_PULLUP);
pinMode(b6, INPUT_PULLUP);
pinMode(b7, INPUT_PULLUP);
pinMode(b8, INPUT_PULLUP);
pinMode(b9, INPUT_PULLUP);
pinMode(b10, INPUT_PULLUP);
pinMode(b11, INPUT_PULLUP);
pinMode(b12, INPUT_PULLUP);
pinMode(b13, INPUT_PULLUP);
pinMode(b14, INPUT_PULLUP);
pinMode(b15, INPUT_PULLUP);
pinMode(b16, INPUT_PULLUP);
}

void loop() {

//READ STATES-----------------------------------------------

int bS1 = digitalRead(b1);
int bS2 = digitalRead(b2);
int bS3 = digitalRead(b3);
int bS4 = digitalRead(b4);
int bS5 = digitalRead(b5);
int bS6 = digitalRead(b6);
int bS7 = digitalRead(b7);
int bS8 = digitalRead(b8);
int bS9 = digitalRead(b9);
int bS10 = digitalRead(b10);
int bS11 = digitalRead(b11);
int bS12 = digitalRead(b12);
int bS13 = digitalRead(b13);
int bS14 = digitalRead(b14);
int bS15 = digitalRead(b15);
int bS16 = digitalRead(b16);
pS1 = analogRead(pp1);
sS1 = analogRead(ss1);

//BUTTONS--------------------------------------------------

if (bS1 == LOW && lastState == HIGH) {
noteOn(144, 60 ,100);
delay(2);
} else if(bS1 == HIGH && lastState == LOW) {
noteOn(128, 60 ,0);
delay(2);
}
lastState = bS1;

if (bS2 == LOW && lastState2 == HIGH) {
noteOn(144, 61 ,100);
delay(2);
} else if(bS2 == HIGH && lastState2 == LOW) {
noteOn(128, 61 ,0);
delay(2);
}
lastState2 = bS2;

if (bS3 == LOW && lastState3 == HIGH) {
noteOn(144, 62 ,100);
delay(2);
} else if(bS3 == HIGH && lastState3 == LOW) {
noteOn(128, 62 ,0);
delay(2);
}
lastState3 = bS3;

if (bS4 == LOW && lastState4 == HIGH) {
noteOn(144, 63 ,100);
delay(2);
} else if(bS4 == HIGH && lastState4 == LOW) {
noteOn(128, 63 ,0);
delay(2);
}
lastState4 = bS4;

if (bS5 == LOW && lastState5 == HIGH) {
noteOn(144, 64 ,100);
delay(2);
} else if(bS5 == HIGH && lastState5 == LOW) {
noteOn(128, 64 ,0);
delay(2);
}
lastState5 = bS5;

if (bS6 == LOW && lastState6 == HIGH) {
noteOn(144, 65 ,100);
delay(2);
} else if(bS6 == HIGH && lastState6 == LOW) {
noteOn(128, 65 ,0);
delay(2);
}
lastState6 = bS6;

if (bS7 == LOW && lastState7 == HIGH) {
noteOn(144, 66 ,127);
delay(2);
} else if(bS7 == HIGH && lastState7 == LOW) {
noteOn(128, 66 ,0);
delay(2);
}
lastState7 = bS7;

if (bS8 == LOW && lastState8 == HIGH) {
noteOn(144, 67 ,127);
delay(2);
} else if(bS8 == HIGH && lastState8 == LOW) {
noteOn(128, 67 ,0);
delay(2);
}
lastState8 = bS8;

if (bS9 == LOW && lastState9 == HIGH) {
noteOn(144, 68 ,100);
delay(2);
} else if(bS9 == HIGH && lastState9 == LOW) {
noteOn(128, 60 ,0);
delay(2);
}
lastState9 = bS9;

if (bS10 == LOW && lastState10 == HIGH) {
noteOn(144, 69 ,100);
delay(2);
} else if(bS10 == HIGH && lastState10 == LOW) {
noteOn(128, 69 ,0);
delay(2);
}
lastState10 = bS10;

if (bS11 == LOW && lastState11 == HIGH) {
noteOn(144, 70 ,100);
delay(2);
} else if(bS11 == HIGH && lastState11 == LOW) {
noteOn(128, 70 ,0);
delay(2);
}
lastState11 = bS11;

if (bS12 == LOW && lastState12 == HIGH) {
noteOn(144, 71 ,100);
delay(2);
} else if(bS12 == HIGH && lastState12 == LOW) {
noteOn(128, 71 ,0);
delay(2);
}
lastState12 = bS12;

if (bS13 == LOW && lastState13 == HIGH) {
noteOn(144, 72 ,100);
delay(2);
} else if(bS13 == HIGH && lastState13 == LOW) {
noteOn(128, 72 ,0);
delay(2);
}
lastState13 = bS13;

if (bS14 == LOW && lastState14 == HIGH) {
noteOn(144, 73 ,100);
delay(2);
} else if(bS14 == HIGH && lastState14 == LOW) {
noteOn(128, 73 ,0);
delay(2);
}
lastState14 = bS14;

if (bS15 == LOW && lastState15 == HIGH) {
noteOn(144, 74 ,100);
delay(2);
} else if(bS15 == HIGH && lastState15 == LOW) {
noteOn(128, 74 ,0);
delay(2);
}
lastState15 = bS15;

if (bS16 == LOW && lastState16 == HIGH) {
noteOn(144, 75 ,100);
delay(2);
} else if(bS16 == HIGH && lastState16 == LOW) {
noteOn(128, 75 ,0);
delay(2);
}
lastState16 = bS16;

//POTENTIOMETERS---------------------------------------------

p1 = pS1/8;
if (p1 != Lp1) {
noteOn(176,1,p1);
delay(10);
Lp1 = p1;
}

s1 = sS1/8;
if (s1 != Sp1) {
noteOn(177,1,s1);
delay(10);
Sp1 = s1;
}

//CONTROLLER PORTS--------------------------------------------

byte state = port1.buttons();

if (state & NES_A) {
noteOn(144, 60, 100);
delay(ndelay);
noteOn(128, 60, 100);
}

if (state & NES_B) {
noteOn(144, 61, 100);
delay(ndelay);
noteOn(128, 61, 100);
}

if (state & NES_START) {
noteOn(144, 62, 100);
delay(ndelay);
noteOn(128, 62, 100);
}

if (state & NES_SELECT) {
noteOn(144, 63, 100);
delay(ndelay);
noteOn(128, 63, 100);
}

if (state & NES_UP) {
noteOn(144, 64, 100);
delay(ndelay);
noteOn(128, 64, 100);
}

if (state & NES_DOWN) {
noteOn(144, 65, 100);
delay(ndelay);
noteOn(128, 65, 100);
}

if (state & NES_LEFT) {
noteOn(144, 66, 100);
delay(ndelay);
noteOn(128, 66, 100);
}

if (state & NES_RIGHT) {
noteOn(144, 67, 100);
delay(ndelay);
noteOn(128, 67, 100);
}
}

//--------------------------------------------------------------

void noteOn(int cmd, int pitch, int velocity) {
Serial.write(cmd);
Serial.write(pitch);
Serial.write(velocity);
}

Hi,

Unless there's something in your circuit to debounce these switches using hardware, it appears that's going to be a concern for this code.

If you've not encountered debouncing before as a concept, check out this tutorial by Jeremy Blum that guides you though what causes it, and a simple way of fixing it.

I think you'll find a lot of your issues stem from that.

Cheers !
Geoff

The whole of that code could be written in less than 20 lines if you learn how to use arrays and for loops.

Please read the forum rules and post your code with the </> icon.

Grumpy_Mike:
The whole of that code could be written in less than 20 lines if you learn how to use arrays and for loops.

I took that challenge this afternoon when I first saw this...didn't get it quite down to 20, but it reduced to 120 lines with just the switch logic changed.

Thank you Geoff and Mike for your replies. I am going to take your advice and reduce the code for the switches using an array and for loop as soon as I get the switch logic correct.

Unless there's something in your circuit to debounce these switches using hardware, it appears that's going to be a concern for this code.

Geoff, are you saying that these switches can only be debounced through rewiring my circuit? Or can this be achieved through altering the switch logic as well? When I first tested this code with one button, with none of the other buttons connected to GND or a digital input, the current code I had worked fine. A MIDI note was triggered on and then off by only one button, with none of the others triggering any notes. The problem seems to have arisen when all the other switches were connected to GND and their respective digital pins. If my understanding of debouncing is correct, I would just need to add a portion to my switch code that allows some time for the switch to bounce and rereads the state again after that time? If so, how do you think the lack of debouncing is leading to the problem I described above?

Sorry for all the questions, I'm just really curious and anxious to understand the issue and make this device work! Thanks again so much for your time :slight_smile:

are you saying that these switches can only be debounced through rewiring my circuit?

No.

Or can this be achieved through altering the switch logic as well?

Not the logic but the software.

If my understanding of debouncing is correct, I would just need to add a portion to my switch code that allows some time for the switch to bounce and rereads the state again after that time?

A simple delay of 20mS after a contact has been detected is usually enough.

, how do you think the lack of debouncing is leading to the problem I described above?

Comtact bouncing would manifest itself in multiple rapid key detection.

When I first tested this code with one button, with none of the other buttons connected to GND or a digital input, the current code I had worked fine. A MIDI note was triggered on and then off by only one button, with none of the others triggering any notes. The problem seems to have arisen when all the other switches were connected to GND and their respective digital pins.

That seems to point to some sort of hardware wiring problem such that your circuit is not what you think it is.

heeldrag:
Geoff, are you saying that these switches can only be debounced through rewiring my circuit? Or can this be achieved through altering the switch logic as well?

Did you watch the video in the link I had in my first post? That tutorial is just simple debouncing in software and you could use that here.

And I agree, tackle the switches first then move to making the code more compact later. There's nothing wrong with what you've done here dealing with each switch test by creating an individual block in the code, it's just with more experience you'll see patterns in your problems that can save you lots of time, keystrokes and ultimately make it far simpler to create and debug more complex tasks. And doing it with an array will scale easier if you want to spin it up to 32 switches for version 2.0

All the best with this, Geoff

After further inspection, Mike was right, my wiring was not as I thought it was. After fixing it, everything is working fine!! Time to look into reducing the code.

Geoff, thank you for showing me that video, I am now going to debounce the switches and make four of them toggle on and off.

You guys are awesome. Thanks again :slight_smile: