Midi Controller/DAW/Micro: false triggering because of stage vibrations?

Disclaimer: very new to arduino and electronics in general.

I'm a musician. I built a MIDI Controller to play samples on my laptop when playing music live. (with this tutorial: https://www.instructables.com/DIY-USB-Midi-Controller-With-Arduino-a-Beginners-G/)

It's just one button (a big red buzzer, arduino is put inside the button).
It works flawlessly when rehearsing. Unless: I take it on stage.
On several occasions when I played concerts it just triggered play even though the button wasn't touched.

I eventually shielded off all the cables very well so I was sure cables weren't touching and triggering something and even got a new arduino micro just in case the board was faulty. I feel like it got a bit better but the issue still hasn't resolved.

Played a gig recently and on soundcheck I noticed that when a certain frequency (low rumbly bass) from a synthesizer got played, the arduino triggered play without the button being touched.

Button was close to the subwoofer at that point. I moved it to another place on the stage and the issue resolved for the moment. Still at some point during the show it happened again.

Does anybody know what that could be about? How rumbling frequencies / external magnet fields / whatever is around on a stage could trigger the button? and how i could avoid it?

thanks alotttt,
Jodok

install infrared near sensor. it should disable input from the button when no hand is over.

Thanksss! So, it can be inside a dark closed off case and still work?
Also would there be no other solution for the arduino / the circuit to not be sensitive to external circumstances like vibrations or magnet / electronic fields?

Normally one would increase the button debounce. What is the sketch you uploaded ?

it is obvious that electronic is sensitive to electric and magnetic fields. normally, Faradey cage used for protection.
if you want to sense thru enclosure you may want try radar sensor

Show us how you have actually wired it. If the button is far away from the micro, this is probably anyway your issue.
You may be best of using a trigger with an opto-coupler on the micro and a power source becoming active when pressing the button, lighting the opto-coupler led, and thus triggering the GPIO of the micro.

Sure! Some more documentation:

/*
  Based on Sketch built by Gustavo Silveira (aka Music Nerd)
  Modified by Dolce Wang

  This code is only for Arduinos that use ATmega32u4 (like Micro, Pro Micro, Leonardo...)
  Remember to also assign the correct board in the IDE (like Tools / Boards / Sparkfun AVR / Pro Micro...)

*/

// Change any fields with //**


// LIBRARY

#include "MIDIUSB.h" 

// BUTTONS
const int NButtons = 1; //***  total number of buttons
const int buttonPin[NButtons] = {9}; //*** define Digital Pins connected from Buttons to Arduino; (ie {10, 16, 14, 15, 6, 7, 8, 9, 2, 3, 4, 5}; 12 buttons)
                                            
int buttonCState[NButtons] = {};        // stores the button current value
int buttonPState[NButtons] = {};        // stores the button previous value

      
// debounce
unsigned long lastDebounceTime[NButtons] = {0};  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    //** the debounce time; increase if the output flickers

/*
// POTENTIOMETERS
const int NPots = 8; //*** total number of pots (knobs and faders)
const int potPin[NPots] = {A9, A8, A7, A6, A3, A2, A1, A0}; //*** define Analog Pins connected from Pots to Arduino; Leave nothing in the array if 0 pots {}
int potCState[NPots] = {0}; // Current state of the pot; delete 0 if 0 pots
int potPState[NPots] = {0}; // Previous state of the pot; delete 0 if 0 pots
int potVar = 0; // Difference between the current and previous state of the pot

int midiCState[NPots] = {0}; // Current state of the midi value; delete 0 if 0 pots
int midiPState[NPots] = {0}; // Previous state of the midi value; delete 0 if 0 pots

const int TIMEOUT = 300; //* Amount of time the potentiometer will be read after it exceeds the varThreshold
const int varThreshold = 10; //* Threshold for the potentiometer signal variation
boolean potMoving = true; // If the potentiometer is moving
unsigned long PTime[NPots] = {0}; // Previously stored time; delete 0 if 0 pots
unsigned long timer[NPots] = {0}; // Stores the time that has elapsed since the timer was reset; delete 0 if 0 pots
*/

// MIDI Assignments 
byte midiCh = 1; //* MIDI channel to be used
byte note = 36; //* Lowest note to be used; 36 = C2; 60 = Middle C
byte cc = 1; //* Lowest MIDI CC to be used


// SETUP
void setup() {

  // Baud Rate
  // 31250 for MIDI class compliant | 115200 for Hairless MIDI

  // Buttons
  // Initialize buttons with pull up resistors
  for (int i = 0; i < NButtons; i++) {
    pinMode(buttonPin[i], INPUT_PULLUP);
  }

}

