Hi guys.
I would like to send MIDI notes when 2 buttons are pressed at the same time.
Let's say I have a control surface with 3 MIDI note buttons.
When I press buttons 1 and 2 OR buttons 1 and 3 I would like to send different MIDI notes.
See the sketch below, unfortunately it doesn't work as expected:
You can not use the same variable butState to keep track of the two states you want to monitor. They need to be different.
If you want to only send a note once, then you need to detect when a button combination becomes pressed, not if a button combination is pressed. Check out the State Change Detection example in the IDE to learn how (File->examples->02.digital->StateChangeDetection)
I don't see anything in the posted code that is involved with how close to simultaneously the combination needs to be pressed.
If single presses are to be handled as well as combinations that's a problem. You don't want to hang around too long waiting on a possible combination in a musical instrument context, but there will be some delay introduced no matter it be very short.
byte but = digitalRead (PinBut1) | digitalRead (PinBut2) << 1 | digitalRead (PinBut3) << 2;
if (butState != but) { etc.
But you will have to allow for the de-bounce and you haven't yet. You will not be able to start pressing to both buttons exactly at once. But at least you can now just simply compare all states at once from a single variable.
So after every change you should check to see if the state is constant for a period of something like 100ms before you actually accept it as a new state.
and so
if ((but == 0b100) && (butState == 0b111)) {
2 & 3 are being pressed now and before none were pressed.
And at the same time you are running the control surface on those same pins ? I am not so sure that is a good idea. If there is a method for combined button in there you should use that, otherwise you should do all of it outside of that.
I added a second variable but still can't figure out what's the C++ correspondent function of when rather than if.
The new sketch get compiled, but I haven't tested it yet.
if you want to make sure the note stops you will have to use 'else'
if (LOW == butState2) midi.sendNoteOn(note1, velocityHIGH);
else midi.sendNoteOn(note1, velocityLOW);
btw it is a good idea to be consistent in use of '{' & '}' with if statements and use ctrl-T to auto format your code. Don't put more than 1 '}" on a line so it is easier to see the nesting thru the indent int the code.
Sa,e here of course
if (LOW == butState1) midi.sendNoteOn(note0, velocityHIGH);
else midi.sendNoteOn(note0, velocityLOW);
also
byte but =
You declare a variable twice with the same name within the same scope, that is not a good idea ! you can re-use the variable without issue, but re-declare ? the compiler should throw a warning about it.
yeah of course, and now i see that it isn't the same scope, in the original code.
byte but = digitalRead (PinBut1) | digitalRead (PinBut2);
if (butState1 != but) {
so really in the original code the rest only gets executed if there is a change in the state of 1 & 2 combination.
Ah well, that explains the strange behavior. This is what happens with poorly formatted and indented code i guess.
The code in question does not seem to be related to the Control Surface library, it's just standard digital input state change detection logic.
That being said, Control Surface does come with a Button class that could be useful for that purpose: Control Surface: 2.Button.ino
Hi guys, thanks for your answers. @Deva_Rishi I tried to use your bit of sketch;
it runs but it constantly send both notes regardless if I press the buttons or not (see the screenshot attached).
Seriously ?
first of all all button need to be declared INPUT_PULLUP
You also have to read the every time.
Then you compare the value with the old value.
If there is a change, check for every possible double press in the new value for noteOn
and for the old state for noteOff.
What you posted is not my sketch at all and doesn't contain anything that i wrote !
one of the button pins was not pulled up, and the button states never got updated. I am seriously confused about what you posted, but i think that with i posted, you will sort of get what you want. I do hope something clicks and you understand a bit better now.
Hello @Deva_Rishi
thanks for your sketch.
I'm still trying to make it work, unsuccessfully for now I'm afraid.
Also I would like to know what the binary values stand for (0b010 & 0b001).
@PieterP I'd be very intrigued to use the Button you mentioned.
..but how can I use a combination of two or more variables instead of just Button? (see the example below).
bitwise 'or' of the result of the pin state reads. each shifted into their individual bits.
(read up on bitshifting and bitwise logic operations)
All pins are set to INPUT_PULLUP, so if one of the pins is pulled LOW the result of the digitalRead() is
HIGH. Actually digitalRead() returns an int and HIGH == 1 and LOW == 0 by definition. Some people may argue not to use them that way since they are just definitions and they may change in the future, In way that is correct, but somehow i do doubt that it will ever happen. Anyway if all pins are HIGH but == 0b111. for any of the buttons one of the bits is '0' if it is being pressed. (0b101 is the result when pinBut2 is LOW and being pressed.) The program works, maybe the hardware is faulty ?
i ran a simple testprogram to test this particular method,
Hello @Deva_Rishi
I managed to make it work!
There was an issue with IDE.
I really appreciate your help!
However it doesn't seem to work if use buttons that are connected to the Arduino board through a multiplexer.
The sketch gets uploaded and single buttons work as expected BUT buttons combinations don't work.
I wonder if it is anything related with the multiplexer's frequency.
@Deva_Rishi Yes, I wanted to experiment button combinations through a multiplexer.
As I said, all buttons work fine, except the combinations (button1+button2 & button1+button3).