Ich habe einen optischen Encoder mit 600 Impulsen pro Umdrehung (und einige andere Dinge), der über die Interrupt-Pins 2 und 3 mit einem Arduino Uno verbunden ist (versuchte es auf r2 und r3).
Während ich darauf wartete, dass meine MIDI-Buchse per Post ankam, versuchte ich, mein Setup über den seriellen USB-Port mit meinem Computer zu verbinden, zusammen mit Hairless-Midi und LoopMidi. Loopmidi ist ein virtueller MIDI-Port, und Hairless-Midi überbrückt serielle Ports mit MIDI-Ports – virtuell oder anderweitig. Ich habe eine Baudrate von 115200 verwendet, weil ich dachte, dass es nicht schaden könnte, zu hoch zu gehen. In Mixxx schien alles ziemlich gut zu funktionieren. Wirklich gut, eigentlich. Es schien sehr reaktionsschnell und genau zu sein. Der Encoder hat keinen Takt verpasst, egal wie schnell ich das Ding überspanne.
Daher war ich ziemlich aufgeregt, als die MIDI-Buchse ankam. Ich legte es in mein Steckbrett und änderte es
Serial.begin(115200);
zu
Serial.begin(31250);
und in Mixxx getestet. Wenn ich jetzt den Encoder mäßig schnell in eine Richtung drehe, bewegt sich die virtuelle Platte in diese Richtung und dreht sich dann plötzlich in die andere Richtung und dann wieder zurück. Ich nehme an, dass dem Encoder Impulse fehlen?
Ich habe es in zwei verschiedenen 6-Dollar-USB-Midi-Kabeln sowie in meinem M-Audio Fast Track Ultra ausprobiert.
Dann dachte ich, dass es vielleicht etwas mit der niedrigeren Baudrate zu tun hat (115200 vs 31250). Ich änderte die Rate auf 38400 und ging über USB Serial. Es hat super funktioniert. Ich habe sogar 19200 ausprobiert. Perfekt. Sogar bei 9600 hat es funktioniert.
Warum passiert das? Ist die USB-Seriell-Schaltung im Arduino zusammen mit etwas freier Software wirklich zuverlässiger als ein Midi-Kabel und ein 300-Dollar-Audio-Interface, selbst wenn das Arduino auf sehr niedrige Baudraten eingestellt ist? Oder gibt es etwas an der seltsamen Baudrate von 31250, die Probleme im Arduino verursacht?
Ich hatte keine Gelegenheit zu versuchen, die 31250-Rate über die USB-Serial zu verwenden, da haarloses Midi diese Rate nicht zulässt.
BEARBEITEN: Hier ist der relevante Teil des Codes und der relevante Teil der Schaltung. Es gibt ein paar andere Komponenten, die das Problem verschlimmern könnten, aber selbst ohne diese Komponenten funktioniert der optische Encoder bei 31250 nicht.
enum PinAssignments {
encoderPinA = 2, // rigth
encoderPinB = 3, // left
};
volatile int encoderPos = 0; // a counter for the dial
unsigned int lastReportedPos = 0; // change management
boolean A_set = false;
boolean B_set = false;
void setup() {
pinMode(encoderPinA, INPUT_PULLUP);
pinMode(encoderPinB, INPUT_PULLUP);
// encoder pin on interrupt 0 (pin 2)
attachInterrupt(0, doEncoderA, CHANGE);
// encoder pin on interrupt 1 (pin 3)
attachInterrupt(1, doEncoderB, CHANGE);
Serial.begin(31250);
}
void loop() {
if (encoderPos != lastReportedPos){
Serial.write(0xB0);
Serial.write(0x27);
Serial.write(64 + encoderPos - lastReportedPos);
encoderPos = 0;
lastReportedPos = encoderPos;
}
}
// Interrupt on A changing state
void doEncoderA(){
A_set = !A_set;
// adjust counter + if A leads B
if ( A_set && !B_set )
encoderPos += 1;
}
// Interrupt on B changing state, same as A above
void doEncoderB(){
B_set = !B_set;
if( B_set && !A_set )
encoderPos -= 1;
}
Es ist komisch. Eine andere Möglichkeit: Verwirrt die seltsame Baudrate irgendwie die Hardware-Interrupts?
Nochmals BEARBEITEN: Ich habe mixxx im Mididebug-Modus ausgeführt und den Datensatz in eine Richtung gespannt. Das stand im Log:
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3E"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
... for a while and then ...
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41"
...
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Es geht also von der Wiederholung von 63 mit gelegentlichen 62 bis zur plötzlichen Wiederholung von 65 mit gelegentlichen 66. Eine Geschwindigkeit von 64 bedeutet, dass sich das Rad nicht bewegt. 63 bedeutet eine Bewegung gegen den Uhrzeigersinn um einen Impuls. 65 ist ein Impuls im Uhrzeigersinn. Oder umgekehrt, je nachdem wie das Ding verkabelt ist.
Bedeutet das, dass das Problem beim Arduino und nicht bei den Midi-Adaptern liegt?
Ihre Baudrate ist kein ganzzahliger Teiler Ihrer MCU-Uhr. Die Baudrate wird von der Uhr der MCU geteilt. Es ist einfach, 9600, 19200 und andere Raten mit einem ganzzahligen Teiler der Uhr zu erhalten. Wenn Sie beispielsweise einen 6,144-MHz-Quarz haben, müssen Sie durch 3200 teilen, um 19200 zu erhalten.
Für die ungeraden Datenraten in verschiedenen Anwendungen (Audio, analoges Video und viele andere) werden spezielle Kristalle verwendet, um einen ganzzahligen Teiler zu erhalten. Beispielsweise könnte eine NTSC-Schaltung einen 5,034963-MHz-Kristall zum Erzeugen der verschiedenen Synchronisationssignale haben, siehe
Wenn Ihre MCU über einen internen Taktgenerator verfügt, versuchen Sie, ihn auf einen anderen Wert einzustellen, um einen ganzzahligen Teiler zu erhalten, da sonst der Bitfehler zu hoch ist.
Eine definitive Möglichkeit zum Testen besteht darin, Ihren MIDI-Ausgang mit Ihrem MIDI-Eingang zu verkabeln und das System wie zuvor mit dem seriellen USB einzurichten, es jedoch (über Ihre "virtuelle Midi-Kabel" -Software) an den MIDI-Ausgang des Computers zu leiten . Dadurch wird getestet, ob Ihre USB-MIDI-Hardware tatsächlich zuverlässig mit der Datenrate arbeitet, mit der das Gerät arbeitet. Meiner Erfahrung nach sind viele USB-MIDI-Geräte im Grunde für Keyboards konzipiert (die nur etwa 3 Bytes senden, wenn eine Taste gedrückt oder losgelassen wird) und haben seltsame Überlaufprobleme, wenn Sie mit der vollen 31,25-kBit-Rate senden. Dies ist auch sehr stark vom Betriebssystem / Treiber abhängig.
Ich denke, Sie möchten auch sicherstellen, dass der Sender/Leitungstreiber funktioniert. Bitte posten Sie ein Schema Ihrer Arduino MIDI-Out-Schaltung. Was verwendest du als Ausgangstreiber?
Ich mache viele Annahmen, aber unter der Annahme, dass der Arduino Uno bei 16 MHz, 31250 bps genau unterstützt wird (0% Fehler) mit einem UBBR-Registerwert von 31, laut diesem: AVR UART- Ratenrechner . Dies zeigt mir, dass die Bitrate von MIDI kein Problem sein sollte (mein Verständnis ist tatsächlich, dass 31250 weitgehend so gewählt wurde, dass es mit einem 1-MHz-Takt einfach zu handhaben ist, im Gegensatz zu den von Fernschreibmaschinen abgeleiteten RS-232-Raten).
Außerdem wäre ein Dump der Nachrichten, die der PC über einen MIDI-Sniffer oder -Monitor empfängt, beim Debuggen sehr nützlich.
Jippie
Der Phil Lee
Jippie
Der Phil Lee
Jippie