/*
25 Key Midi Footpedal with
Octave Up/Down, Mod, Sustain, and Volume
Created by Brad Hill on 19-06-2015
based primarily on Teensy "Buttons" with snippets from
MidiHacker's MultiButtonMIDIOctave.ino,
Graham Wykes' Miditzer Pedalboard Scanner for Teensy2.0++ board,
Lionel Cassin's "midi-bass-pedals-using-arduino.html",
G333T's video (https://www.youtube.com/watch?v=9J_tGVLD7UQ),
and various Teensy/Arduino definitions and examples.
This code is released into the Public Domain.
*/
#include <Bounce.h>
const int channel = 1; // the MIDI channel number to send messages
const int ms = 5; // bounce time in ms (increase for more sensitve switches)
const int d = 25; // default delay time (ms) for "activity" LED
int LEDU = 0; // pin for octave up LED
int LEDD = 1; // pin for ocatave down LED
int octaveup = 32; // pin for octave up switch
int octavedown = 33; // pin for octave down switch
int octave = 3; // set base octave
int vpot = 38; // pin setup for volume pot
int vol; // place holder for vpot reading
int vel = 99; // fixed note velocity
// Create Bounce objects for each button. The Bounce object
// automatically deals with contact chatter or "bounce", and
// it makes detecting changes very simple.
Bounce button0 = Bounce(0, ms);
Bounce button1 = Bounce(1, ms); // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, ms); // which is appropriate for good
Bounce button3 = Bounce(3, ms); // quality mechanical pushbuttons
Bounce button4 = Bounce(4, ms);
Bounce button5 = Bounce(5, ms); // if a button is too "sensitive"
Bounce button6 = Bounce(6, ms); // to rapid touch, you can
Bounce button7 = Bounce(7, ms); // increase this time.
Bounce button8 = Bounce(8, ms);
Bounce button9 = Bounce(9, ms);
Bounce button10 = Bounce(10, ms);
Bounce button11 = Bounce(11, ms);
Bounce button12 = Bounce(12, ms);
Bounce button13 = Bounce(13, ms);
Bounce button14 = Bounce(14, ms);
Bounce button15 = Bounce(15, ms);
Bounce button16 = Bounce(16, ms);
Bounce button17 = Bounce(17, ms);
Bounce button18 = Bounce(18, ms);
Bounce button19 = Bounce(19, ms);
Bounce button20 = Bounce(20, ms);
Bounce button21 = Bounce(21, ms);
Bounce button22 = Bounce(22, ms);
Bounce button23 = Bounce(23, ms);
Bounce button24 = Bounce(24, ms);
Bounce button25 = Bounce(25, ms);
Bounce button26 = Bounce(26, ms);
Bounce button27 = Bounce(27, ms);
Bounce button28 = Bounce(28, ms);
Bounce button29 = Bounce(29, ms);
Bounce button30 = Bounce(30, ms);
Bounce button31 = Bounce(31, ms);
Bounce button32 = Bounce(32, ms);
Bounce button33 = Bounce(33, ms);
Bounce button34 = Bounce(34, ms);
Bounce button35 = Bounce(35, ms);
Bounce button36 = Bounce(36, ms);
Bounce button37 = Bounce(37, ms);
Bounce button38 = Bounce(38, ms);
Bounce button39 = Bounce(39, ms);
Bounce button40 = Bounce(40, ms);
Bounce button41 = Bounce(41, ms);
Bounce button42 = Bounce(42, ms);
Bounce button43 = Bounce(43, ms);
Bounce button44 = Bounce(44, ms);
Bounce button45 = Bounce(45, ms);
//--------------------------SETUP-----------------------------------------------
//------------------------------------------------------------------------------
void setup() {
// Configure the pins for input mode with pullup resistors.
// The pushbuttons connect from each pin to ground. When
// the button is pressed, the pin reads LOW because the button
// shorts it to ground. When released, the pin reads HIGH
// because the pullup resistor connects to +5 volts inside
// the chip. LOW for "on", and HIGH for "off" may seem
// backwards, but using the on-chip pullup resistors is very
// convenient. The scheme is called "active low", and it's
// very commonly used in electronics... so much that the chip
// has built-in pullup resistors!
pinMode(0, OUTPUT); // LED for "octave up"
pinMode(1, OUTPUT); // LED for "octave down"
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP); // TX output for MIDI Jack
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, OUTPUT); // Teensy++ 2.0 LED, may need 1k resistor pullup
pinMode(7, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
pinMode(10, INPUT_PULLUP);
pinMode(11, INPUT_PULLUP);
pinMode(12, INPUT_PULLUP);
pinMode(13, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
pinMode(15, INPUT_PULLUP);
pinMode(16, INPUT_PULLUP);
pinMode(17, INPUT_PULLUP);
pinMode(18, INPUT_PULLUP);
pinMode(19, INPUT_PULLUP);
pinMode(20, INPUT_PULLUP);
pinMode(21, INPUT_PULLUP);
pinMode(22, INPUT_PULLUP);
pinMode(23, INPUT_PULLUP);
pinMode(24, INPUT_PULLUP);
pinMode(25, INPUT_PULLUP);
pinMode(26, INPUT_PULLUP);
pinMode(27, INPUT_PULLUP);
pinMode(28, INPUT_PULLUP);
pinMode(29, INPUT_PULLUP);
pinMode(30, INPUT_PULLUP);
pinMode(31, INPUT_PULLUP);
pinMode(32, INPUT_PULLUP);
pinMode(33, INPUT_PULLUP);
pinMode(34, INPUT_PULLUP);
pinMode(35, INPUT_PULLUP);
pinMode(36, INPUT_PULLUP);
pinMode(37, INPUT_PULLUP);
pinMode(38, INPUT_PULLUP);
pinMode(39, INPUT_PULLUP);
pinMode(40, INPUT_PULLUP);
pinMode(41, INPUT_PULLUP);
pinMode(42, INPUT_PULLUP);
pinMode(43, INPUT_PULLUP);
pinMode(44, INPUT_PULLUP);
pinMode(45, INPUT_PULLUP);
digitalWrite(6,HIGH); // Set Teensy++ fixed LED to "on"
digitalWrite(0,LOW); // Set "octave up" LED to "off"
digitalWrite(1,LOW); // Set "octave down" LED to "off
}
//--------------------------MAIN LOOP-------------------------------------
//------------------------------------------------------------------------
void loop() {
// Update all the buttons. There should not be any long
// delays in loop(), so this runs repetitively at a rate
// faster than the buttons could be pressed and released.
button0.update();
button1.update();
button2.update();
button3.update();
button4.update();
button5.update();
button6.update();
button7.update();
button8.update();
button9.update();
button10.update();
button11.update();
button12.update();
button13.update();
button14.update();
button15.update();
button16.update();
button17.update();
button18.update();
button19.update();
button20.update();
button21.update();
button22.update();
button23.update();
button24.update();
button25.update();
button26.update();
button27.update();
button28.update();
button29.update();
button30.update();
button31.update();
button32.update();
button33.update();
button34.update();
button35.update();
button36.update();
button37.update();
button38.update();
button39.update();
button40.update();
button41.update();
button42.update();
button43.update();
button44.update();
button45.update();
//---------------------------------SET OCTAVE --------------------------------------------
int up = digitalRead(octaveup); // alias "octaveup" pin read as "up"
int down = digitalRead(octavedown); // alias "octavedown" pin read as "down"
if(up == LOW){ // if "up" button pressed
if(octave < 6){ octave++; // constrain highest note to C8 (108)
}
while(up == LOW){ // wait until button is released
up = digitalRead(octaveup);
delay(20);
}
}
if(down == LOW){ // if "down" button pressed
if(octave > 1){ octave--; // constrain lowest note to C1 (24)
}
while(down == LOW){ // wait until button is released
down = digitalRead(octavedown);
delay(20);
}
}
if(up && down == LOW){ // if "up" and "down" buttons both pressed
octave = 3; // return to base octave
}
if(octave > 3){ // if the octave is above base
digitalWrite(LEDU,HIGH); // turn on "octave up" LED
} else { // otherwise leave it off
digitalWrite(LEDU,LOW);
}
if(octave < 3){ // if the current octave is below base
digitalWrite(LEDD,HIGH); // turn on the "octave down" LED
} else { // otherwise leave it off
digitalWrite(LEDD,LOW);
}
vol = analogRead(vpot); // Read velocity from the volume pot
vel = map(vol, 0, 1023, 0, 127); // change the velocity range
// from "pot range" (0-1023)
// to "MIDI range" (0-127)
//----------------------READ BUTTON PINS FOR NOTE ON--------------------------------------------------
// Check each button from 7 - 31 for "falling" edge.
// Send a MIDI Note On message when each button presses
// Update the Joystick buttons only upon changes.
// falling = high (not pressed - voltage from pullup resistor)
// to low (pressed - button connects pin to ground)
if (button7.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(12 + (octave*12), vel, channel); // C
delay(d);
digitalWrite(6,HIGH);
}
if (button8.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(13 + (octave*12), vel, channel); // C#
delay(d);
digitalWrite(6,HIGH);
}
if (button9.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(14 + (octave*12), vel, channel); // D
delay(d);
digitalWrite(6,HIGH);
}
if (button10.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(15 + (octave*12), vel, channel); // Eb
delay(d);
digitalWrite(6,HIGH);
}
if (button11.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(16 + (octave*12), vel, channel); // E
delay(d);
digitalWrite(6,HIGH);
}
if (button12.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(17 + (octave*12), vel, channel); // F
delay(d);
digitalWrite(6,HIGH);
}
if (button13.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(18 + (octave*12), vel, channel); // F
delay(d);
digitalWrite(6,HIGH);
}
if (button14.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(19 + (octave*12), vel, channel); // G
delay(d);
digitalWrite(6,HIGH);
}
if (button15.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(20 + (octave*12), vel, channel); // G#
delay(d);
digitalWrite(6,HIGH);
}
if (button16.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(21 + (octave*12), vel, channel); // A
digitalWrite(6,HIGH);
}
if (button17.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(22 + (octave*12), vel, channel); // B
delay(d);
digitalWrite(6,HIGH);
}
if (button18.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(23 + (octave*12), vel, channel); // B
delay(d);
digitalWrite(6,HIGH);
}
if (button19.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(24 + (octave*12), vel, channel); // C
digitalWrite(6,HIGH);
}
if (button20.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(25 + (octave*12), vel, channel); // C#
delay(d);
digitalWrite(6,HIGH);
}
if (button21.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(26 + (octave*12), vel, channel); // D
delay(d);
digitalWrite(6,HIGH);
}
if (button22.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(27 + (octave*12), vel, channel); // Eb
delay(d);
digitalWrite(6,HIGH);
}
if (button23.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(28 + (octave*12), vel, channel); // E
delay(d);
digitalWrite(6,HIGH);
}
if (button24.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(29 + (octave*12), vel, channel); // F
delay(d);
digitalWrite(6,HIGH);
}
if (button25.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(30 + (octave*12), vel, channel); // F#
delay(d);
digitalWrite(6,HIGH);
}
if (button26.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(31 + (octave*12), vel, channel); // G
delay(d);
digitalWrite(6,HIGH);
}
if (button27.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(32 + (octave*12), vel, channel); // G#
delay(d);
digitalWrite(6,HIGH);
}
if (button28.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(33 + (octave*12), vel, channel); // A
delay(d);
digitalWrite(6,HIGH);
}
if (button29.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(34 + (octave*12), vel, channel); // Bb
delay(d);
digitalWrite(6,HIGH);
}
if (button30.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(35 + (octave*12), vel, channel); // B
delay(d);
digitalWrite(6,HIGH);
}
if (button31.fallingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(36 + (octave*12), vel, channel); // C
delay(d);
digitalWrite(6,HIGH);
}
//----------------------READ BUTTON PINS FOR SUSTAIN AND MODULATION--------------
// Check sus button for "falling" edge.
// Send a MIDI CC message when button is pressed
// Update the Joystick buttons only upon changes.
// falling = high (not pressed - voltage from pullup resistor)
// to low (pressed - button connects pin to ground)
if (button35.fallingEdge()) {
usbMIDI.sendControlChange(64, 127, channel); // (type=64=sus, value=127=on, MIDI channel)
}
// Check mod button for "falling" edge.
// Send a MIDI CC message when the button is pressed
// Update the Joystick buttons only upon changes.
// falling = high (not pressed - voltage from pullup resistor)
// to low (pressed - button connects pin to ground)
if (button34.fallingEdge()) {
usbMIDI.sendControlChange(1, 64, channel); // (type=1=mod, value=64, MIDI channel)
}
// Check mod button for "rising" edge.
// Send a MIDI CC message when button is not pressed
// Update the Joystick buttons only upon changes.
// falling = high (not pressed - voltage from pullup resistor)
// to low (pressed - button connects pin to ground)
if (button34.risingEdge()) {
usbMIDI.sendControlChange(1, 0, channel); // (type=1=mod, value=0=off, MIDI channel)
}
// Check sus button for "rising" edge.
// Send a MIDI CC message when button is not pressed
// Update the Joystick buttons only upon changes.
// rising = low (pressed - button connects pin to ground)
// to high (not pressed - voltage from pullup resistor)
if (button35.risingEdge()) {
usbMIDI.sendControlChange(64, 0, channel); // (type=64=sus, value=0=off, MIDI channel)
}
//---------------READ BUTTON PINS FOR NOTE OFF-----------------------------------------
// Check each button for "rising" edge
// Send a MIDI Note Off message when each button releases
// For many types of projects, you only care when the button
// is pressed and the release isn't needed.
// rising = low (pressed - button connects pin to ground)
// to high (not pressed - voltage from pullup resistor)
if (button7.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(12 + (octave*12), 0, channel); // C
delay(d);
digitalWrite(6,HIGH);
}
if (button8.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(13 + (octave*12), 0, channel); // C#
delay(d);
digitalWrite(6,HIGH);
}
if (button9.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(14 + (octave*12), 0, channel); // D
delay(d);
digitalWrite(6,HIGH);
}
if (button10.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(15 + (octave*12), 0, channel); // Eb
delay(d);
digitalWrite(6,HIGH);
}
if (button11.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(16 + (octave*12), 0, channel); // E
delay(d);
digitalWrite(6,HIGH);
}
if (button12.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(17 + (octave*12), 0, channel); // F
delay(d);
digitalWrite(6,HIGH);
}
if (button13.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(18 + (octave*12), 0, channel); // F#
delay(d);
digitalWrite(6,HIGH);
}
if (button14.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(19 + (octave*12), 0, channel); // G
delay(d);
digitalWrite(6,HIGH);
}
if (button15.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(20 + (octave*12), 0, channel); // G#
delay(d);
digitalWrite(6,HIGH);
}
if (button16.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(21 + (octave*12), 0, channel); // A
delay(d);
digitalWrite(6,HIGH);
}
if (button17.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(22 + (octave*12), 0, channel); // Bb
delay(d);
digitalWrite(6,HIGH);
}
if (button18.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(23 + (octave*12), 0, channel); // B
delay(d);
digitalWrite(6,HIGH);
}
if (button19.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(24 + (octave*12), 0, channel); // C
delay(d);
digitalWrite(6,HIGH);
}
if (button20.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(25 + (octave*12), 0, channel); // C#
delay(d);
digitalWrite(6,HIGH);
}
if (button21.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(26 + (octave*12), 0, channel); // D
delay(d);
digitalWrite(6,HIGH);
}
if (button22.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(27 + (octave*12), 0, channel); // Eb
delay(d);
digitalWrite(6,HIGH);
}
if (button23.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(28 + (octave*12), 0, channel); // E
delay(d);
digitalWrite(6,HIGH);
}
if (button24.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(29 + (octave*12), 0, channel); // F
delay(d);
digitalWrite(6,HIGH);
}
if (button25.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(30 + (octave*12), 0, channel); // F#
delay(d);
digitalWrite(6,HIGH);
}
if (button26.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(31 + (octave*12), 0, channel); // G
digitalWrite(6,HIGH);
}
if (button27.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(32 + (octave*12), 0, channel); // G#
delay(d);
digitalWrite(6,HIGH);
}
if (button28.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(33 + (octave*12), 0, channel); // A
delay(d);
digitalWrite(6,HIGH);
}
if (button29.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(34 + (octave*12), 0, channel); // Bb
delay(d);
digitalWrite(6,HIGH);
}
if (button30.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(35 + (octave*12), 0, channel); // B
delay(d);
digitalWrite(6,HIGH);
}
if (button31.risingEdge()) {
digitalWrite(6,LOW);
usbMIDI.sendNoteOn(36 + (octave*12), 0, channel); // C
delay(d);
digitalWrite(6,HIGH);
}
// MIDI Controllers should discard incoming MIDI messages.
// http://forum.pjrc.com/threads/24179-Teensy-3-Ableton-Analog-CC-causes-midi-crash
while (usbMIDI.read()) { // ignore incoming messages
}
}