Go Down

Topic: Shift register 4021 debounce or something else? (Read 1 time) previous topic - next topic

kustom

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.

johnwasser

If you are connecting to physical buttons you should probably include some debounce logic.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

kustom


johnwasser

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.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

kustom

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

Code: [Select]

//#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
 
}
 

Grumpy_Mike

Quote
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.

kustom

#6
Mar 15, 2012, 09:19 pm Last Edit: Mar 15, 2012, 09:28 pm by kustom Reason: 1
I eventually solved it using another array.

Code: [Select]

//#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
 
}



 
 


Go Up