Simple MIDI USB Clock Converter for Analogue Sequencers
Title says it all really. I have several analogue sequencers that I designed and built years ago and I clock them with a Kenton Pro Solo Mk3. This unit can switch the MIDI THRU port to SYNC24 mode to work with Roland Drum Machines. This is a great solution but does tie up my Kenton which uses with my Editor and needs MIDI THRU for 2 way comms.
Arduino and the Pro Micro
I realised it was a simple job to reprogram on of my Pro Micros to convert MIDI Clock and Stop/Start messages. I've used it for a few weeks and its a worker so I thought I build proper unit:
- Pro Micro
- 24 Pin DIL Socket
- 1 x PCB Mounting 1/4 Stereo Jack Socket (my sequencers are all 1/4)
- 1 x 10K pot (I used a 47K pot)
Like my SYNC24 breakout box this will be mounted on the back of an existing 19" rack panel.
The code is at the bottom of the post - you will need to install the MIDIUSB.h library
Analog pulses are output on the clock jack connected to Pin 2. When stop is pressed on the sequencer the Stop command $FC is picked up and a RESET pulse is sent out on Pin 5. This is connected to the RESET IN on my sequencer. This ensures the analogue sequencer is set to STEP 1 before the next MIDI clocks $F8 are received. I don't need to use a START pulse as my sequencer will start on the next clock pulse.
Pin A10 is connected to a 47K pot to adjust the clock divide ratio. Stop the sequencer before changing this value.
The MIDI Start command $FA is used to ensure the first Clock Pulse is sent out and that the RESET line goes LOW
/*
* BasicMidiClockDiv.ino
* Tested on Logic 10.6 and Ableton Live 9
* Proves Clock Out, Reset and CLock Divide
*/
#include "MIDIUSB.h"
#define CLK 5 // Clock
#define RST 2 // Reset
#define DEADBAND 24
// Pin A10 uses a 10K (47K) pot to set Clock Divide
//Pulse per quarter note. Each beat has 24 pulses.
//Tempo is based on software inner BPM.
int ppqn = 0;
int ClkOn = 2 ;
int ClkOff = 5 ;
int prev_val;
int value ;
void setup() {
Serial.begin(115200);
pinMode(RST, OUTPUT);
pinMode(CLK, OUTPUT);
}
void loop() {
midiEventPacket_t rx;
do {
rx = MidiUSB.read();
//Count pulses
if(rx.byte1 == 0xF8){
if(ppqn == 1) {
digitalWrite(CLK,HIGH);
}
if(ppqn == ClkOn) {
digitalWrite(CLK,LOW);
}
if(ppqn == ClkOff) {
ppqn = 0;
}
++ppqn ;
}
//Clock start byte
else if(rx.byte1 == 0xFA){
digitalWrite(CLK,HIGH);
// digitalWrite(RST,LOW);
ppqn = 0;
}
//Clock stop byte
else if(rx.byte1 == 0xFC){
// MidiUSB.flush();
digitalWrite(RST,HIGH);
digitalWrite(CLK,LOW);
delay(200);
digitalWrite(RST,LOW);
ppqn = 0;
}
} while (rx.header != 0);
// CLOCK DIVIDE
value = analogRead(A10);
// Get difference from current and previous value
int diff = abs(value - prev_val);
// Exit this function if the new value is not within the deadband
if (diff <= DEADBAND) return;
// Store new value
prev_val = value;
// Get the 7 bit value
int val2bit = value >> 7;
Serial.print(val2bit);
Serial.println();
prev_val = value;
// <3 <6 <12 < 24 1/16 1/8 1/4 1/2
switch (val2bit) {
case 0:
ClkOn = 1;
ClkOff = 2 ;
Serial.print(val2bit);
Serial.print(ClkOn );
Serial.println();
break ;
case 1:
ClkOn = 2;
ClkOff = 3 ;
Serial.print(val2bit);
Serial.print(ClkOn );
Serial.println();
break ;
case 2:
ClkOn = 3 ;
ClkOff = 6 ;
Serial.print(val2bit);
Serial.print(ClkOn );
Serial.println();
break ;
case 3:
ClkOn = 4 ;
ClkOff = 8 ;
Serial.print(val2bit);
Serial.print(ClkOn );
Serial.println();
break ;
case 4:
ClkOn = 6;
ClkOff = 12 ;
Serial.print(val2bit);
Serial.print(ClkOn );
Serial.println();
break ;
case 5:
ClkOn = 8; // triplet
ClkOff = 16 ;
Serial.print(val2bit);
Serial.print(ClkOn );
Serial.println();
break ;
case 6:
ClkOn = 12;
ClkOff= 24 ;
Serial.print(val2bit);
Serial.print(ClkOn );
Serial.println();
break ;
case 7:
ClkOn = 24;
ClkOff= 48 ;
Serial.print(val2bit);
Serial.print(ClkOn );
Serial.println();
break ;
}
// }
}
Comments