megalomidiac
Member
Serial port / MIDI CLOCK problems with Teensy 3.2
Hi, I am working on a 32 step sequencer with various modes and tried to make it work on 16 channels simultanously.
The problem is, the BPM speed will decrease rapidly and become unstable, if I make more than 3 channels at the same time, or increase the clock divider with MIDI serial1 activated.
If I turn serial1 off and use only the USB MIDI the problem doesn't occur.
As the original code would be to big, I have broken it down to a test/performance code, which can be adjusted at int divider, int bpm and constant byte MAXTRACK. And off course deactivate the serial1.sendNoteOn for testing if USB works allone.
There will be some unnecessary parts be left in this code from the original like the pinouts or stp[], so don't note this.
I used an interrupt timer and I know you shouldn't use for examples arrays in it, but the problem doesn't occure with deactivated serial1.
To shorten the code for this inspection, I have left out all methods which fill out the arrays with own values and step information, chords and so on and made instead random values.
So there will be only the same chord per channel but on every channel another and it changes if you restart the device
Am I overdoing it to the Teensy hardware or made I a concept failure or something else?
Hi, I am working on a 32 step sequencer with various modes and tried to make it work on 16 channels simultanously.
The problem is, the BPM speed will decrease rapidly and become unstable, if I make more than 3 channels at the same time, or increase the clock divider with MIDI serial1 activated.
If I turn serial1 off and use only the USB MIDI the problem doesn't occur.
As the original code would be to big, I have broken it down to a test/performance code, which can be adjusted at int divider, int bpm and constant byte MAXTRACK. And off course deactivate the serial1.sendNoteOn for testing if USB works allone.
There will be some unnecessary parts be left in this code from the original like the pinouts or stp[], so don't note this.
I used an interrupt timer and I know you shouldn't use for examples arrays in it, but the problem doesn't occure with deactivated serial1.
To shorten the code for this inspection, I have left out all methods which fill out the arrays with own values and step information, chords and so on and made instead random values.
So there will be only the same chord per channel but on every channel another and it changes if you restart the device
Am I overdoing it to the Teensy hardware or made I a concept failure or something else?
Code:
#include <MIDI.h>
#include <IntervalTimer.h>
USING_NAMESPACE_MIDI
MIDI_CREATE_INSTANCE(HardwareSerial ,Serial1, MIDI1);
const byte CLOCK = 0xF8; //248;
const byte START = 0xFA; //250;
const byte CONTINUE = 0xFB; //251;
const byte STOP = 0xFC; //252;
const byte MAXTRACK = 4; //nr of max channels played simultanously
int bpm = 200;
int divider = 12; // 1/8 clock divider
//int divider = 6; // 1/16
//int divider = 3; // 1/32
byte seqValues[MAXTRACK][32] = {0};
byte seqControl[MAXTRACK][32] = {0};
float midIntervall = (1000.0/(float(bpm)/60.0))/24.0;
int tick[MAXTRACK] = {0}; //counter for ppq
int seqLength[MAXTRACK] = {0}; //length of step sequencer
int seqSpeed[MAXTRACK] = {0}; //clock divider
int stp[MAXTRACK] = {0}; //sequencer step position
IntervalTimer myTimer0;
void setup() {
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, INPUT_PULLUP);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
for(int i = 0; i < MAXTRACK; i++){
seqLength[i] = 16;
seqSpeed[i] = divider;
for(int j = 0; j < 32; j++){
seqValues[i][j] = random(36,81); //filling random notes and velocities at start
seqControl[i][j] = random(0,129);
}
}
MIDI1.begin(MIDI_CHANNEL_OMNI);
myTimer0.begin(MidiClock, float(midIntervall) * 1000.0);
myTimer0.priority(0);
}
void MidiClock() {
usbMIDI.sendRealTime(CLOCK); //USB sync signal
Serial1.write(CLOCK); //DIN sync signal
for (int i = 0; i < MAXTRACK; i++){
RealTimeSystem(CLOCK,i);
}
}
void RealTimeSystem(byte realtimebyte,byte curPattern) { // processes MIDI real time messages (MIDI system clock)
boolean advance = false;
if (realtimebyte == CLOCK) { // clock signal
tick[curPattern]++;
advance = (tick[curPattern] % seqSpeed[curPattern]) == 0;
}
if (realtimebyte == START) {
tick[curPattern] = 0;
}
if (realtimebyte == STOP) {
StopLastInSequence(curPattern);
ResetSequence();
}
if (advance) {
tick[curPattern] = 0;
SendNextInSequence(curPattern);
}
}
void ResetSequence() { //set all step sequencer position to 0
for(int i = 0; i < MAXTRACK; i++){
stp[i] = 0;
}
}
void SendNextInSequence(byte curPattern) {
byte seqChannel = curPattern + 1;
StopLastInSequence(curPattern); //stops last played note before playing next
usbMIDI.sendNoteOn(seqValues[curPattern][0],seqControl[curPattern][0],seqChannel);
MIDI1.sendNoteOn(seqValues[curPattern][0],seqControl[curPattern][0],seqChannel);
usbMIDI.sendNoteOn(seqValues[curPattern][1],seqControl[curPattern][1],seqChannel);
MIDI1.sendNoteOn(seqValues[curPattern][1],seqControl[curPattern][1],seqChannel);
usbMIDI.sendNoteOn(seqValues[curPattern][2],seqControl[curPattern][2],seqChannel);
MIDI1.sendNoteOn(seqValues[curPattern][2],seqControl[curPattern][2],seqChannel);
usbMIDI.sendNoteOn(seqValues[curPattern][3],seqControl[curPattern][3],seqChannel);
MIDI1.sendNoteOn(seqValues[curPattern][3],seqControl[curPattern][3],seqChannel);
}
void StopLastInSequence(byte curPattern) {
byte seqChannel = curPattern + 1;
usbMIDI.sendNoteOn(seqValues[curPattern][0],0,seqChannel);
MIDI1.sendNoteOn(seqValues[curPattern][0],0,seqChannel);
usbMIDI.sendNoteOn(seqValues[curPattern][1],0,seqChannel);
MIDI1.sendNoteOn(seqValues[curPattern][1],0,seqChannel);
usbMIDI.sendNoteOn(seqValues[curPattern][2],0,seqChannel);
MIDI1.sendNoteOn(seqValues[curPattern][2],0,seqChannel);
usbMIDI.sendNoteOn(seqValues[curPattern][3],0,seqChannel);
MIDI1.sendNoteOn(seqValues[curPattern][3],0,seqChannel);
}
void loop() {
// put your main code here, to run repeatedly:
}
Last edited: