Leonardo - one button responds slowly in my code

Using an Arduino Leonardo:

I don't believe this is a coding issue which is why I'm posting here. I have 4 buttons on INPUT_PULLUP pinmode. When a button is pressed my code sends a signal ON, when it is released it sends a signal OFF.

The first three buttons respond instantly ON and OFF, the fourth button responds ON instantly, but there is a significant delay in the OFF. It happens consistently, and it appears to specifically be on Pin 5 (I am using 2-5). I have tried swapping buttons/inputs around, but it still repeats on Pin 5 only.

Is there any reasonable explanation for this?

No idea.

How does it send ON or OFF? Over serial or as a keyboard? Or maybe to a LED (HIGH/LOW)? Please provide your code.

The code is currently designed for more than 4 buttons, but I only have 4 connected.

Basically whats happening here is when a button is pressed it sends a few MIDI Note On signals, when it's released, it sends corresponding Midi Note Off signals.

I can't see any reason why Pin 5 specifically would be erratic.

#include "MIDIUSB.h"

//Major Chords
int allChords[18][4] = {    {51, 55, 58, 62}, //Majors/7ths Eb
                            {58, 62, 65, 69}, //Bb
                            {53, 57, 61, 65}, //F
                            {60, 64, 67, 71}, //C
                            {55, 59, 62, 66}, //G
                            {50, 54, 57, 61}, //D
                            {57, 61, 64, 68}, //A
                            {52, 56, 59, 63}, //E
                            {59, 63, 66, 70}, //B
                            {51, 54, 58, 51}, //Minors Eb
                            {58, 61, 65, 58}, //Bb
                            {53, 56, 60, 53}, //F
                            {60, 63, 67, 60}, //C
                            {55, 58, 62, 55}, //G
                            {50, 53, 57, 50}, //D
                            {57, 60, 64, 57}, //A
                            {52, 55, 59, 52}, //E
                            {59, 62, 66, 59}  //B
};

                      
//Eb Bb F C G D A E B
//Major, Minor, 7th

const int buttonPin[] = {2,3,4,5};
const int ledPin = 13;
int chanVel = 100;
int buttonState[27] = {};

void setup() {
  pinMode(ledPin,OUTPUT); //set LED Pin to output

  for (int i=0; i<27; i++){ 
  pinMode(buttonPin[i], INPUT_PULLUP); //set all pins as input pullups
  buttonState[i] = 0; //set all button states to off
  }
}

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

void loop() {
  for (int i=0; i<4; i++){ // read every pin and check if its H/L
    if(digitalRead(buttonPin[i]) == LOW && buttonState[i] == 0){
      if (i < 18){
        noteOn(0,allChords[i][0],chanVel);
        noteOn(0,allChords[i][1],chanVel);
        noteOn(0,allChords[i][2],chanVel);
        MidiUSB.flush(); 
      }
      else {
        noteOn(0,allChords[i-18][0],chanVel);
        noteOn(0,allChords[i-18][1],chanVel);
        noteOn(0,allChords[i-18][2],chanVel);
        noteOn(0,allChords[i-18][3],chanVel);
        MidiUSB.flush();
      }
      buttonState[i] = 1;
    }
    else if (digitalRead(buttonPin[i]) == HIGH && buttonState[i] == 1) {
      if(i < 18) {
        noteOff(0,allChords[i][0],chanVel);
        noteOff(0,allChords[i][1],chanVel);
        noteOff(0,allChords[i][2],chanVel);
        MidiUSB.flush();
      }
      else {
        noteOff(0,allChords[i-18][0],chanVel);
        noteOff(0,allChords[i-18][1],chanVel);
        noteOff(0,allChords[i-18][2],chanVel);
        noteOff(0,allChords[i-18][3],chanVel);
        MidiUSB.flush();
      }
    buttonState[i] = 0;
    }
  }
}

I suspect the main problem is

if (digitalRead(buttonPin[i]) == LOW & buttonState[i] == 0)

A single & is a bit-wise AND, not a logical AND; corrected version

if (digitalRead(buttonPin[i]) == LOW && buttonState[i] == 0)

Same for comparing to HIGH

Not sure how something like this will work out

      noteOff(0, allChords[i - 18][0], chanVel);

