/* bespoke code example
By Leif Oddson
https://forum.pjrc.com/threads/56935-midi-controller
*/
//************LIBRARIES USED**************
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
// include the Bounce library for 'de-bouncing' switches -- removing electrical chatter as contacts settle
#include <Bounce.h>
//usbMIDI.h library is added automatically when code is compiled as a MIDI device
// ******CONSTANT VALUES********
// customize code behaviour here!
const int channel = 1; // MIDI channel
const int A_PINS = 6; // number of Analog PINS
[COLOR="#FF0000"]const int D_PINS = 12; // number of Digital PINS[/COLOR]
// define the pins you want to use and the CC ID numbers on which to send them..
const int ANALOG_PINS[A_PINS] = {A0,A1,A2,A3,A4,A5};
const int CCID[A_PINS] = {21,22,23,24,25,26};
[COLOR="#FF0000"]
// define the pins and notes for digital events
const int DIGITAL_PINS[D_PINS] = {0,1,2,3,4,5,6,7,8,9,10,11};
const int CCchainID[D_PINS] = {60,60,60,60,60,60,70,70,70,70,70,70};
const int CCchainVal[D_PINS] = {0,25,50,75,100,127,0,25,50,75,100,127};[/COLOR]
const int BOUNCE_TIME = 7; // 5 ms is usually sufficient
const boolean toggled = true;
//******VARIABLES***********
// a data array and a lagged copy to tell when MIDI changes are required
byte data[A_PINS];
byte dataLag[A_PINS]; // when lag and new are not the same then update MIDI CC value
//************INITIALIZE LIBRARY OBJECTS**************
// not sure if there is a better way... some way run a setup loop on global array??
// use comment tags to comment out unused portions of array definitions
// initialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead analog[]{
{ANALOG_PINS[0],true},
{ANALOG_PINS[1],true},
{ANALOG_PINS[2],true},
{ANALOG_PINS[3],true},
{ANALOG_PINS[4],true},
{ANALOG_PINS[5],true}/*,
{ANALOG_PINS[6],true},
{ANALOG_PINS[7],true},*/
};
// initialize the bounce objects
Bounce digital[] = {
Bounce(DIGITAL_PINS[0],BOUNCE_TIME),
Bounce(DIGITAL_PINS[1], BOUNCE_TIME),
Bounce(DIGITAL_PINS[2], BOUNCE_TIME),
Bounce(DIGITAL_PINS[3], BOUNCE_TIME),
Bounce(DIGITAL_PINS[4], BOUNCE_TIME),
Bounce(DIGITAL_PINS[5], BOUNCE_TIME),
Bounce(DIGITAL_PINS[6], BOUNCE_TIME),
Bounce(DIGITAL_PINS[7], BOUNCE_TIME),
Bounce(DIGITAL_PINS[8], BOUNCE_TIME),
Bounce(DIGITAL_PINS[9], BOUNCE_TIME),
Bounce(DIGITAL_PINS[10], BOUNCE_TIME),
Bounce(DIGITAL_PINS[11], BOUNCE_TIME)
};
//************SETUP**************
void setup() {
// loop to configure input pins and internal pullup resisters for digital section
for (int i=0;i<D_PINS;i++){
pinMode(DIGITAL_PINS[i], INPUT_PULLUP);
}
}
//************LOOP**************
void loop() {
// getAnalogData(); // commented out to avoid garbage MIDI until you are ready with the analog voltage dividers
getDigitalData();
while (usbMIDI.read()) {
// controllers must call .read() to keep the queue clear even if they are not responding to MIDI
}
}
//************ANALOG SECTION************** uncomment call from loop to make active when you are ready!
void getAnalogData(){
for (int i=0;i<A_PINS;i++){
// update the ResponsiveAnalogRead object every loop
analog[i].update();
// if the repsonsive value has change, print out 'changed'
if(analog[i].hasChanged()) {
data[i] = analog[i].getValue()>>3;
if (data[i] != dataLag[i]){
dataLag[i] = data[i];
usbMIDI.sendControlChange(CCID[i], data[i], channel);
}
}
}
}
//************DIGITAL SECTION**************
void getDigitalData(){
for (int i=0;i<D_PINS;i++){
digital[i].update();
if (digital[i].fallingEdge()) {
usbMIDI.sendControlChange(CCchainID[i],CCchainVal[i],channel);
}
}
}
#include <MIDI_Controller.h>
AnalogCC faders[] = {
{A0, MIDI_CC::Channel_Volume, 1}, // Create a new instance of class 'AnalogCC' on pin A0, controller number 0x07 (channel volume), on MIDI channel 1.
{A1, MIDI_CC::Channel_Volume, 2},
{A2, MIDI_CC::Channel_Volume, 3},
{A3, MIDI_CC::Channel_Volume, 4},
{A4, MIDI_CC::Channel_Volume, 5},
{A5, MIDI_CC::Channel_Volume, 6},
{A6, MIDI_CC::Channel_Volume, 7},
{A7, MIDI_CC::Channel_Volume, 8},
// ...
};
DigitalCC buttons[] = {
{2, 0x20, 1}, // Create a new instance of class 'DigitalCC' on pin 2, controller number 0x20, on MIDI channel 1.
{3, 0x21, 1},
{4, 0x22, 1},
// ...
}
void setup() { }
void loop() { // Refresh all inputs
MIDI_Controller.refresh();
}
#include <MIDI_Controller.h>
AnalogCC potentiometers[] = {
{A0, MIDI_CC::Channel_Volume, 1}, // Create a new instance of class 'AnalogCC' on pin A0, controller number 0x07 (channel volume), on MIDI channel 1.
{A1, MIDI_CC::Channel_Volume, 2},
{A2, MIDI_CC::Channel_Volume, 3},
{A3, MIDI_CC::Channel_Volume, 4},
{A4, MIDI_CC::Channel_Volume, 5},
{A5, MIDI_CC::Channel_Volume, 6},
};
DigitalCC buttons[] = {
{2, 0x20, 1}, // Create a new instance of class 'DigitalCC' on pin 2, controller number 0x20, on MIDI channel 1.
{3, 0x21, 1},
{4, 0x22, 1},
{5, 0x23, 1},
{6, 0x24, 1},
{7, 0x25, 1},
};
void setup() { }
void loop() { // Refresh all inputs
MIDI_Controller.refresh();
}
You have to configure it... and you're going to have to start trying to read the code.Well it loads but, same as others, it only registers the first button on the chain selector. Only difference is before when I hit the second button while holding down the first it would change the first, now it does nothing. The first button says cc#60 When I use the buttons sketch it says note C3 #48 to F3 #53.
//************LOOP**************
void loop() {
[COLOR="#0000FF"] // [/COLOR]getAnalogData(); // commented out to avoid garbage MIDI until you are ready with the analog voltage dividers
getDigitalData();
while (usbMIDI.read()) {
// controllers must call .read() to keep the queue clear even if they are not responding to MIDI
}
}
/* Buttons to USB MIDI Example
You must select MIDI from the "Tools > USB Type" menu
To view the raw MIDI data on Linux: aseqdump -p "Teensy MIDI"
This example code is in the public domain.
*/
#include <Bounce.h>
// the MIDI channel number to send messages
const int channel = 1;
// 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, 5);
Bounce button1 = Bounce(1, 5); // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5); // which is appropriate for good
Bounce button3 = Bounce(3, 5); // quality mechanical pushbuttons
Bounce button4 = Bounce(4, 5);
Bounce button5 = Bounce(5, 5); // if a button is too "sensitive"
Bounce button6 = Bounce(6, 5); // to rapid touch, you can
Bounce button7 = Bounce(7, 5); // increase this time.
Bounce button8 = Bounce(8, 5);
Bounce button9 = Bounce(9, 5);
Bounce button10 = Bounce(10, 5);
Bounce button11 = Bounce(11, 5);
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, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP); // 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); // Teensy 2.0 LED, may need 1k resistor pullup
}
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();
// Check each button 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 (button0.fallingEdge()) {
usbMIDI.sendNoteOn(60, 99, channel); // 60 = C4
}
if (button1.fallingEdge()) {
usbMIDI.sendNoteOn(61, 99, channel); // 61 = C#4
}
if (button2.fallingEdge()) {
usbMIDI.sendNoteOn(62, 99, channel); // 62 = D4
}
if (button3.fallingEdge()) {
usbMIDI.sendNoteOn(63, 99, channel); // 63 = D#4
}
if (button4.fallingEdge()) {
usbMIDI.sendNoteOn(64, 99, channel); // 64 = E4
}
if (button5.fallingEdge()) {
usbMIDI.sendNoteOn(65, 99, channel); // 65 = F4
}
if (button6.fallingEdge()) {
usbMIDI.sendNoteOn(66, 99, channel); // 66 = F#4
}
if (button7.fallingEdge()) {
usbMIDI.sendNoteOn(67, 99, channel); // 67 = G4
}
if (button8.fallingEdge()) {
usbMIDI.sendNoteOn(68, 99, channel); // 68 = G#4
}
if (button9.fallingEdge()) {
usbMIDI.sendNoteOn(69, 99, channel); // 69 = A5
}
if (button10.fallingEdge()) {
usbMIDI.sendNoteOn(70, 99, channel); // 70 = A#5
}
if (button11.fallingEdge()) {
usbMIDI.sendNoteOn(71, 99, channel); // 71 = B5
}
// 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 (button0.risingEdge()) {
usbMIDI.sendNoteOff(60, 0, channel); // 60 = C4
}
if (button1.risingEdge()) {
usbMIDI.sendNoteOff(61, 0, channel); // 61 = C#4
}
if (button2.risingEdge()) {
usbMIDI.sendNoteOff(62, 0, channel); // 62 = D4
}
if (button3.risingEdge()) {
usbMIDI.sendNoteOff(63, 0, channel); // 63 = D#4
}
if (button4.risingEdge()) {
usbMIDI.sendNoteOff(64, 0, channel); // 64 = E4
}
if (button5.risingEdge()) {
usbMIDI.sendNoteOff(65, 0, channel); // 65 = F4
}
if (button6.risingEdge()) {
usbMIDI.sendNoteOff(66, 0, channel); // 66 = F#4
}
if (button7.risingEdge()) {
usbMIDI.sendNoteOff(67, 0, channel); // 67 = G4
}
if (button8.risingEdge()) {
usbMIDI.sendNoteOff(68, 0, channel); // 68 = G#4
}
if (button9.risingEdge()) {
usbMIDI.sendNoteOff(69, 0, channel); // 69 = A5
}
if (button10.risingEdge()) {
usbMIDI.sendNoteOff(70, 0, channel); // 70 = A#5
}
if (button11.risingEdge()) {
usbMIDI.sendNoteOff(71, 0, channel); // 71 = B5
}
// 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
}
}