Archiv verlassen und diese Seite im Standarddesign anzeigen : MIDI Übertragungsfehler [gelöst]
Hallo alle zusammen!
Ich habe folgendes Problem, bei dem ich eure Hilfe brauche:
Ein Atmega32 @ 16Mhz empfäng Daten von einem MIDI-Keyboard. Die angehängte Schaltung wandelt die Daten von einem "Strom-Signal" in ein "Spannungs-Signal" um (sodass ich sie bei 31250 Baud mit der USART empfangen kann).
Leider kommt es immer wieder zu Übertragungsfehler, was bei einem MIDI Instrument - nunja - bescheiden ist. Immer wieder bleiben Töne hängen oder gar falsche Töne erklingen.
Zwischen der Platine mit der angehängten Schaltung und dem AVR sind nochmal 15cm ungeschirmte Leitung (einfach 2 Kabel).
Was kann ich tun, um die Fehler zu minimieren?
Danke für Hilfe,
Bääääär
Elektrisch kann man da nicht viel falsch machen. Ist ja eine Stromschleife, die büffelt vor sich hin.
Hangeln bleiben gibt es ja, aber "falsche" Töne sind bei MIDI seltsam.
Ist deine Empfangsroutine wasserdicht ?
running status, etc, ?
Ich hoffe doch, dass der Code in Ordnung ist. ich habe ihn mal angehangen.
Zum Phänomen: Es erklingen beim Drücken einer Taste teils falsche Töne, die dank richtig überragenem NoteOff-Event dann hängen bleiben. Das sind eigentlich fast alle möglichen Töne - rauf und runter.
Folgendes wird bem Empfangen aufgerufen:
SIGNAL (SIG_USART_RECV) {
Keyboard_ReceiveMessage(UDR);
}
Meine Vermutung ist auch, das es sich dabei um Bittfehler handelt, die sich bei der Übertragung einschleichen.
Ich würd's mal mit einem anderen Optokoppler (mit integriertem Schmitt Trigger) versuchen.
Nimm mal den PC900 von Sharp.
Ja, Bitfehler sind das sicher. Der Optokoppler könnte natürlich wirklich eine Fehlerquelle sein. Meiner wurde allerdings auch hier verwendet: http://www.mikrocontroller.net/articles/Midi_Rekorder_mit_MMC/SD-Karte
Ok, was macht den Sharp denn besser, im Vergleich zum jetztigen? Schmitt Trigger klingt sinnvoll - aber wird das wirklich Besserung bringen?
Grüße,
Bääääär
Welche Werte hast du für r5, r6 ?
Die verwende ich, geht tadellos
https://www.roboternetz.de/wissen/index.php/MIDI-Interface
Schmitt Trigger klingt sinnvoll - aber wird das wirklich Besserung bringen?
Ich hab kürzlich mit den 6N139 ein wenig rumgepielt und hab bei einer Übertragungsrate von 38400 Bit / sek den Kollektorwiderstand auf 1k Ohm reduzieren müssen um ausreichend steile Flanken hinzukriegen. Erst bei so kleinen Kollektorwiderstand lief die Datenübertragung fehlerfrei.
Aus der Vergangenheit:
Meine Versuche mit MiDi und dem ach so beliebten CNY17 waren auch nicht von Erfolg gekrönt.
Als ich den Entwurf dann auf PC900 umgestrickt hab lief es dann plötzlich problemlos.
Der PC900 wurde, soweit ich weiß, für den Einsatz in Stromschleifen entwickelt.
Das kannst Du ja aber auch alles im Datenblatt nachlesen.
Eine Zeitlang wurde der Optokoppler als Obsolete erklärt inzwischen hat sich Sharp anscheinend eines Besseren besonnen.
Der PC900 im Ausgang nicht einfach einen Transistor, sondern einen Eingangsverstärker mit eingebautem Schmitt Trigger, was auch bei verschliffenen Eingangssignalen steile Impulsflanken generiert.
Da macht der 6N139 das genaue Gegenteil davon.
Das Teil kostet bei Conrad gerade mal 1,70€ - Einen Versuch wär mir das schon mal Wert.
Ich hab Deinen Code nicht durchgeackert, aber beherrscht der auch den "running status"?
Mein Masterkeyboard (M-Audio Delta V2 )produziert ebenjenen und ich hab damit schon 'ne Weile
gekämpft.
p.s.
Ich nutze seit Jahren den 6N137 mit der üblichen Eingangsbeschaltung:
Antiparallele Si-Diode, 220R.
Ausgangsseitig nutze ich nur den AVR-internen Pullup (ist der an?).
Der PC900 ist mir zu teuer und mit dem CNY17 isses 'ne Fummelei mit den Pullups.
Ich hab eigentlich in dem Code nix in richtung runningstatus erkennen können.
Bei einem Controll-Byte (2^^7) setzt er den Buffer zurück.
Und er interessiert sich offenbar nur für note-on/off.
Das scheint mir für einen speziellen Zweck geschrieben zu sein.
Was soll das Zeugs denn können ?
Bei einem Controll-Byte (2^^7) setzt er den Buffer zurück.
Dann sollts auch mit "Running Status" funktionieren, wenn die Notennummer nicht woanders
verschluckt wird und die Velocity als solche dann interpretiert wird.
"Running Status" bedeutet, daß nicht jeden kanalabhängigen Daten ein Statusbyte vorangestellt werden
muß, solange der Status sich nicht ändert. Keyboards, die so funktionieren, wie z.B.
das Oxygen V2 von M-Audio, kennen daher auch kein echtes "Note Off" (0x8n), sondern
machen für "Note Off" nochmals ein "Note On" (Bzw. bleibt es beim Status 0x9n) mit der Velocity 0 auf die entsprechende Notennummer.
Sonst würde sich das mit dem "Runnimg Status" nicht lohnen.
Dabei geht allerdings die Loslaß-Velocity flöten.
Damit allein funzt es eben nicht:
Kommen zwei Notes hintereinander, der zweite aber ohne Command, dann kriegt er letzteren nicht mit.
Ups, stimmt,
dann geht das nur mit Keyboards, die ohne diesen "Running Mode" arbeiten.
Hallo mal wieder!
Hatte einigen Schulstress, deshalb melde ich mich jetzt erst. Danke schonmal für die zahlreichen Antworten!
Welche Werte hast du für r5, r6 ?
Die Werte der Widerstände, die den Optokoppler betreffen, entsprechen denen im von mir geposteten Schaltplan (hier (http://www.mikrocontroller.net/articles/Midi_Rekorder_mit_MMC/SD-Karte)).
Wenn ich das mit dem running status richtig verstanden habe, dann beherrsche ich den. Ich verwende solange das letzte Statusbyte (also das der letzten vollen Message), bis wieder ein Statusbyte ankommt. Ich habe nochmal zwei Kommentare in GROSSBUCHSTABEN angefügt, die diese Thematik betreffen.
// This function is called, when new data from the keyboard reaches the UART-RX.
// It stores all bytes in "LastMessage", until a NoteOn or NoteOff message is complete.
void Keyboard_ReceiveMessage(unsigned char c){
// WENN DAS EMPFANGENE BYTE GROESSER IST ASL 127 (ALSO VORNE EINE 1 HAT => EIN STATUSBYTE IST) WIRD ES ALS LETZTES STATUSBYTE VERMERKT
if (c > 127) { // if c is a command-byte, restart receiving message
received = 0;
}
LastMessage[received] = c;
received++;
if (((received == 3) && ((LastMessage[0]>>4) == 0b00001001)) || // if the received message has 3 bytes and is a NoteOn-Event
((received == 2) && ((LastMessage[0]>>4) == 0b00001000))) { // or if it has 2 bytes and is a NoteOff-Event
// wait if the Buffer is full.
sei();
while((KEYBOARDBUFFERSIZE + Keyboard_Buffer_Start - Keyboard_Buffer_End) % KEYBOARDBUFFERSIZE >
(KEYBOARDBUFFERSIZE - 2));
cli();
// This Message is now complete => it can be filled in the buffer
Keyboard_Buffer[Keyboard_Buffer_Start][0] = LastMessage[0];
Keyboard_Buffer[Keyboard_Buffer_Start][1] = LastMessage[1];
Keyboard_Buffer[Keyboard_Buffer_Start][2] = LastMessage[2];
Keyboard_Buffer_Start++ ;
if (Keyboard_Buffer_Start > KEYBOARDBUFFERSIZE - 1) {
Keyboard_Buffer_Start = 0;
}
// reset to get the next (one/two) databytes
// HIER WIRD WIEDER ZURÜCKGESETZT, ABER SO, DASS DAS LETZTE STATUSBYTE ERHALTEN BLEIBT
received = 1;
}
}
Ja, der Code soll nur Note-On oder Note-Off erkennen, da ich damit die Daten aus der Platine einer Klaviatur auslese. Das ganze findet in meiner Keytar Verwendung (siehe Anhang).
Keyboards, die so funktionieren, wie z.B.
das Oxygen V2 von M-Audio, kennen daher auch kein echtes "Note Off" (0x8n), sondern
machen für "Note Off" nochmals ein "Note On" (Bzw. bleibt es beim Status 0x9n) mit der Velocity 0 auf die entsprechende Notennummer.
Auch das funktioniert bei mir.
Nochmals zur Problembeschreibung: Die falsch gesendeten Töne (kommt bei Note-Ons und bei Note-Offs vor) kommen eher sporadisch. Es gibt Phasen, da geht alles und es gibt Phasen, da spielt meine Keytar nur Müll. Ich vermute sehr stark, dass es da geringe Einflüsse von außen gibt (z.B. Felder von Boxen oder sonstwas) die Dank falscher Beschaltung bzw. falschem Optokoppler dick ins Gewicht fallen...
Ich würde das gerne mal am Oszi betrachten, um zu sehen, wo das Problem liegt - ich habe auch einen (wenn er die Bezeichnung Oszi verdient). Bild siehe Anhang. Ich hab keine Ahnung, wie man den benutzt...
Nochmal zum PC900: Ich werde mir mal einen kaufen. Wie sieht die Beschaltung bei dir aus, wkrug?
Vielen Dank,
Bääääär
Ich geb Dir mal ein paar Beispiele, wie Note On, oder Note Off aussehen kann.
Das kannst Du ja mal durchspielen, um Programmierfehler auszuschließen:
Mein Running Status hat nämlich gemeinerweise auch noch nen Time Out von ca. 2Sekunden, wenn nix passiert.
Eingestellt ist Kanal 1. Ich spiele Notennummer 60, dann 62, lasse dann 60 los und dann 62.
Erstmal die Tripletts mit echtem Note Off und echter "Loslaßvelocity", ohne Running Status, wie es mein X7000 macht.
Dabei lasse ich die Nr60 langsam los, Velo=0 und die Nr62 schnell, Velo=108:
144, 60, 32.....144, 62, 45.......128, 60, 0....128, 62, 108
Jetzt, wie es das Oxygen macht im Running Status, noch ohne Timeout:
144, 60, 32.....62, 45.......60, 0........62, 0
Jetzt mache ich ne Pause von 3Sekunden, bevor ich die zuerst angeschlagene Note, Nr 60 loslasse:
144, 60, 32.....62, 45...............144, 60, 0.....62, 0
Das muß die Routine alles können, wenn sie wasserdicht sein soll.
Wie Du siehst, kann auch dieses Pseudo Note off drei Byte haben.
Das Statusbyte kann also quasi an beliebiger Stelle Notennummer und Velocity anführen.
Warum shiftest Du eigentlich im Statusbyte Das Statusnibble auf das Kanalnummernibble
im zweiten if ?
Sieht irgendwie unnötig aus. Shiften ist ein ganz schöner Aufwand für den Atmel.
Hallo!
Ja, die beschriebenen Dinge sind für meine Routine kein Ding.
Das Shiften mache ich, um zu erfahren, ob die empfangene Message ein NoteOn oder NoteOff ist. Der Rest soll ignoriert werden. Zugegebenermaßen, das ließe sich auch nich eleganter machen. Ich schau mal.
Ich bin aber sicher, dass das so geht. In der Software vermute ich keinen Fehler. Die hat auch schon (in leicht abgewandelter Form) auf einem Eval-Board geklappt - ohne Übertragungsfehler. Außerdem wäre dann zumindest ein System hinter den Übertragungsfehlern. Es gibt ja Momente, da kann ich 2 Minuten lang diverses Zeug spielen, ohne einen einzigen Fehler zu haben.
Ich probiere jetzt mal den PC900 aus. Wobei ich auch gelesen habe, man solle den nicht nehmen. Naja, einen Versuch is es ja Wert.
Danke für die viele Hilfe,
Bääääär
Ja, der PC900 hats getan!
Vielen Dank für den guten Tipp! Habe jetzt schon seit mehreren Wochen keine Fehler gehabt, und hoffe, dass es auch dabei bleibt =)
Wenn jemand das gleiche Problem hat, kann er/sie mir einfach eine PN schicken.
Euer Bääääär
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.