If i is less than 18, you have a negative index into your allChords array.

====
A Leonardo with 27 pins :wink: I'm not sure what the result of the for-loop in setup is; it might affect pins in a way that you don't expect.

Below a better (my opinion) version which will automatically pick the correct number of buttons at compile time :wink: You can use the same approach in the for-loop in loop() as well

  for (int i = 0; i < sizeof(buttonPin) / sizeof(buttonPin[0]); i++) {
    pinMode(buttonPin[i], INPUT_PULLUP); //set all pins as input pullups
    buttonState[i] = 0; //set all button states to off
  }

sterretje:
I suspect the main problem is

if (digitalRead(buttonPin[i]) == LOW & buttonState[i] == 0)

A single & is a bit-wise AND, not a logical AND; corrected version

if (digitalRead(buttonPin[i]) == LOW && buttonState[i] == 0)

Same for comparing to HIGH

Not sure how something like this will work out

      noteOff(0, allChords[i - 18][0], chanVel);

If i is less than 18, you have a negative index into your allChords array.

====
A Leonardo with 27 pins :wink: I'm not sure what the result of the for-loop in setup is; it might affect pins in a way that you don't expect.

Below a better (my opinion) version which will automatically pick the correct number of buttons at compile time :wink: You can use the same approach in the for-loop in loop() as well

  for (int i = 0; i < sizeof(buttonPin) / sizeof(buttonPin[0]); i++) {

pinMode(buttonPin[i], INPUT_PULLUP); //set all pins as input pullups
    buttonState[i] = 0; //set all button states to off
  }

Thanks. The plan actually was for using a multiplexer. In the loop function I didn't actually iterate through all 27 buttons, just 4.

Good call on the &.. I had a feeling it was wrong when I was writing it lol

The i-18 code is only active if i is 18 or greater (thus only really calling allChords[0]). The reason for this was because buttons 18-27 share most of the same data with 1-9, so I combined their data in the array and called allChords 0-3 instead of 0-2.

I will update the code and see if it works, thanks!

Aimbit:
The i-18 code is only active if i is 18 or greater (thus only really calling allChords[0]).

Not as i read it :wink:

for (int i = 0; i < 4; i++) { // read every pin and check if its H/L
  if (digitalRead(buttonPin[i]) == LOW & buttonState[i] == 0) {
    ...
    ...
  }
  else if (digitalRead(buttonPin[i]) == HIGH & buttonState[i] == 1) {
    noteOff(0, allChords[i - 18][0], chanVel);
    noteOff(0, allChords[i - 18][1], chanVel);
    noteOff(0, allChords[i - 18][2], chanVel);
    noteOff(0, allChords[i - 18][3], chanVel);
    MidiUSB.flush();
    buttonState[i] = 0;
  }
}

i ranges from 0..3; fill in the numbers :wink:

i ranges from 0..3; fill in the numbers :wink:

Oooof.. Yes I messed up the else if part. I just updated my code up top to add another 'if else' for the noteOff section to mimic the noteOn. That should clear up the negative issue.

I guess it was my code afterall... The button on pin 5 works as expected now! Must have been the bitwise AND.
thanks!

Sidenote: What would my bitwise & statement have been trying to evaluate for pin 5? Comparing a digital read LOW (0000?) and a 5? (0101?) which I think would result in just 0000

@Aimbit

Your topic was Moved to it's current location / section as it is more suitable.

Could you also take a few moments to Learn How To Use The Forum.
Other general help and troubleshooting advice can be found here.
It will help you get the best out of the forum in the future.

ballscrewbob:
@Aimbit

Your topic was Moved to it's current location / section as it is more suitable.

Could you also take a few moments to Learn How To Use The Forum.
Other general help and troubleshooting advice can be found here.
It will help you get the best out of the forum in the future.

thanks, Wasn't planning for this to be a coding question. :slight_smile:

Aimbit:
thanks, Wasn't planning for this to be a coding question. :slight_smile:

I know. I initially gave you the benefit of the doubt about Installation and Troubleshooting. After you admitted the coding issue ( :wink: ), I reported it for the move.

Whilst mods rely on other users to spot things we do try to see where things really should go its not just a report and do what the reporter says. Anyways moving right along.