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 (auf r2 und r3 ausprobiert) verbunden ist.
Während ich darauf wartete, dass meine MIDI-Buchse per Post einging, versuchte ich, mein Setup zusammen mit hairless-midi und loopMidi über den seriellen USB-Anschluss mit meinem Computer zu verbinden. Loopmidi ist ein virtueller MIDI-Port, und hairless-midi verbindet serielle Ports mit virtuellen oder anderen MIDI-Ports. Ich habe eine Baudrate von 115200 verwendet, weil ich dachte, es könnte nicht schaden, 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 Beat verpasst, egal wie schnell ich das Ding überspanne.
Ich war also ziemlich aufgeregt, als die MIDI-Buchse ankam. Ich legte es in mein Steckbrett und zog mich um
Serial.begin(115200);
zu
Serial.begin(31250);
und testete es in Mixxx. Wenn ich den Encoder jetzt mäßig schnell in eine Richtung drehe, bewegt sich der virtuelle Datensatz in diese Richtung und dreht sich dann plötzlich in die andere Richtung und dann wieder zurück. Ich gehe davon aus, dass dem Encoder Impulse fehlen?
Ich habe es in zwei verschiedenen 6-Dollar-USB-Midi-Kabeln sowie in meinem M-Audio Fast Track Ultra versucht.
Dann dachte ich, dass es vielleicht etwas mit der niedrigeren Baudrate zu tun hat (115200 vs 31250). Ich habe die Rate auf 38400 geändert und bin über USB seriell gegangen. Es hat super funktioniert. Ich habe es sogar mit 19200 versucht. Perfekt. Sogar bei 9600 hat es funktioniert.
Warum passiert dies? Ist die USB-serielle Schaltung im Arduino zusammen mit einer kostenlosen 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 31250-Baudrate, das Probleme im Arduino verursacht?
Ich hatte keine Chance, die 31250-Rate über die USB-Serie zu verwenden, da haarloses Midi diese Rate nicht zulässt.
EDIT: Hier ist der relevante Teil des Codes und der relevante Teil der Schaltung. Es gibt einige andere Komponenten, die das Problem möglicherweise verschlimmern, aber auch 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: Beeinträchtigt die seltsame Baudrate irgendwie die Hardware-Interrupts?
Nochmals BEARBEITEN: Ich habe mixxx im Mididebug-Modus ausgeführt und den Datensatz in eine Richtung verschoben. Dies war im Protokoll:
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 einer Wiederholung von 63 mit einer gelegentlichen 62 zu einer plötzlichen Wiederholung von 65 mit einer gelegentlichen 66. Eine Geschwindigkeit von 64 bedeutet, dass sich das Rad nicht bewegt. 63 bedeutet, einen Impuls gegen den Uhrzeigersinn zu bewegen. 65 ist ein Impuls im Uhrzeigersinn. Oder umgekehrt, je nachdem, wie das Ding verkabelt ist.
Bedeutet das, dass das Problem im Arduino und nicht in den Midi-Adaptern liegt?
Antworten:
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-Kristall haben, müssen Sie durch 3200 dividieren, um 19200 zu erhalten.
Für die ungeraden Datenraten in verschiedenen Anwendungen (Audio, analoges Video und viele andere) werden spezifische Kristalle verwendet, um einen ganzzahligen Divisor zu erhalten. Beispielsweise könnte eine NTSC-Schaltung einen 5,034963-MHz-Kristall zum Erzeugen der verschiedenen Synchronisationssignale aufweisen, siehe
Wenn Ihre MCU über einen internen Taktgenerator verfügt, versuchen Sie, ihn auf einen anderen Wert einzustellen, um einen ganzzahligen Divisor zu erhalten. Andernfalls ist der Bitfehler zu hoch.
quelle
Eine definitive Möglichkeit zum Testen besteht darin, Ihren MIDI-Ausgang mit Ihrem MIDI-Eingang zu verbinden und das System wie zuvor über USB-Seriell einzurichten, es jedoch (über Ihre Software für das virtuelle Midi-Kabel) an den MIDI-Ausgang des Computers weiterzuleiten . Dadurch wird geprüft, ob Ihre USB-MIDI-Hardware tatsächlich zuverlässig mit der Datenrate arbeitet, mit der das Gerät arbeitet. Nach meiner Erfahrung sind viele USB-MIDI-Geräte im Wesentlichen für Keyboards konzipiert (die beim Drücken oder Loslassen einer Taste nur etwa 3 Byte senden) 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 veröffentlichen Sie eine schematische Darstellung Ihrer Arduino MIDI-Out-Schaltung. Was verwenden Sie als Ausgabetreiber?
Ich mache viele Annahmen, aber unter der Annahme, dass der Arduino Uno bei 16 MHz 31250 Bit / s mit einem UBBR-Registerwert von 31 genau unterstützt wird (0% Fehler), lautet dies: AVR UART- Ratenrechner . Dies zeigt mir, dass die Bitrate von MIDI kein Problem sein sollte (nach meinem Verständnis wurde 31250 im Gegensatz zu den von Teletyp-Maschinen abgeleiteten RS-232-Raten weitgehend so gewählt, dass sie mit einem 1-MHz-Takt einfach zu handhaben sind).
Außerdem wäre ein Dump der Nachrichten, die der PC über einen MIDI-Sniffer oder -Monitor empfängt, beim Debuggen sehr nützlich.
quelle