VincentYeh
Published

Arduino MIDI Virtual DJ Controller

Make your own DJ controller!!!

IntermediateShowcase (no instructions)4,093
Arduino MIDI Virtual DJ Controller

Things used in this project

Hardware components

Resistor 10k ohm
Resistor 10k ohm
×15
Resistor 100k ohm
Resistor 100k ohm
×14
Ceramic Disc Capacitor, 0.1 µF
Ceramic Disc Capacitor, 0.1 µF
×16
Ceramic Disc Capacitor, 20 pF
×4
12 MHz Crystal
12 MHz Crystal
×1
16 MHz Crystal
16 MHz Crystal
×1
Rotary Potentiometer, 10 kohm
Rotary Potentiometer, 10 kohm
×2
Potentiometer, Slide
Potentiometer, Slide
×1
Tactile Switch, Top Actuated
Tactile Switch, Top Actuated
×15
USB Connector, USB Type B
USB Connector, USB Type B
×1
CD4051
×2
CH340g
×1
ATmega328
Microchip ATmega328
×1

Software apps and online services

VIRTUAL DJ pro
Hairless MIDISerial Bridge
loopMIDI
MIDI-OX

Story

Read more

Schematics

Circuit

Code

VDJ_Controller

Arduino
#define DEBUG false     
//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.

#define VALUE_MIN_RANGE 1
#define DEBOUNCE_MS 100

#define MIDI_MSG_NOTE_OFF 128 //or 0x80
#define MIDI_MSG_NOTE_ON 144 //or 0x90
#define MIDI_MSG_CTRL_CHANGE 176 //or 0xB0

byte previous_values[2][8];
byte previous_M_slide_value;
unsigned long btn_timer[2][8];
//unsigned long timer = 0;