////
// LOOP
void loop() {

  buttons();
  /*potentiometers();*/

}

////
// BUTTONS
void buttons() {

  for (int i = 0; i < NButtons; i++) {

    buttonCState[i] = digitalRead(buttonPin[i]);  // read pins from arduino

    if ((millis() - lastDebounceTime[i]) > debounceDelay) {

      if (buttonPState[i] != buttonCState[i]) {
        lastDebounceTime[i] = millis();

        if (buttonCState[i] == LOW) {

          // Sends the MIDI note ON 
          
         // use if using with ATmega32U4 (micro, pro micro, leonardo...)
          noteOn(midiCh, note + i, 127);  // channel, note, velocity
          MidiUSB.flush();


        }
        else {

          // Sends the MIDI note OFF accordingly to the chosen board

          // use if using with ATmega32U4 (micro, pro micro, leonardo...)
          noteOn(midiCh, note + i, 0);  // channel, note, velocity
          MidiUSB.flush();

        }
        buttonPState[i] = buttonCState[i];
      }
    }
  }
}
/*
////
// POTENTIOMETERS
void potentiometers() {


  for (int i = 0; i < NPots; i++) { // Loops through all the potentiometers

    potCState[i] = analogRead(potPin[i]); // reads the pins from arduino

    midiCState[i] = map(potCState[i], 0, 1023, 0, 127); // Maps the reading of the potCState to a value usable in midi

    potVar = abs(potCState[i] - potPState[i]); // Calculates the absolute value between the difference between the current and previous state of the pot

    if (potVar > varThreshold) { // Opens the gate if the potentiometer variation is greater than the threshold
      PTime[i] = millis(); // Stores the previous time
    }

    timer[i] = millis() - PTime[i]; // Resets the timer 11000 - 11000 = 0ms

    if (timer[i] < TIMEOUT) { // If the timer is less than the maximum allowed time it means that the potentiometer is still moving
      potMoving = true;
    }
    else {
      potMoving = false;
    }

    if (potMoving == true) { // If the potentiometer is still moving, send the change control
      if (midiPState[i] != midiCState[i]) {

        // Sends  MIDI CC 
        // Use if using with ATmega32U4 (micro, pro micro, leonardo...)
        controlChange(midiCh, cc + i, midiCState[i]); //  (channel, CC number,  CC value)
        MidiUSB.flush();

        potPState[i] = potCState[i]; // Stores the current reading of the potentiometer to compare with the next
        midiPState[i] = midiCState[i];
      }
    }
  }
}

*/
// if using with ATmega32U4 (micro, pro micro, leonardo...)


// Arduino MIDI functions MIDIUSB Library
void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

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

/*
  Based on Sketch built by Gustavo Silveira (aka Music Nerd)
  Modified by Dolce Wang

  This code is only for Arduinos that use ATmega32u4 (like Micro, Pro Micro, Leonardo...)
  Remember to also assign the correct board in the IDE (like Tools / Boards / Sparkfun AVR / Pro Micro...)

*/

// Change any fields with //**


// LIBRARY

#include "MIDIUSB.h" 

// BUTTONS
const int NButtons = 1; //***  total number of buttons
const int buttonPin[NButtons] = {9}; //*** define Digital Pins connected from Buttons to Arduino; (ie {10, 16, 14, 15, 6, 7, 8, 9, 2, 3, 4, 5}; 12 buttons)
                                            
int buttonCState[NButtons] = {};        // stores the button current value
int buttonPState[NButtons] = {};        // stores the button previous value

      
// debounce
unsigned long lastDebounceTime[NButtons] = {0};  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    //** the debounce time; increase if the output flickers

/*
// POTENTIOMETERS
const int NPots = 8; //*** total number of pots (knobs and faders)
const int potPin[NPots] = {A9, A8, A7, A6, A3, A2, A1, A0}; //*** define Analog Pins connected from Pots to Arduino; Leave nothing in the array if 0 pots {}
int potCState[NPots] = {0}; // Current state of the pot; delete 0 if 0 pots
int potPState[NPots] = {0}; // Previous state of the pot; delete 0 if 0 pots
int potVar = 0; // Difference between the current and previous state of the pot

int midiCState[NPots] = {0}; // Current state of the midi value; delete 0 if 0 pots
int midiPState[NPots] = {0}; // Previous state of the midi value; delete 0 if 0 pots

const int TIMEOUT = 300; //* Amount of time the potentiometer will be read after it exceeds the varThreshold
const int varThreshold = 10; //* Threshold for the potentiometer signal variation
boolean potMoving = true; // If the potentiometer is moving
unsigned long PTime[NPots] = {0}; // Previously stored time; delete 0 if 0 pots
unsigned long timer[NPots] = {0}; // Stores the time that has elapsed since the timer was reset; delete 0 if 0 pots
*/

