Pages: [1]   Go Down
Author Topic: Debouncing multiplexed buttons  (Read 1213 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've been working on this for hours how and nothing seems to work.

I have a Mayhew Labs Mux Sheild with 16 push buttons on the first Mux. I'm trying to debounce the input, but nothing I've tried seems to work. Here is the code I have:

Code:
#define CONTROL0 5   
#define CONTROL1 4
#define CONTROL2 3
#define CONTROL3 2

int buttonState[16];
int buttonStatePrev[16];

void setup()
{
 for(int i=0; i < sizeof(buttonState); i++){
    buttonState[i] = 0;
    buttonStatePrev[i] = 0;
  }
 pinMode(CONTROL0, OUTPUT);
  pinMode(CONTROL1, OUTPUT);
  pinMode(CONTROL2, OUTPUT);
  pinMode(CONTROL3, OUTPUT);
 
  MIDI.begin(4);   
  //Serial.begin(9600);
  Serial.begin(115200);
 
  pinMode(14, INPUT);         
  pinMode(15, OUTPUT);
  pinMode(16, INPUT);
   
  digitalWrite(14, HIGH);       
  digitalWrite(15, LOW);
  //digitalWrite(16, HIGH);
}

void loop{
 for (int i=0; i < 16; i++)
    {
      buttonStatePrev[i] = buttonState[i];
      buttonState[i] = digitalReadMUX(i);
     
      //Serial.println(buttonState[i]);
     
      if (buttonState[i] == 1 && buttonStatePrev[i] == 0) {
        MIDI.sendNoteOn(58-i,127,1);
      } else if(buttonState[i] == 0 && buttonStatePrev[i] == 1){
        MIDI.sendNoteOff(58-i,0,1);
      }
     
    }
}

void selectMUXPin(int pin)
{
    digitalWrite(CONTROL0, pin & 8);
    digitalWrite(CONTROL1, pin & 4);
    digitalWrite(CONTROL2, pin & 2);
    digitalWrite(CONTROL3, pin & 1);
}

int digitalReadMUX(int pin)
{
  selectMUXPin(pin);
  return (!digitalRead(14));
}


I tried importing the Bounce library, declaring a bounce object on pin 14 (the pin of the first mux) and in digitalReadMux return the bounce.read(), but for some reason that just completely destroys the logic - only the button on pin M01 pin 1 seems to be read (the rest do nothing) and the resulting MIDI message consists of 16x noteOn messages followed by 16 noteOff messages.

Can anyone help me out here? I've been at this for hours now, and I'm making absolutely no progress.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bump. Can a mod please move this to Multiplexing and LEDs? Might get more help there.
Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 108
Posts: 4021
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
void loop()
{
  for (int i=0; i < 16; i++)
  {
    buttonState[i] = digitalReadMUX(i);                 //get current button state
    if (buttonState[i] == 1 && buttonStatePrev[i] == 0) //the button state has changed
    {
      buttonStateStart[i] = millis();
      //note the time it changed
    }
    if ((millis() - buttonStateStart[i]) > debounceTime)//has been in this state for some time
    {
      //so do stuff here
      buttonStatePrev[i] = buttonState[i];                //remember the button state 
    }
  }
}
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes I've seen that, but how do I incorporate this block of code:

Code:
if (buttonState[i] == 1 && buttonStatePrev[i] == 0) {
        MIDI.sendNoteOn(58-i,127,1);
      } else if(buttonState[i] == 0 && buttonStatePrev[i] == 1){
        MIDI.sendNoteOff(58-i,0,1);
      }

Its meant to send the NoteOn when state changes from off to on and a NoteOff when its state changes from on to off. It works as is, except for the bouncing issue. When I incorporate your code, it sends nothing.

Code:
void loop()
{
  for (int i=0; i < 16; i++)
  {
    buttonState[i] = digitalReadMUX(i);                 //get current button state
    if (buttonState[i] == 1 && buttonStatePrev[i] == 0) //the button state has changed
    {
      buttonStateStart[i] = millis();
      //note the time it changed
    }
   
    if ((millis() - buttonStateStart[i]) > debounceTime)//has been in this state for some time
    {
      //so do stuff here
      if (buttonState[i] == 1 && buttonStatePrev[i] == 0) {
        MIDI.sendNoteOn(58-i,127,1);
      } else if(buttonState[i] == 0 && buttonStatePrev[i] == 1){
        MIDI.sendNoteOff(58-i,0,1);
      }
     
      buttonStatePrev[i] = buttonState[i];
    }
  }
}

At this point I've tried a thousand variations and I still can't get it to debounce properly; I either get a stream of NoteOns and no NoteOffs, or NoteOn NoteOffs that are still bouncing all over the place.
Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 108
Posts: 4021
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't have the hardware to try the multiplexed version using an array of button data but this is a de-bounced button state change program.  Adding the arrays and reading from the multiplexed input should be relatively simple.
Code:
byte buttonPin = 8;
byte currentButtonState = 0;
byte prevButtonState = 1;
byte wasPrevButtonState = 1;
long buttonStateStart;
long debounceTime = 100;

void setup()
{
  Serial.begin(9600);
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
  currentButtonState = digitalRead(buttonPin);
  if (currentButtonState != prevButtonState)  //button state has changed
  {
    buttonStateStart = millis();  //remember the time of the state changed
    wasPrevButtonState = prevButtonState;
    prevButtonState = currentButtonState;    //ready for the next change check
  }

  if ((millis() - buttonStateStart) > debounceTime)  //has been in this state for some time
  {   
    if (currentButtonState == 0  && wasPrevButtonState == 1)
    {
      Serial.println("action 1");
      wasPrevButtonState = currentButtonState;        //stop the action happening again until state changes
    }
    else if (currentButtonState == 1  && wasPrevButtonState == 0)
    {
      Serial.println("action 2");
      wasPrevButtonState = currentButtonState;        //stop the action happening again until state changes
    }
  }
}
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Valencia, Spain
Online Online
Faraday Member
**
Karma: 143
Posts: 5309
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Try this:

Code:
void loop()
{
  for (int i=0; i < 16; i++)
  {
    if ((millis() - buttonStateStart[i]) > debounceTime)// Allow some time to pass between changes
    {
      buttonState[i] = digitalReadMUX(i);        //get current button state
      if (buttonState[i] != buttonStatePrev[i]) //the button state has changed
      {
        if (buttonState[i] == 1) {
          MIDI.sendNoteOn(58-i,127,1);
        }
        else {
          MIDI.sendNoteOff(58-i,0,1);
        }
        buttonStateStart[i] = millis();
        buttonStatePrev[i] = buttonState[i];
      }
    }
  }
}

Logged

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It seems so obvious now, kicking myself! Thank you Fungus!
Logged

Valencia, Spain
Online Online
Faraday Member
**
Karma: 143
Posts: 5309
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think you can simplify it a bit, use less RAM:

Code:
void loop()
{
  for (int i=0; i < 16; i++)
  {
    if ((millis() - buttonStateStart[i]) > debounceTime)// Allow some time to pass between changes
    {
      byte b = digitalReadMUX(i);        //get current button state
      if (b != buttonStatePrev[i]) //the button state has changed
      {
        if (b == 1) {
          MIDI.sendNoteOn(58-i,127,1);
        }
        else {
          MIDI.sendNoteOff(58-i,0,1);
        }
        buttonStatePrev[i] = b;
        buttonStateStart[i] = millis();
      }
    }
  }
}
Logged

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

Pages: [1]   Go Up
Jump to: