Arduino MIDI Virtual DJ Controller
Make your own DJ controller!!!
Components and supplies
1
CH340g
16
Ceramic Disc Capacitor, 0.1 µF
15
Resistor 10k ohm
1
USB Connector, USB Type B
15
Tactile Switch, Top Actuated
14
Resistor 100k ohm
1
16 MHz Crystal
2
Rotary Potentiometer, 10 kohm
1
ATmega328
1
12 MHz Crystal
2
CD4051
4
Ceramic Disc Capacitor, 20 pF
1
Potentiometer, Slide
Apps and platforms
1
VIRTUAL DJ pro
1
Hairless MIDISerial Bridge
1
MIDI-OX
1
loopMIDI
Project description
Code
VDJ_Controller
arduino
1#define DEBUG false 2//You can use Arduino Serial Plotter for debug by changing DEBUG to true,but it will make your MIDI board unable to send MIDI Message. 3 4#define VALUE_MIN_RANGE 1 5#define DEBOUNCE_MS 100 6 7#define MIDI_MSG_NOTE_OFF 128 //or 0x80 8#define MIDI_MSG_NOTE_ON 144 //or 0x90 9#define MIDI_MSG_CTRL_CHANGE 176 //or 0xB0 10 11byte previous_values[2][8]; 12byte previous_M_slide_value; 13unsigned long btn_timer[2][8]; 14//unsigned long timer = 0; 15 16void setup() { 17 18 Serial.begin(115200); 19 previous_M_slide_value=-1; 20 for (int i = 0; i < 8; i++) { 21 previous_values[0][i] = -1; 22 previous_values[1][i] = -1; 23 btn_timer[0][i]=0; 24 btn_timer[1][i]=0; 25 } 26 27 pinMode(7, OUTPUT); 28 pinMode(6, OUTPUT); 29 pinMode(5, OUTPUT); 30 31} 32 33void loop() { 34 35 for (int i = 0; i < 8; i++) { 36 select(i); 37 int curr_value[2]; 38 curr_value[0] = analogRead(A0); 39 curr_value[1] = analogRead(A1); 40 for (byte side = 0; side < 2; side++) { 41 if (i != 3 && previous_values[side][i] != (ATD(curr_value[side]) == 1 ? 0 : 127) && millis()>=btn_timer[side][i]) { 42// When button is pressed. 43 byte val = ATD(curr_value[side]) == 1 ? 0 : 127; 44 previous_values[side][i] = val; 45 if (val == 127) { 46 if (!DEBUG)sendNoteOn(0x39+side+i*2, val, 1); 47 } else if (val == 0) { 48 if (!DEBUG)sendNoteOff(0x39+side+i*2, val, 1); 49 btn_timer[side][i]=millis()+DEBOUNCE_MS; 50 } 51 } else if (i == 3) { 52 int analog_val = map(curr_value[side], 0, 1023, 0, 127); 53 if (range(previous_values[side][i], analog_val, VALUE_MIN_RANGE) != previous_values[side][i]) { 54// When slider value is changed. 55 previous_values[side][i] = analog_val; 56 if (!DEBUG)sendCtrlChange(0x39+side+i*2, previous_values[side][i], 1); 57 } 58 } 59 } 60 if(DEBUG)for(byte si=0;si<2;si++){ 61 Serial.print(String(previous_values[si][i] + i * 150+si*150*8)); 62 Serial.print(","); 63 } 64 } 65 if(DEBUG)Serial.println(); 66 67 int analog_val = map(analogRead(A2), 0, 1023, 0, 127); 68 if (range(previous_M_slide_value, analog_val, VALUE_MIN_RANGE) != previous_M_slide_value) { 69 previous_M_slide_value = analog_val; 70 if (!DEBUG)sendCtrlChange(0x57, previous_M_slide_value, 1); 71 } 72 73 74} 75 76 77void printChart(int val) { 78 Serial.print(val); 79 Serial.print(","); 80} 81int range(int previous, int current, int d) { 82// This method compare previous value and current value. 83// If current value only increase or decrease "d",this method will return previous value. 84// If current value increase or decrease "d" + >0 value ,this method will return current value. 85 86//example: 87// previous=5;current=4;d=1 88// return 5 89 90// previous=5;current=3;d=1 91// return 3 92 93 if (current == 127)return 127; 94 else if (current == 0)return 0; 95 if (current > previous && current - d == previous)return previous; 96 else if (current < previous && previous - d == current)return previous; 97 else if (current == previous)return previous; 98 return current; 99} 100 101bool ATD(int analog_val) { 102// Analog to digital 103// analog_val:0~1023 104// return 0 or 1. 105 if (((float)analog_val * 0.0048828125) > 2.94) { 106 return 1; 107 } else if (((float)analog_val * 0.0048828125) <= 1.47) { 108 return 0; 109 } 110} 111 112void select(int select) { 113// CD4051 select 114// C (MSB) : S2 13 D7 115// B : S1 12 D6 116// A (LSB) : S0 11 D5 117 118 for (int inputPin = 0; inputPin < 3; inputPin++) 119 { 120 int pinState = bitRead(select, inputPin); 121 digitalWrite(inputPin + 5, pinState); 122 } 123} 124 125//MIDI------------------------------------------ 126void sendNoteOn(byte note,byte velocity,byte channel){ 127 sendChannelVoiceMsg(MIDI_MSG_NOTE_ON|(channel-1),note,velocity); 128 129 } 130 131void sendNoteOff(byte note,byte velocity,byte channel){ 132 sendChannelVoiceMsg(MIDI_MSG_NOTE_OFF|(channel-1),note,velocity); 133 } 134 135void sendCtrlChange(byte cc,byte value,int channel) { 136 sendChannelVoiceMsg(MIDI_MSG_CTRL_CHANGE|(channel-1),cc,value); 137} 138 139void sendChannelVoiceMsg(byte command, byte note, byte velocity) { 140 //send MIDI Channel Voice Message 141 Serial.write(command); 142 Serial.write(note); 143 Serial.write(velocity); 144}
devices
xml
The file in document\VirtualDJ\Devices.
1<device name="arduino VDJ Controller" author="VincentYeh" description="arduino VDJ Controller" version="800" decks="1" type="MIDI" identifier="#tevmidi0#" motor="no"> 2 3<button note="0x39" name="BUTTON-L0" channel="0" /> 4<button note="0x3A" name="BUTTON-R0" channel="0" /> 5 6<button note="0x3B" name="BUTTON-L1" channel="0" /> 7<button note="0x3C" name="BUTTON-R1" channel="0" /> 8 9<button note="0x3D" name="BUTTON-L2" channel="0" /> 10<button note="0x3E" name="BUTTON-R2" channel="0" /> 11 12<slider cc="0x3F" name="SLIDER-L0" channel="0"/> 13<slider cc="0x40" name="SLIDER-R0" channel="0"/> 14 15<button note="0x41" name="BUTTON-L3" channel="0" /> 16<button note="0x42" name="BUTTON-R3" channel="0" /> 17 18<button note="0x43" name="BUTTON-L4" channel="0" /> 19<button note="0x44" name="BUTTON-R4" channel="0" /> 20 21<button note="0x45" name="BUTTON-L5" channel="0" /> 22<button note="0x46" name="BUTTON-R5" channel="0" /> 23 24<button note="0x47" name="BUTTON-L6" channel="0" /> 25<button note="0x48" name="BUTTON-R6" channel="0" /> 26 27 28<slider cc="0x57" name="SLIDER-M0" channel="0"/> 29 30</device>
arduino VDJ Controller - arduino VDJ Controller
xml
The file in document\VirtualDJ\Mappers.
1<?xml version="1.0" encoding="UTF-8"?> 2<mapper device="arduino 3 VDJ Controller" version="802" date="2019-04-06"> 4 <map value="BUTTON-L0" 5 action="deck left play_button" /> 6 <map value="BUTTON-L1" action="deck 7 left stop_button" /> 8 <map value="BUTTON-L2" action="deck left sync" /> 9 <map 10 value="BUTTON-L3" action="deck left pitch_reset" /> 11 <map value="BUTTON-L4" 12 action="deck left loop_half" /> 13 <map value="BUTTON-L5" action="deck left 14 loop" /> 15 <map value="BUTTON-L6" action="deck left loop_double" /> 16 <map 17 value="BUTTON-R0" action="deck right play_button" /> 18 <map value="BUTTON-R1" 19 action="deck right stop_button" /> 20 <map value="BUTTON-R2" action="deck 21 right sync" /> 22 <map value="BUTTON-R3" action="deck right pitch_reset" 23 /> 24 <map value="BUTTON-R4" action="deck right loop_half" /> 25 <map value="BUTTON-R5" 26 action="deck right loop" /> 27 <map value="BUTTON-R6" action="deck right 28 loop_double" /> 29 <map value="SLIDER-M0" action="crossfader" /> 30 <map 31 value="SLIDER-L0" action="deck left filter" /> 32 <map value="SLIDER-R0" 33 action="deck right filter" /> 34 35 36 <map value="PAD-L0" action="deck 37 left hot_cue 1" /> 38 <map value="PAD-L1" action="deck left hot_cue 2" /> 39 <map 40 value="PAD-L2" action="deck left hot_cue 3" /> 41 <map value="PAD-R0" action="deck 42 right hot_cue 1" /> 43 <map value="PAD-R1" action="deck right hot_cue 2" 44 /> 45 <map value="PAD-R2" action="deck right hot_cue 3" /> 46</mapper> 47
VDJ_Controller
arduino
1#define DEBUG false 2//You can use Arduino Serial Plotter for debug by changing DEBUG to true,but it will make your MIDI board unable to send MIDI Message. 3 4#define VALUE_MIN_RANGE 1 5#define DEBOUNCE_MS 100 6 7#define MIDI_MSG_NOTE_OFF 128 //or 0x80 8#define MIDI_MSG_NOTE_ON 144 //or 0x90 9#define MIDI_MSG_CTRL_CHANGE 176 //or 0xB0 10 11byte previous_values[2][8]; 12byte previous_M_slide_value; 13unsigned long btn_timer[2][8]; 14//unsigned long timer = 0; 15 16void setup() { 17 18 Serial.begin(115200); 19 previous_M_slide_value=-1; 20 for (int i = 0; i < 8; i++) { 21 previous_values[0][i] = -1; 22 previous_values[1][i] = -1; 23 btn_timer[0][i]=0; 24 btn_timer[1][i]=0; 25 } 26 27 pinMode(7, OUTPUT); 28 pinMode(6, OUTPUT); 29 pinMode(5, OUTPUT); 30 31} 32 33void loop() { 34 35 for (int i = 0; i < 8; i++) { 36 select(i); 37 int curr_value[2]; 38 curr_value[0] = analogRead(A0); 39 curr_value[1] = analogRead(A1); 40 for (byte side = 0; side < 2; side++) { 41 if (i != 3 && previous_values[side][i] != (ATD(curr_value[side]) == 1 ? 0 : 127) && millis()>=btn_timer[side][i]) { 42// When button is pressed. 43 byte val = ATD(curr_value[side]) == 1 ? 0 : 127; 44 previous_values[side][i] = val; 45 if (val == 127) { 46 if (!DEBUG)sendNoteOn(0x39+side+i*2, val, 1); 47 } else if (val == 0) { 48 if (!DEBUG)sendNoteOff(0x39+side+i*2, val, 1); 49 btn_timer[side][i]=millis()+DEBOUNCE_MS; 50 } 51 } else if (i == 3) { 52 int analog_val = map(curr_value[side], 0, 1023, 0, 127); 53 if (range(previous_values[side][i], analog_val, VALUE_MIN_RANGE) != previous_values[side][i]) { 54// When slider value is changed. 55 previous_values[side][i] = analog_val; 56 if (!DEBUG)sendCtrlChange(0x39+side+i*2, previous_values[side][i], 1); 57 } 58 } 59 } 60 if(DEBUG)for(byte si=0;si<2;si++){ 61 Serial.print(String(previous_values[si][i] + i * 150+si*150*8)); 62 Serial.print(","); 63 } 64 } 65 if(DEBUG)Serial.println(); 66 67 int analog_val = map(analogRead(A2), 0, 1023, 0, 127); 68 if (range(previous_M_slide_value, analog_val, VALUE_MIN_RANGE) != previous_M_slide_value) { 69 previous_M_slide_value = analog_val; 70 if (!DEBUG)sendCtrlChange(0x57, previous_M_slide_value, 1); 71 } 72 73 74} 75 76 77void printChart(int val) { 78 Serial.print(val); 79 Serial.print(","); 80} 81int range(int previous, int current, int d) { 82// This method compare previous value and current value. 83// If current value only increase or decrease "d",this method will return previous value. 84// If current value increase or decrease "d" + >0 value ,this method will return current value. 85 86//example: 87// previous=5;current=4;d=1 88// return 5 89 90// previous=5;current=3;d=1 91// return 3 92 93 if (current == 127)return 127; 94 else if (current == 0)return 0; 95 if (current > previous && current - d == previous)return previous; 96 else if (current < previous && previous - d == current)return previous; 97 else if (current == previous)return previous; 98 return current; 99} 100 101bool ATD(int analog_val) { 102// Analog to digital 103// analog_val:0~1023 104// return 0 or 1. 105 if (((float)analog_val * 0.0048828125) > 2.94) { 106 return 1; 107 } else if (((float)analog_val * 0.0048828125) <= 1.47) { 108 return 0; 109 } 110} 111 112void select(int select) { 113// CD4051 select 114// C (MSB) : S2 13 D7 115// B : S1 12 D6 116// A (LSB) : S0 11 D5 117 118 for (int inputPin = 0; inputPin < 3; inputPin++) 119 { 120 int pinState = bitRead(select, inputPin); 121 digitalWrite(inputPin + 5, pinState); 122 } 123} 124 125//MIDI------------------------------------------ 126void sendNoteOn(byte note,byte velocity,byte channel){ 127 sendChannelVoiceMsg(MIDI_MSG_NOTE_ON|(channel-1),note,velocity); 128 129 } 130 131void sendNoteOff(byte note,byte velocity,byte channel){ 132 sendChannelVoiceMsg(MIDI_MSG_NOTE_OFF|(channel-1),note,velocity); 133 } 134 135void sendCtrlChange(byte cc,byte value,int channel) { 136 sendChannelVoiceMsg(MIDI_MSG_CTRL_CHANGE|(channel-1),cc,value); 137} 138 139void sendChannelVoiceMsg(byte command, byte note, byte velocity) { 140 //send MIDI Channel Voice Message 141 Serial.write(command); 142 Serial.write(note); 143 Serial.write(velocity); 144}
arduino VDJ Controller - arduino VDJ Controller
xml
The file in document\VirtualDJ\Mappers.
1<?xml version="1.0" encoding="UTF-8"?> 2<mapper device="arduino VDJ Controller" version="802" date="2019-04-06"> 3 <map value="BUTTON-L0" action="deck left play_button" /> 4 <map value="BUTTON-L1" action="deck left stop_button" /> 5 <map value="BUTTON-L2" action="deck left sync" /> 6 <map value="BUTTON-L3" action="deck left pitch_reset" /> 7 <map value="BUTTON-L4" action="deck left loop_half" /> 8 <map value="BUTTON-L5" action="deck left loop" /> 9 <map value="BUTTON-L6" action="deck left loop_double" /> 10 <map value="BUTTON-R0" action="deck right play_button" /> 11 <map value="BUTTON-R1" action="deck right stop_button" /> 12 <map value="BUTTON-R2" action="deck right sync" /> 13 <map value="BUTTON-R3" action="deck right pitch_reset" /> 14 <map value="BUTTON-R4" action="deck right loop_half" /> 15 <map value="BUTTON-R5" action="deck right loop" /> 16 <map value="BUTTON-R6" action="deck right loop_double" /> 17 <map value="SLIDER-M0" action="crossfader" /> 18 <map value="SLIDER-L0" action="deck left filter" /> 19 <map value="SLIDER-R0" action="deck right filter" /> 20 21 22 <map value="PAD-L0" action="deck left hot_cue 1" /> 23 <map value="PAD-L1" action="deck left hot_cue 2" /> 24 <map value="PAD-L2" action="deck left hot_cue 3" /> 25 <map value="PAD-R0" action="deck right hot_cue 1" /> 26 <map value="PAD-R1" action="deck right hot_cue 2" /> 27 <map value="PAD-R2" action="deck right hot_cue 3" /> 28</mapper> 29
Downloadable files
Circuit
Circuit
Circuit
Circuit
Comments
Only logged in users can leave comments