// MIDI Assignments 
byte midiCh = 1; //* MIDI channel to be used
byte note = 36; //* Lowest note to be used; 36 = C2; 60 = Middle C
byte cc = 1; //* Lowest MIDI CC to be used


// SETUP
void setup() {

  // Baud Rate
  // 31250 for MIDI class compliant | 115200 for Hairless MIDI

  // Buttons
  // Initialize buttons with pull up resistors
  for (int i = 0; i < NButtons; i++) {
    pinMode(buttonPin[i], INPUT_PULLUP);
  }

}

////
// LOOP
void loop() {

  buttons();
  /*potentiometers();*/

}

////
// BUTTONS
void buttons() {

  for (int i = 0; i < NButtons; i++) {

    buttonCState[i] = digitalRead(buttonPin[i]);  // read pins from arduino

    if ((millis() - lastDebounceTime[i]) > debounceDelay) {

      if (buttonPState[i] != buttonCState[i]) {
        lastDebounceTime[i] = millis();

        if (buttonCState[i] == LOW) {

          // Sends the MIDI note ON 
          
         // use if using with ATmega32U4 (micro, pro micro, leonardo...)
          noteOn(midiCh, note + i, 127);  // channel, note, velocity
          MidiUSB.flush();


        }
        else {

          // Sends the MIDI note OFF accordingly to the chosen board

          // use if using with ATmega32U4 (micro, pro micro, leonardo...)
          noteOn(midiCh, note + i, 0);  // channel, note, velocity
          MidiUSB.flush();

        }
        buttonPState[i] = buttonCState[i];
      }
    }
  }
}
/*
////
// POTENTIOMETERS
void potentiometers() {


  for (int i = 0; i < NPots; i++) { // Loops through all the potentiometers

    potCState[i] = analogRead(potPin[i]); // reads the pins from arduino

    midiCState[i] = map(potCState[i], 0, 1023, 0, 127); // Maps the reading of the potCState to a value usable in midi

    potVar = abs(potCState[i] - potPState[i]); // Calculates the absolute value between the difference between the current and previous state of the pot

    if (potVar > varThreshold) { // Opens the gate if the potentiometer variation is greater than the threshold
      PTime[i] = millis(); // Stores the previous time
    }

    timer[i] = millis() - PTime[i]; // Resets the timer 11000 - 11000 = 0ms

    if (timer[i] < TIMEOUT) { // If the timer is less than the maximum allowed time it means that the potentiometer is still moving
      potMoving = true;
    }
    else {
      potMoving = false;
    }

    if (potMoving == true) { // If the potentiometer is still moving, send the change control
      if (midiPState[i] != midiCState[i]) {

        // Sends  MIDI CC 
        // Use if using with ATmega32U4 (micro, pro micro, leonardo...)
        controlChange(midiCh, cc + i, midiCState[i]); //  (channel, CC number,  CC value)
        MidiUSB.flush();

        potPState[i] = potCState[i]; // Stores the current reading of the potentiometer to compare with the next
        midiPState[i] = midiCState[i];
      }
    }
  }
}

*/
// if using with ATmega32U4 (micro, pro micro, leonardo...)


// Arduino MIDI functions MIDIUSB Library
void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

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

how is it working at all without any initiation?

You need to explain me: what is an initiation?
non native english speaker and new to the whole of this. :slight_smile:

this one

but if it work so then try this

#include "MIDIUSB.h"

const int buttonPin = 9; 

// debounce
unsigned long lastDebounceTime = 0;  
unsigned long debounceDelay = 100;   

// MIDI Assignments
const byte midiCh = 1; //* MIDI channel to be used
const byte note = 36; //* Lowest note to be used; 36 = C2; 60 = Middle C

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {
  if (!digitalRead(buttonPin)) {
    if (lastDebounceTime == 0)lastDebounceTime = millis();
  }
  else {
    noteOff();
    lastDebounceTime = 0;
  }

  if (lastDebounceTime > 0)
    if (millis() - lastDebounceTime > debounceDelay) {
      noteOn();
      lastDebounceTime = 0;
    }
}

void noteOn() {
  midiEventPacket_t noteOn = {0x09, 0x90 | midiCh, note, 127};
  MidiUSB.sendMIDI(noteOn);
  MidiUSB.flush();
}

