PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : MIDI Übertragungsfehler [gelöst]



Bääääär
22.03.2009, 19:18
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

PicNick
22.03.2009, 19:37
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, ?

Bääääär
22.03.2009, 20:39
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);

}

wkrug
22.03.2009, 22:36
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.

Bääääär
22.03.2009, 23:16
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

PicNick
23.03.2009, 07:49
Welche Werte hast du für r5, r6 ?

Die verwende ich, geht tadellos
https://www.roboternetz.de/wissen/index.php/MIDI-Interface

wkrug
23.03.2009, 07:56
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.

tholan
23.03.2009, 11:30
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.

PicNick
23.03.2009, 13:33
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 ?

tholan
23.03.2009, 14:07
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.

PicNick
23.03.2009, 17:24
Damit allein funzt es eben nicht:
Kommen zwei Notes hintereinander, der zweite aber ohne Command, dann kriegt er letzteren nicht mit.

tholan
23.03.2009, 19:38
Ups, stimmt,
dann geht das nur mit Keyboards, die ohne diesen "Running Mode" arbeiten.

Bääääär
30.03.2009, 23:06
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

tholan
01.04.2009, 22:48
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.

Bääääär
01.04.2009, 22:59
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

Bääääär
09.05.2009, 15:44
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