midi_controller.ino (2883B)
1 #include <Bounce2.h> 2 3 #define MIDI_CHANNEL 2 4 #define MIDI_CHANGE_THRESHOLD 2 5 6 #define NUM_POTS 8 7 static const uint8_t potPins[NUM_POTS] = {A0, A1, A2, A3, A6, A7, A8, A9}; 8 static const uint8_t potCC[NUM_POTS] = {1, 2, 3, 4, 5, 6, 7, 8}; 9 int potVal[NUM_POTS] = {0, 0, 0, 0, 0, 0, 0, 0}; 10 int oldVal[NUM_POTS] = {0, 0, 0, 0, 0, 0, 0, 0}; 11 12 #define NUM_BUTTONS 4 13 #define MOMENTARY 0 14 #define LATCH 1 15 #define TRIGGER 2 16 static const uint8_t btnPins[NUM_BUTTONS] = {6, 7, 8, 9}; 17 static const uint8_t btnCC[NUM_BUTTONS] = {11, 12, 13, 14}; 18 uint8_t btnVal[NUM_BUTTONS] = {HIGH, HIGH, HIGH, HIGH}; 19 uint8_t btnOldVal[NUM_BUTTONS] = {HIGH, HIGH, HIGH, HIGH}; 20 uint8_t btnMode[NUM_BUTTONS] = {MOMENTARY, TRIGGER, TRIGGER, LATCH}; 21 Bounce *buttons = new Bounce[NUM_BUTTONS]; 22 23 unsigned long previousMillis = 0; 24 25 // Reads all pots and sends midi CC message if it has been a change 26 // greater than threshold (so we avoid flickering) 27 void readPots() { 28 uint8_t i; 29 30 for (i = 0; i < NUM_POTS; i++) { 31 potVal[i] = analogRead(potPins[i]); 32 potVal[i] = map(potVal[i], 0, 4095, 0, 127); 33 if (abs(potVal[i] - oldVal[i]) > MIDI_CHANGE_THRESHOLD) { 34 usbMIDI.sendControlChange(potCC[i], potVal[i], MIDI_CHANNEL); 35 oldVal[i] = potVal[i]; 36 } 37 } 38 } 39 40 41 void setup() { 42 analogReadResolution(12); 43 analogReadAveraging(16); 44 for (uint8_t i = 0; i < NUM_BUTTONS; ++i) { 45 buttons[i].attach( btnPins[i] , INPUT_PULLUP ); 46 buttons[i].interval(10); 47 } 48 } 49 50 void loop() { 51 unsigned long currentMillis = millis(); 52 53 if(currentMillis - previousMillis > 5) { // moaaarrr stability in readings 54 previousMillis = currentMillis; 55 readPots(); 56 } 57 58 for (uint8_t i = 0; i < NUM_BUTTONS; i++) { 59 buttons[i].update(); 60 if (buttons[i].fell()) { 61 if (btnOldVal[i] == HIGH) { 62 // this is send max for momentary and latch 63 usbMIDI.sendControlChange(btnCC[i], 127, MIDI_CHANNEL); 64 btnOldVal[i] = LOW; 65 } else { 66 // if trigger mode send max again 67 if (btnMode[i] == TRIGGER) { 68 // it seems vcv rack needs notes on/off for its trigger module. 69 usbMIDI.sendNoteOn(btnCC[i], 127, MIDI_CHANNEL); 70 usbMIDI.sendNoteOff(btnCC[i], 127, MIDI_CHANNEL); 71 // usbMIDI.sendControlChange(btnCC[i], 127, MIDI_CHANNEL); 72 } else { // if we're here is latch mode, so we turn it off 73 usbMIDI.sendControlChange(btnCC[i], 0, MIDI_CHANNEL); 74 btnOldVal[i] = HIGH; 75 } 76 } 77 } 78 if (buttons[i].rose()) { 79 if (btnOldVal[i] == LOW && btnMode[i] == MOMENTARY) { 80 // button released logic goes here. 81 // we only use this for momentary buttons. 82 usbMIDI.sendControlChange(btnCC[i], 0, MIDI_CHANNEL); 83 btnOldVal[i] = HIGH; 84 } 85 } 86 } 87 }