Shift register 4021 debounce or something else?

Hi to all, I have 5 4021 registers daisy chained and everything works pretty much as expected except this issue: Sometimes when I press button Arduino thinks I've pressed it twice and since I'm building MIDI controller I can't allow that. The code is pretty much the same as in tutorial.

If you are connecting to physical buttons you should probably include some debounce logic.

How do I do that for shift registers?

Same way as for any other button. If it has been less than 'n' milliseconds since that button last transitioned from not pressed to pressed, ignore the press.

I’m lost on this. Here is my code, so I’d appreciate some help with this:

//#define DEBUG
#include <ShiftRegisterDataCollect.h>

//number of shift registers
#define NUMBER_OF_SHIFT_REGISTERS 5

//shift register pins
#define CLOCK_PIN 7
#define LATCH_PIN 8
#define DATA_PIN 9

//array of first 8 basic 2^n values
int arrayOfBasicValues[8] = { 128, 64, 32, 16, 8, 4, 2, 1 };

//array of sum of basic values
int arrayOfSum[8*NUMBER_OF_SHIFT_REGISTERS] = { 0 };

//array of previous values
boolean arrayOfButtonChange[8*NUMBER_OF_SHIFT_REGISTERS] = { false };

//array of MIDI note values
int arrayOfMIDInotes[8] = { 30, 31, 32, 33, 34, 35, 36, 37 };

//for loop variable
int i = 0;

//Define variables to hold the data for each shift register.
byte switchVar[NUMBER_OF_SHIFT_REGISTERS] = {0};

ShiftRegisterDataCollect shiftData(LATCH_PIN, CLOCK_PIN, DATA_PIN);


void setup() {
  //start serial
  Serial.begin(9600);

}

void loop() {
  
  
  shiftData.latchPin();

  for (i=0; i<NUMBER_OF_SHIFT_REGISTERS; i++)  {
    
  //get values from shift register 
  switchVar[i] = shiftData.shiftInFunc();
  
  //break result to set of basic values and then generate MIDI notes
  resultBreak(switchVar[i], i);

  }

}


int resultBreak (int readData, int shiftRegisterNumber) {
  
  int j = 0;
  int n = 0;

  for (j=0; j<8; j++) {
    
 //first part of the loop. get basic values    
 
      if (readData >= arrayOfBasicValues[j]) {
            
            arrayOfSum[j+8*shiftRegisterNumber] = arrayOfBasicValues[j];
            
            readData -= arrayOfBasicValues[j];

      }  else arrayOfSum[j+8*shiftRegisterNumber] = 0;
      
      
      //second part of the loop, send midi values
      if (arrayOfSum[j+8*shiftRegisterNumber] != 0 && arrayOfButtonChange[j+8*shiftRegisterNumber] == false) {
      
              sendMIDI(arrayOfSum[j+8*shiftRegisterNumber], shiftRegisterNumber);
              
              //true indicates that the button is pressed so that the code sends only one MIDI note while button is pressed
              arrayOfButtonChange[j+8*shiftRegisterNumber] = true;
          }
          
       //if the button isn't pressed anymore, set value in arrayOfButtonState to false
      if (arrayOfSum[j+8*shiftRegisterNumber] == 0)  arrayOfButtonChange[j+8*shiftRegisterNumber] = false;   
              
  } 
}

void sendMIDI (int value, int shiftRegisterNumber) {
  
   
   int i;
   char note;

   for (i=0; i<8; i++) {
  
    //find the correct value in array of basic values and generate note code 
    if (value == arrayOfBasicValues[i])  { note = arrayOfMIDInotes[i] + (8*shiftRegisterNumber); break; }
    
   }
   
    #ifdef DEBUG
    Serial.print("button: ");
    Serial.print (value);
    Serial.print("\n");
    Serial.print("register number: ");
    Serial.print (shiftRegisterNumber + 1);
    Serial.print("\n");

  #else
    Serial.write(0x90); 
    Serial.write(note); 
    Serial.write(0x45);
    
    #endif
  
}

How do I do that for shift registers?

Make sure you do not read the shift registers any faster than every 20mS. When you get the other stuff in the loop you will find you won't anyway.

I eventually solved it using another array.

//#define DEBUG
#include <ShiftRegisterDataCollect.h>