void noteOff() {
  midiEventPacket_t noteOff = {0x09, 0x90 | midiCh, note, 0};
  MidiUSB.sendMIDI(noteOff);
  MidiUSB.flush();
}

and here is how library example initiate

/*
 * MIDIUSB_test.ino
 *
 * Created: 4/6/2015 10:47:08 AM
 * Author: gurbrinder grewal
 * Modified by Arduino LLC (2015)
 */ 

#include "MIDIUSB.h"

// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

void setup() {
  Serial.begin(115200);
}

// 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).

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

void loop() {
  Serial.println("Sending note on");
  noteOn(0, 48, 64);   // Channel 0, middle C, normal velocity
  MidiUSB.flush();
  delay(500);
  Serial.println("Sending note off");
  noteOff(0, 48, 64);  // Channel 0, middle C, normal velocity
  MidiUSB.flush();
  delay(1500);

  // controlChange(0, 10, 65); // Set the value of controller 10 on channel 0 to 65
}

Hello jodoker

Welcome to the worldbest Arduino forum ever.

Consider this proposal. I have cleaned up your Button Manager.

#include "MIDIUSB.h"

const int buttonPin = 9;      //*** define Digital Pins connected from Buttons to Arduino; (ie {10, 16, 14, 15, 6, 7, 8, 9, 2, 3, 4, 5}; 12 buttons)
uint8_t buttonCState = LOW;     // stores the button current state
uint8_t buttonCStateOld = LOW;     // stores the button old value

// debounce
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 100;    //** the debounce time; increase if the output flickers

// MIDI Assignments
const byte midiCh = 1; //* MIDI channel to be used
const byte note = 36; //* Lowest note to be used; 36 = C2; 60 = Middle C

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
  uint32_t currentMillis {millis()};
  if (currentMillis - lastDebounceTime >= debounceDelay)
  {
    lastDebounceTime = currentMillis;
    buttonCState = digitalRead(buttonPin) ? LOW : HIGH;
    if (buttonCStateOld != buttonCState)
    {
      buttonCStateOld = buttonCState;
      if (buttonCState == HIGH)
      {
        noteOn();
      }
      else
      {
        noteOff();
      }
    }
  }
  /*
    buttonCState = !digitalRead(buttonPin);
    if (buttonCState) {
    if (lastDebounceTime == 0)lastDebounceTime = millis();
    }
    else {
    noteOff();
    lastDebounceTime = 0;
    }

    if (lastDebounceTime > 0)
    if (millis() - lastDebounceTime > debounceDelay) {
      noteOn();
      lastDebounceTime = 0;
    }
  */
}

void noteOn() {
  midiEventPacket_t noteOn = {0x09, 0x90 | midiCh, note, 127};
  MidiUSB.sendMIDI(noteOn);
  MidiUSB.flush();
}

void noteOff() {
  midiEventPacket_t noteOff = {0x09, 0x90 | midiCh, note, 0};
  MidiUSB.sendMIDI(noteOff);
  MidiUSB.flush();
}

hth

Have a nice day and enjoy coding in C++.

really?

Why don't I understand this question?

    buttonCState = digitalRead(buttonPin) ;
    if (buttonCStateOld != buttonCState)
    {
      buttonCStateOld = buttonCState;
      if (buttonCState )
      {
        noteOff();
      }
      else
      {
         noteOn();
     }
    }

Up to you.
Do it as you like.

Well we have a method of posting photos in a thread, and that's not it.

Regardless, how long is the wire between the button & the Arduino ?

1 Like

I was only allowed to post 3 photos at a low resolution, so I thought sharing a link works better.
sorry if that's outside any guidelines.

It's about 8cm. long

Hmmm are you sure that the soldering connections are good ? could you re-malt them once, just in case.
Other option is that there is an internal part of the switch which start to vibrate along.

Regardless, for debounce you should test that the button-change is consistent for the de-bounce time specified. In other words, if you detect a change, that change should be consistent, for at least 100ms ( 50ms equals 20Hz, which is actually similar to what comes out of the sub-woofer) and you should test it constantly for those 100ms. (rather than just test it afterwards)

I'm sure that is the source of your problems.

image

This is a very bad design and leaves the input as a 10k aerial, so its susceptible to local electric fields.

This explains a better design, with the button connected to ground.

image

Rt is just to show the track (or in your case wire) resistance. You should choose a low value (say 1k) for the pullup resistor, Rpu and around 1uF for the capacitor.
You should also connect a capacitor across the Vcc and Ground rails to stablise that supply.

1 Like