void setup() {
  
  Serial.begin(115200);
  previous_M_slide_value=-1;
  for (int i = 0; i < 8; i++) {
    previous_values[0][i] = -1;
    previous_values[1][i] = -1;
    btn_timer[0][i]=0;
    btn_timer[1][i]=0;
  }

  pinMode(7, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(5, OUTPUT);

}

void loop() {

  for (int i = 0; i < 8; i++) {
    select(i);
    int curr_value[2];
    curr_value[0] = analogRead(A0);
    curr_value[1] = analogRead(A1);
    for (byte side = 0; side < 2; side++) {
      if (i != 3 && previous_values[side][i] != (ATD(curr_value[side]) == 1 ? 0 : 127) && millis()>=btn_timer[side][i]) {
//        When button is pressed.
        byte val = ATD(curr_value[side]) == 1 ? 0 : 127;
        previous_values[side][i] = val;
        if (val == 127) {
          if (!DEBUG)sendNoteOn(0x39+side+i*2, val, 1);
        } else if (val == 0) {
          if (!DEBUG)sendNoteOff(0x39+side+i*2, val, 1);
          btn_timer[side][i]=millis()+DEBOUNCE_MS;
        }
      } else if (i == 3) {
        int analog_val = map(curr_value[side], 0, 1023, 0, 127);
        if (range(previous_values[side][i], analog_val, VALUE_MIN_RANGE) != previous_values[side][i]) {
//        When slider value is changed.
          previous_values[side][i] = analog_val;
          if (!DEBUG)sendCtrlChange(0x39+side+i*2, previous_values[side][i], 1);
        }
      }
    }
    if(DEBUG)for(byte si=0;si<2;si++){
      Serial.print(String(previous_values[si][i] + i * 150+si*150*8));
      Serial.print(",");
    }
  }
  if(DEBUG)Serial.println();
  
  int analog_val = map(analogRead(A2), 0, 1023, 0, 127);
  if (range(previous_M_slide_value, analog_val, VALUE_MIN_RANGE) != previous_M_slide_value) {
    previous_M_slide_value = analog_val;
    if (!DEBUG)sendCtrlChange(0x57, previous_M_slide_value, 1);
  }
  
  
}


void printChart(int val) {
  Serial.print(val);
  Serial.print(",");
}
int range(int previous, int current, int d) {
//  This method compare previous value and current value.
//  If current value only increase or decrease "d",this method will return previous value.
//  If current value increase or decrease "d" + >0 value ,this method will return current value.

//example:
//  previous=5;current=4;d=1
//  return 5

//  previous=5;current=3;d=1
//  return 3

  if (current == 127)return 127;
  else if (current == 0)return 0;
  if (current > previous && current - d == previous)return previous;
  else if (current < previous && previous - d == current)return previous;
  else if (current == previous)return previous;
  return current;
}

bool ATD(int analog_val) {
//  Analog to digital
//  analog_val:0~1023
//  return 0 or 1.
  if (((float)analog_val * 0.0048828125) > 2.94) {
    return 1;
  } else if (((float)analog_val * 0.0048828125) <= 1.47) {
    return 0;
  }
}

void select(int select) {
//  CD4051 select
//  C (MSB) : S2  13  D7
//  B       : S1  12  D6
//  A (LSB) : S0  11  D5

  for (int inputPin = 0; inputPin < 3; inputPin++)
  {
    int pinState = bitRead(select, inputPin);
    digitalWrite(inputPin + 5, pinState);
  }
}

//MIDI------------------------------------------
void sendNoteOn(byte note,byte velocity,byte channel){
  sendChannelVoiceMsg(MIDI_MSG_NOTE_ON|(channel-1),note,velocity);
  
  }

void sendNoteOff(byte note,byte velocity,byte channel){
  sendChannelVoiceMsg(MIDI_MSG_NOTE_OFF|(channel-1),note,velocity);
  }
  
void sendCtrlChange(byte cc,byte value,int channel) {
  sendChannelVoiceMsg(MIDI_MSG_CTRL_CHANGE|(channel-1),cc,value);
}

void sendChannelVoiceMsg(byte command, byte note, byte velocity) {
  //send MIDI Channel Voice Message
  Serial.write(command);
  Serial.write(note);
  Serial.write(velocity);
}

devices

XML
The file in document\VirtualDJ\Devices.
<device name="arduino VDJ Controller" author="VincentYeh" description="arduino VDJ Controller" version="800" decks="1" type="MIDI" identifier="#tevmidi0#" motor="no">

<button note="0x39" name="BUTTON-L0" channel="0" />
<button note="0x3A" name="BUTTON-R0" channel="0" />

<button note="0x3B" name="BUTTON-L1" channel="0" />
<button note="0x3C" name="BUTTON-R1" channel="0" />

<button note="0x3D" name="BUTTON-L2" channel="0" />
<button note="0x3E" name="BUTTON-R2" channel="0" />

<slider cc="0x3F" name="SLIDER-L0" channel="0"/>
<slider cc="0x40" name="SLIDER-R0" channel="0"/>

<button note="0x41" name="BUTTON-L3" channel="0" />
<button note="0x42" name="BUTTON-R3" channel="0" />

<button note="0x43" name="BUTTON-L4" channel="0" />
<button note="0x44" name="BUTTON-R4" channel="0" />

<button note="0x45" name="BUTTON-L5" channel="0" />
<button note="0x46" name="BUTTON-R5" channel="0" />

<button note="0x47" name="BUTTON-L6" channel="0" />
<button note="0x48" name="BUTTON-R6" channel="0" />


<slider cc="0x57" name="SLIDER-M0" channel="0"/>

</device>

arduino VDJ Controller - arduino VDJ Controller

XML
The file in document\VirtualDJ\Mappers.
<?xml version="1.0" encoding="UTF-8"?>
<mapper device="arduino VDJ Controller" version="802" date="2019-04-06">
	<map value="BUTTON-L0" action="deck left play_button" />
	<map value="BUTTON-L1" action="deck left stop_button" />
	<map value="BUTTON-L2" action="deck left sync" />
	<map value="BUTTON-L3" action="deck left pitch_reset" />
	<map value="BUTTON-L4" action="deck left loop_half" />
	<map value="BUTTON-L5" action="deck left loop" />
	<map value="BUTTON-L6" action="deck left loop_double" />
	<map value="BUTTON-R0" action="deck right play_button" />
	<map value="BUTTON-R1" action="deck right stop_button" />
	<map value="BUTTON-R2" action="deck right sync" />
	<map value="BUTTON-R3" action="deck right pitch_reset" />
	<map value="BUTTON-R4" action="deck right loop_half" />
	<map value="BUTTON-R5" action="deck right loop" />
	<map value="BUTTON-R6" action="deck right loop_double" />
	<map value="SLIDER-M0" action="crossfader" />
	<map value="SLIDER-L0" action="deck left filter" />
	<map value="SLIDER-R0" action="deck right filter" />
	
	
	<map value="PAD-L0" action="deck left hot_cue 1" />
	<map value="PAD-L1" action="deck left hot_cue 2" />
	<map value="PAD-L2" action="deck left hot_cue 3" />
	<map value="PAD-R0" action="deck right hot_cue 1" />
	<map value="PAD-R1" action="deck right hot_cue 2" />
	<map value="PAD-R2" action="deck right hot_cue 3" />
</mapper>

Credits

VincentYeh
0 projects • 0 followers
Contact

Comments

Please log in or sign up to comment.