Arcade Button MIDI Controller

Hey everyone,

I’m in the process of building a MIDI controller using the Arduino Uno. So far, I have successfully wired six pots and written a code that makes use of MIDI Control Change messages, to control parameters within a Digital Audio Workstation.

My next step is to add arcade buttons that trigger Note On/Off messages. I have so far wired up one button so that its “NO” terminal plugs into digital pin 12, (TX is being used to wire the MIDI output) and the common terminal is wired to the ground.

I am not sure if this is right so far, or what my next stage is.

Any help would be great :slight_smile:

http://arduino.cc/en/tutorial/button

you have to throw a little resistance in there so its not a direct short to ground, the tutorial show it setup when the button is open it reads low, and high when closed, if you want it the other way swap ground and power

You could show us the code written so far to see if it can be improved upon.

A site with basic MIDI experiments - http://midihacker.com/category/arduino/ - might be inspiring.

(I still have an application on my wishlist that when the C6 is played on my keyboard the lamp above the sheet music goes ON/OFF)

Thank you :)

Code wise, how do I go about triggering a note on message?

I'm thinking it must be an if statement - so if the button state is high, a note plays? Not sure how to write this though.

// POT Variables:
int input_nb = 6;                               // number of analog inputs
int AV[6] = {0,0,0,0,0,0};                      // define variables for the controller data
byte LastAV[6] = {0,0,0,0,0,0};                 // define the last value variables
byte midiCCselect[6] = {20,21,22,23,24,25};     // MIDI controller number (20-31 undefined) this is good for adding extra inputs later on.
byte thresh[6] = {1,1,1,1,1,1};                 // select threshold for each analog input

// BUTTON Variables:
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin
int buttonState = 0;         // variable for reading the pushbutton status
byte note = 0;

void setup() {
  //  Set MIDI baud rate:
  Serial.begin(31250); // 31250
  
  
  //**BUTTONS**
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);   
}

void loop() {
  
  //**POTS**
  
  for (int x =0; x < input_nb; x++) {     // initialisation; condition; increment           
  //  Pot value = 1023
  AV[x] = analogRead(x);
  // Divide this value so it equals 127 (for MIDI)
  int cc = AV[x]/8;
  // If the Control Change is not equal to the last analog value, then send a MIDI CC:
  if (cc !=LastAV[x]) {
  //MIDI Control Change
  midiCC(0xB0, midiCCselect[x], cc);
   // The last value read becomes the new value for the next if statement:
  LastAV[x] = cc;
    }
    
   
  // **BUTTONS**
  
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is LOW:
  if (buttonState == HIGH) {     
  // Play a MIDI note:    
    noteOn(0x90, note, 0x40);  
  } 
  else {
  // Note OFF??:
    digitalWrite(ledPin, LOW); 
  }

  }  
}

// **POTS** sends a Midi CC. 
void midiCC(byte CC_data, byte c_num, byte c_val){
  Serial.write((byte)CC_data);
  Serial.write((byte)c_num);
  Serial.write((byte)c_val);
}

// *BUTTONS** 

//  plays a MIDI note.  Doesn't check to see that
//  cmd is greater than 127, or that data values are  less than 127:
void noteOn(int cmd, int pitch, int velocity) {
  Serial.write(cmd);
  Serial.write(pitch);
  Serial.write(velocity);
}

This is my code so far (it is a bit of a mess, I apologise!)

you must check if a button has changed. that means you must remember its previous state,

something like this

if (digitalRead(12) == HIGH && previousState == LOW)
{
  sendMidiNote();  // or something liek that
  previousState = HIGH;
}
if (digitalRead(12) == LOW) 
{
  previousState = LOW;
}

Thank you :) The type of button I'm using however is not a switch. It returns to its original position once it has been pressed. Will the code you have suggested still be valid for this type of button?

yes

(and technically buttons are just momentary switches :))

Thanks for your input guys :slight_smile:

#include <MIDI.h>


// POT Variables:
int input_nb = 6;                               // number of analog inputs
int AV[6] = {0,0,0,0,0,0};                      // define variables for the controller data
byte LastAV[6] = {0,0,0,0,0,0};                 // define the last value variables
byte midiCCselect[6] = {20,21,22,23,24,25};     // MIDI controller number (20-31 undefined) this is good for adding extra inputs later on.
byte thresh[6] = {1,1,1,1,1,1};                 // select threshold for each analog input



void setup() {
  
  //**BUTTONS**
  // Set inputs and outputs  
  int BUTTON1 = 2;
  int BUTTON2 = 3;
  int BUTTON3 = 4;
  int BUTTON4 = 5;
  int BUTTON6 = 6;
  int BUTTON7 = 7;
  int BUTTON8 = 8;
  int BUTTON9 = 9;
  int LED = 13;
  
  //  Set MIDI baud rate:
  Serial.begin(31250);   

  pinMode(BUTTON1, INPUT);
  pinMode(BUTTON2, INPUT);
  pinMode(BUTTON3, INPUT);
  pinMode(BUTTON4, INPUT);
  pinMode(BUTTON5, INPUT);
  pinMode(BUTTON6, INPUT);
  pinMode(BUTTON7, INPUT);
  pinMode(BUTTON8, INPUT);
  pinMode(BUTTON9, INPUT);
  pinMode(LED, OUTPUT);
}

void loop() {
  
  //**POTS**
  
  for (int x =0; x < input_nb; x++) {     // initialisation; condition; increment    
  
  //  Pot value = 1023
  AV[x] = analogRead(x);
  
  // Divide this value so it equals 127 (for MIDI)
  int cc = AV[x]/8;
  
  // If the Control Change is not equal to the last analog value, then send a MIDI CC:
  if (cc !=LastAV[x]) {
    
  //MIDI Control Change
  midiCC(0xB0, midiCCselect[x], cc);
  
   // The last value read becomes the new value for the next if statement:
  LastAV[x] = cc;
    }
  } 
   
   
   
  // **BUTTONS**
  {
  // read input pins (CURRENTLY ONE BUTTON ONLY FOR TESTING PURPOSES)
  buttonState = digitalRead(BUTTON1);
  
  //check if the button has been pressed.
  //if pressed, the buttonState is LOW:
  if (digitalRead(BUTTON1) == LOW && previousState == LOW)
  digitalWrite(LED, LOW);
  MIDI.sendNoteOn(36,127,1);    //Send Note (C2, vel.127, ch.1)
  note = 1;
  }
  else{
    digitalWrite(LED,HIGH);    //button not pressed, turn off LED
    if(note){
      MIDI.sendNoteOff(36,0,1);
      note = 0;
    }
  }

 

// **POTS** sends a Midi CC. 
void midiCC(byte CC_data, byte c_num, byte c_val){
  Serial.write((byte)CC_data);
  Serial.write((byte)c_num);
  Serial.write((byte)c_val);
}

//  plays a MIDI note.  Doesn't check to see that
//  cmd is greater than 127, or that data values are  less than 127:
void noteOn(int cmd, int pitch, int velocity) {
  Serial.write(cmd);
  Serial.write(pitch);
  Serial.write(velocity);
}

I’ve adapted my code to add what has been suggested. I’ve initialised digital pins for later use, but a button will only be added to one pin for testing purposes.

Does this newer code seem more hopeful?