// *************************************************************** // * Behringer XR18 Arduino MIDI Remote Control * // * By Vern Graner * // *************************************************************** // * This code reads buttons and sends MIDI commands to the * // * Behringer XR18. LEDs are used to indicate button status * // * (down/up). Each button state can send a MIDI command * // *************************************************************** // * Rev Info: V1.0a (VLG) 01-22-2018 Sysex CC changes // * Rev Info: V2.0a (VLG) 01-22-2018 Hard coded OSC commands // * Rev Info: V3.0a (VLG) 01-22-2018 ASCII to HEX OSC commands // * Rev Info: V4.0a (VLG) 01-22-2018 ported to ESP32 // *************************************************************** // Include the MIDI stuff #include #include #include #include #include // Assign Arduino pins to tasks const int button1 = 26; // N.O. Pushbutton held HIGH with 100k const int button2 = 25; // const int button3 = 34; // const int button4 = 39; // const int led1 = 27; // LED with 330ohm to GND const int led2 = 33; // const int led3 = 32; // const int led4 = 15; // // Define program Variables int button1State = 0; // current state of the button int button2State = 0; // int button3State = 0; // int button4State = 0; // int lastButton1State = 0; // previous state of the button int lastButton2State = 0; // int lastButton3State = 0; // int lastButton4State = 0; // int commandLength=0; // byte bigMidiCommand[64]; // maximum command length in bytes byte midiHeader[]= { 0xF0,0x00,0x20,0x32,0x32 }; // XR18 OSC preamble byte midiFooter[]= { 0xF7 }; // XR18 OSC post-amble // Blink LED code // **************************************************************** const int ledPin = 13; // the number of the LED pin int ledState = HIGH; // ledState used to set the LED unsigned long previousMillis = 0; // will store last time LED was updated const long interval = 250; // interval at which to blink (milliseconds) // **************************************************************** HardwareSerial Serial1(2); MIDI_CREATE_INSTANCE(HardwareSerial,Serial1, midiOut); // create a MIDI object called midiOut void setup() { Serial1.begin(31250); // setup MIDI output midiOut.begin(); pinMode(button1, INPUT); // initialize the button pin as a input pinMode(button2, INPUT); // initialize the button pin as a input pinMode(button3, INPUT); // initialize the button pin as a input pinMode(button4, INPUT); // initialize the button pin as a input pinMode(led1, OUTPUT); // initialize the LED as an output pinMode(led2, OUTPUT); // initialize the LED as an output pinMode(led3, OUTPUT); // initialize the LED as an output pinMode(led4, OUTPUT); // initialize the LED as an output pinMode(ledPin, OUTPUT); // Blink LED setup } void loop() { // **************************************** // Button 1 Loop // **************************************** button1State = digitalRead(button1); // read the pushbutton input pin if (button1State != lastButton1State) { // compare the buttonState to its previous state (if not equal) if (button1State == HIGH) { // if the current state is HIGH then the button went from OFF to ON midiBuildCommand("/ch/16/mix/01/level -127"); midiOut.sendSysEx(commandLength, bigMidiCommand, true); // send SysEx digitalWrite(led1, LOW); } else { // if the current state is LOW then the button went from ON to OFF midiBuildCommand("/ch/16/mix/01/level 0"); midiOut.sendSysEx(commandLength, bigMidiCommand, true); // send SysEx digitalWrite(led1, HIGH); } delay(50); // Delay a little bit to avoid bouncing } lastButton1State = button1State; // save the current state as the last state, for next time through the loop // **************************************** // Button 2 Loop // **************************************** button2State = digitalRead(button2); // read the pushbutton input pin if (button2State != lastButton2State) { // compare the buttonState to its previous state if (button2State == HIGH) { // if the current state is HIGH then the button went from off to on: midiBuildCommand("/ch/16/mix/02/level -127"); midiOut.sendSysEx(commandLength, bigMidiCommand, true); // send SysEx digitalWrite(led2, LOW); } else { // if the current state is LOW then the button went from on to off: midiBuildCommand("/ch/16/mix/02/level 0"); midiOut.sendSysEx(commandLength, bigMidiCommand, true); // send SysEx digitalWrite(led2, HIGH); } delay(50); // Delay a little bit to avoid bouncing } lastButton2State = button2State; // save the current state as the last state, for next time through the loop // **************************************** // Button 3 Loop // **************************************** button3State = digitalRead(button3); // read the pushbutton input pin if (button3State != lastButton3State) { // compare the buttonState to its previous state if (button3State == HIGH) { // if the current state is HIGH then the button went from off to on: midiBuildCommand("/ch/16/mix/03/level -127"); midiOut.sendSysEx(commandLength, bigMidiCommand, true); // send SysEx digitalWrite(led3, LOW); } else { // if the current state is LOW then the button went from on to off: midiBuildCommand("/ch/16/mix/03/level 0"); midiOut.sendSysEx(commandLength, bigMidiCommand, true); // send SysEx digitalWrite(led3, HIGH); } delay(50); // Delay a little bit to avoid bouncing } lastButton3State = button3State; // save the current state as the last state, for next time through the loop // **************************************** // Button4 Loop // **************************************** button4State = digitalRead(button4); // read the pushbutton input pin if (button4State != lastButton4State) { // compare the buttonState to its previous state if (button4State == HIGH) { // if the current state is HIGH then the button went from off to on: midiOut.sendControlChange(15,127,2); // send a MIDI CC -- note,velocity,channel digitalWrite(led4, LOW); } else { // if the current state is LOW then the button went from on to off: midiOut.sendControlChange(15,0,2); // send a MIDI CC -- note,velocity,channel digitalWrite(led4, HIGH); } delay(50); // Delay a little bit to avoid bouncing } lastButton4State = button4State; // save the current state as the last state, for next time through the loop // **************************************** // non-blocking LED Blink routine // **************************************** if (button1State == LOW || button2State == LOW || button3State == LOW || button4State == LOW) { unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { // save the last time you blinked the LED previousMillis = currentMillis; // if the LED is off turn it on and vice-versa: if (ledState == HIGH) { ledState = LOW; } else { ledState = HIGH; } // set the LED with the ledState of the variable: digitalWrite(ledPin, ledState); } } else { digitalWrite(ledPin, LOW); previousMillis = 0; ledState = LOW; } // **********************************************************/ } //End of main loop // Subroutines aka functions // **********************************************************\ void midiBuildCommand(String body) { commandLength=0; for (int i=0 ; i