controlChange from the MIDIUSB library stops working when I add Debounce

It is driving me crazy and I can't for the life of me figure out why it's acting this way.

My code is working properly, when I press the button it spits out alternating low/high into the serial monitor with a proper debounce delay. But adding the debounce delay always seems to kill my controlChange function.

For testing purposes, I copied the controlChange function, and repeated it several times in each if statement. It actually worked better that way, I have no clue why. It seems to need to be spammed for anything to read it properly.

#include <frequencyToNote.h>
#include <MIDIUSB.h>
#include <pitchToFrequency.h>
#include <pitchToNote.h>

// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).
// controlChange(0, 10, 65); // Set the value of controller 10 on channel 0 to 65

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

int lastPotValue;
int lastButtonState=0;



unsigned long lastDebounce = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(A0, INPUT);
  pinMode(7, INPUT_PULLUP);
}

void loop() {
  
  unsigned long currentTime = millis();
  int potValue = analogRead(A0);
  int buttonValue = digitalRead(7);

  if (lastPotValue != potValue){
    controlChange(0, 50, potValue/7.90);
    lastPotValue = potValue;
    lastDebounce = currentTime;
  }

  if (buttonValue == LOW && currentTime - lastDebounce > 250){
    if (lastButtonState == 0){
      controlChange(1,51,127);
      Serial.println(lastButtonState);
      lastButtonState = 1;
      lastDebounce = currentTime;
      
    }
    else if (lastButtonState == 1){
      controlChange(1,51,127);
      Serial.println(lastButtonState);
      lastButtonState = 0;
      lastDebounce = currentTime;
    }
  }
}

This bit of code is useless

else if (lastButtonState == 1){

Because you only get to the else once lastButtonState is not zero. Replace it with

else {

That will not stop it working but it shows a bit of inexperience with code.

It is this bit of code where things might be going wrong

if (lastPotValue != potValue){
    controlChange(0, 50, potValue/7.90);
    lastPotValue = potValue;
    lastDebounce = currentTime;
  }

You are changing the lastDebounce variable which you use to debounce your switch!
Why?
Also note that any A/D conversions will always return +/- one least significant bit no matter what the noise level so you don't usually use == or != with pot values. Much better to use a difference such as:-

if (abs(lastPotValue - potValue) > threshold){

where threshold is a variable which shows the amount of change you need to trigger sending the pot control change.
Also potValue/7.90 is just silly use potValue>>3 instead to convert an A/D reading into a MIDI value. The >> is the shift right operator.

Grumpy_Mike:
This bit of code is useless

else if (lastButtonState == 1){

Because you only get to the else once lastButtonState is not zero. Replace it with

else {

That will not stop it working but it shows a bit of inexperience with code.

It is this bit of code where things might be going wrong

if (lastPotValue != potValue){

controlChange(0, 50, potValue/7.90);
    lastPotValue = potValue;
    lastDebounce = currentTime;
  }



You are changing the lastDebounce variable which you use to debounce your switch!
Why?
Also note that any A/D conversions will always return +/- one least significant bit no matter what the noise level so you don't usually use == or != with pot values. Much better to use a difference such as:-


if (abs(lastPotValue - potValue) > threshold){



where threshold is a variable which shows the amount of change you need to trigger sending the pot control change.
Also potValue/7.90 is just silly use potValue>>3 instead to convert an A/D reading into a MIDI value. The >> is the shift right operator.

thanks, yes I just started learning C about a month ago.. I am clearly not proficient in all of the operators and code. However... the point still stands, why doesn't this script appropriately send MIDI signals? I know my IF statements are triggering because of the serial output.

re: the lastButtonState being useless... the reason that is there is because I was actually sending a different MIDI value originally. I am currently figuring out which values trigger appropriately.

re: the lastDebounce. I thought that after a successful button press you need to reset the last time the button was pressed to the current time to 'restart' the counter for the next debounce? I am not sure what you are saying is wrong with it.

re: A/D conversion. I will try that ABS code. I had previously tried doing a check to see if its + or - 1 but when that got converted to MIDI outputs I was getting some very big stepping problems.. eg it would set a control knob to 0, 3%, 5%, 8%, etc... skipping numbers.

re: I am not familiar with shifting at all, I used 7.9 because dividing by 8 was cutting off the 100% midi value for some reason.

However... the point still stands, why doesn't this script appropriately send MIDI signals?

I just told you.

re: the lastButtonState being useless... the reason that is there is because I was actually sending a different MIDI value originally.

Did you not read what I said? It is the "if" statement that was useless, with the else part you can still put something different.

re: I am not familiar with shifting at all, I used 7.9 because dividing by 8 was cutting off the 100% midi value for some reason.

Well given your lack of comprehension you have shown so far, I think you are misunderstanding what you saw.

re: the lastDebounce. I thought that after a successful button press you need to reset the last time the button was pressed to the current time to 'restart' the counter for the next debounce? I am not sure what you are saying is wrong with it.

FFS do you not read anything? You are changing the lastDebounce variable inside the code that reads the pot. This pot is read every time round the loop thus screwing up what you want to achieve.

You are not yet good enough to have attitude like this.

Grumpy_Mike:
I just told you.
Did you not read what I said? It is the "if" statement that was useless, with the else part you can still put something different.
Well given your lack of comprehension you have shown so far, I think you are misunderstanding what you saw.
FFS do you not read anything? You are changing the lastDebounce variable inside the code that reads the pot. This pot is read every time round the loop thus screwing up what you want to achieve.

You are not yet good enough to have attitude like this.

I apologize, I misunderstood what you said. However, I was not doubting what you were saying, I was just saying why I did what I did, and why I thought it was right.

I think I see where I misread your post. Let me look into it.

Thanks

edit: I figured it out.....

Apparently I needed to put "MidiUSB.flush()" after each midi command to force it to send.

Thanks for pointing out the debounce issue though, I definitely overlooked that other if statement.

#include <frequencyToNote.h>
#include <MIDIUSB.h>
#include <pitchToFrequency.h>
#include <pitchToNote.h>

// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).
// controlChange(0, 10, 65); // Set the value of controller 10 on channel 0 to 65

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

int lastPotValue;
int lastButtonState=0;



unsigned long lastDebounce = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(A0, INPUT);
  pinMode(7, INPUT_PULLUP);
}

void loop() {
  
  unsigned long currentTime = millis();
  int potValue = analogRead(A0);
  int buttonValue = digitalRead(7);

//  if (lastPotValue != potValue){
//    controlChange(0, 50, potValue/7.90);
//    lastPotValue = potValue;
//    lastDebounce = currentTime;
//  }

  if (buttonValue == LOW && currentTime - lastDebounce > 250){
    if (lastButtonState == 0){
      controlChange(1,51,127);
      Serial.println(lastButtonState);
      lastButtonState = 1;
      lastDebounce = currentTime;
      
    }
    else {
      controlChange(1,51,0);
      Serial.println(lastButtonState);
      lastButtonState = 0;
      lastDebounce = currentTime;
    }
  }
}