//number of shift registers
#define NUMBER_OF_SHIFT_REGISTERS 5

//shift register pins
#define CLOCK_PIN 7
#define LATCH_PIN 8
#define DATA_PIN 9

//array of first 8 basic 2^n values
int arrayOfBasicValues[8] = { 128, 64, 32, 16, 8, 4, 2, 1 };

//array of sum of basic values
int arrayOfSum[8*NUMBER_OF_SHIFT_REGISTERS] = { 0 };

//array of previous values
int arrayOfButtonChange[8*NUMBER_OF_SHIFT_REGISTERS] = { 0 };

//array of debouncing time
unsigned long int arrayOfDebounce[8*8*NUMBER_OF_SHIFT_REGISTERS] = { 0 };

//array of MIDI note values
int arrayOfMIDInotes[8] = { 30, 31, 32, 33, 34, 35, 36, 37 };

//for loop variable
int i = 0;

//Define variables to hold the data for each shift register.
byte switchVar[NUMBER_OF_SHIFT_REGISTERS] = {0};

ShiftRegisterDataCollect shiftData(LATCH_PIN, CLOCK_PIN, DATA_PIN);

//minimum time between 2 button presses
unsigned long int debounceDelay = 40; 

void setup() {
  //start serial
  Serial.begin(9600);

}

void loop() {
  
  shiftData.latchPin();

  for (i=0; i<NUMBER_OF_SHIFT_REGISTERS; i++)  {
    
  //get values from shift register 
  switchVar[i] = shiftData.shiftInFunc();
  
  //break result to set of basic values and then generate MIDI notes
  resultBreak(switchVar[i], i);

  }
}


int resultBreak (int readData, int shiftRegisterNumber) {
  
  int j = 0;
  int n = 0;

  for (j=0; j<8; j++) {
    
 //first part of the loop. get basic values    
 
      if (readData >= arrayOfBasicValues[j]) {
            
            arrayOfSum[j+8*shiftRegisterNumber] = arrayOfBasicValues[j];
            
            readData -= arrayOfBasicValues[j];

      }  else arrayOfSum[j+8*shiftRegisterNumber] = 0;
      
      
      //second part of the loop, send midi values and debounce
      if ((arrayOfSum[j+8*shiftRegisterNumber] - arrayOfButtonChange[j+8*shiftRegisterNumber]) == arrayOfSum[j+8*shiftRegisterNumber]) {
          
                      //debounce
                      arrayOfDebounce[j+8*shiftRegisterNumber] = millis();
                      
                      //set arrayOfButtonChange to 1 since the button has changed state
                      arrayOfButtonChange[j+8*shiftRegisterNumber] = 1;
                      
      }
          //if button state has changed in less than 40ms ignore it, else send MIDI code
          if (((millis() - arrayOfDebounce[j+8*shiftRegisterNumber]) > debounceDelay) && (arrayOfButtonChange[j+8*shiftRegisterNumber] == 1)) {
          
            
            //send MIDI code
            sendMIDI(arrayOfSum[j+8*shiftRegisterNumber], shiftRegisterNumber);
            
            //sets arrayOfButtonChange to 2 since MIDI note has been sent nad makes sure that only one note is sent while button is being pressed
            arrayOfButtonChange[j+8*shiftRegisterNumber] = 2;
      }
          
       //if the button isn't pressed anymore, set value in arrayOfButtonState to zero
      if (arrayOfSum[j+8*shiftRegisterNumber] == 0)  arrayOfButtonChange[j+8*shiftRegisterNumber] = 0;   
              
  } 
}

void sendMIDI (int value, int shiftRegisterNumber) {

   int i;
   char note;

   for (i=0; i<8; i++) {
  
    //find the correct value in array of basic values and generate note code 
    if (value == arrayOfBasicValues[i])  { note = arrayOfMIDInotes[i] + (8*shiftRegisterNumber); break; }
    
   }
   
    #ifdef DEBUG
    Serial.print("button: ");
    Serial.print (value);
    Serial.print("\n");
    Serial.print("register number: ");
    Serial.print (shiftRegisterNumber + 1);
    Serial.print("\n");

  #else
    Serial.write(0x90); 
    Serial.write(note); 
    Serial.write(0x45);
    
    #endif
  
}

kustom: ..eventually..

Solved?

Greetz Chris