Midi empfangen, hardware

#1291740
Lesenswert?

Hallo,

ich möchte mit meinem AVR über UART MIDI programm changes empfangen.
Softwaremäßig stellt das denke ich kein größeres Problem da, allerdings 
hab ich eine Frage zur Hardware:

Ich wollte den Midi Eingang so wie beim Mr.Midi realisieren:
http://www.mikrocontroller.net/articles/Bild:Eagle-schematic.gif

Allerdings hatte der elektronikladen um die Ecke heute keinen 6N138, 
sondern nur den 6N137 optokoppler. Laut datenblatt ist der ziemlich 
identisch was die Geschwindigkeit angeht. Allerdings hat der keinen 
Darlington Ausgang. Kann ich sie schaltung trotzdem so aufbauen, oder 
muss ich irgendwas beachten? oder ändern?

Gruß
(Firma: TravelRec.) Persönliche Seite #1292011
Lesenswert?

MIDI kann man mit jedem Wald- und Wiesenoptokoppler, wie z.B. CNY17 oder 
PC817 oder ähnliche Typen aufbauen, weil die 31250 Bit/s schaffen alle. 
Lediglich der Arbeitswiderstand des Ausgangstransistors ist kritisch, um 
den richtigen Arbeitspunkt für ausreichend steile Flanken einzustellen. 
Der 6N136/137 ist mit Kanonen auf Spatzen geschossen.
Moderator (Firma: Titel) Persönliche Seite #1292070
Lesenswert?

> die 31250 Bit/s schaffen alle
Machen dabei aber eine nicht ohne weiters vernachlässigbare Verschiebung 
der steigenden bzw. fallenden Flanke.
Der Arbeitspunkt ist elementar wichtig, mit Rc=1k gilt bei sättigendem 
Betrieb des Ausgangstransistors (CNY17): ton = 25us, toff = 42,5us --> 
dmit überschlägig 25us+42,5us = 67us --> 15kHz...

Auch die Daten aus den Datenblättern (PC817) bei Rc=100 Ohm (nicht 
sättigender Betrieb) mit ton=4..18us und toff=3..18us sind m.E. bei 
einer Bitdauer von 32us irgendwie, naja, hmmm...

> Der 6N136/137 ist mit Kanonen auf Spatzen geschossen.
Hauptsache: immer getroffen  ;-)
#1293264
Lesenswert?

hm, ich hab das jetzt mal alles aufm steckbrett aufgebaut und wollt ein 
wenig testen, da ist mir im datenblatt des 6N137 aufgefallen, das der 
Ausgang der single channel variante invertiert ist.

dem USART des atmega 644 kann man nicht irgendwie sagen, alles was 
reinkommt zu invertieren, oder?

inverter hab ich leider keinen da, nur einen BC328. Lässt sich damit ein 
inverter basteln? (ich kenne nur eine Schaltung mit npn)
Moderator (Firma: Titel) Persönliche Seite #1293492
Lesenswert?

> 6N137 ... der Ausgang ... invertiert ist.
Also laut DB: Strom durch die Diode -> 0V am Ausgang
Das ist üblich und gilt übrigens auch für die Zweikanal-Variante.

Sieh dir das mal an: Genau das selbe macht die Schaltung aus 
http://www.midi.org/techspecs/electrispec.php
Auch hier gilt: Strom durch die Diode -> 0V am UART

Fazit: alles im grünen Bereich.

> inverter hab ich leider keinen da, nur einen BC328. Lässt sich damit ein
> inverter basteln? (ich kenne nur eine Schaltung mit npn)
Klar geht das, jeder Transistor ist als Inverter beschaltbar, und nicht 
immer in der Geschichte der Elektronik war der Minuspol auch zugleich 
GND.
1
        ------o------- +5V
2
              |
3
       __   |<
4
  IN -|__|--|
5
5V/0V       |\
6
              |
7
              o---- OUT 
8
              |     0V/5V
9
             .-.  
10
             | | 
11
             '-'  
12
              |  
13
        ------o------- GND
#1461919
Lesenswert?

Nun, zwar eine Weile her, aber jetzt erst habe ich die Beschaltung in 
Betrieb genommen.

Funktioniert einwandfrei, ohne Inverter.

Allerdings habe ich jetzt ein Softwareseitiges Problem:
Mich interessieren nur eingehende Program change befehle.
Diese filtere ich im RX Complete interrupt.
Das klappt soweit auch ganz gut. Nun steht die Programmnummer aber im 
zweiten gesendeten Byte, und das krig ich nicht abgefangen, da bin ich 
immer zu langsam und bekomme irgendwelche daten von nachfolgenden midi 
befehlen.

1
// midi rx interrupt
2
ISR(USART0_RX_vect)
3
{
4
  if((UDR0 & 0b11110000) == 0b11000000)  // filter program change command on any channel
5
  {
6
    UCSR0A &= ~(1<<RXC0);
7
    while(UCSR0A & (1<<RXC0));
8
    printf("Program change %d\n", UDR0); // <- Hier kommt irgendwas
9
  }
10
}


Da wenn ich die Daten garnicht behandle und nur ausgebe, komischerweise 
alles ankommt hab ich es auch mal mittels Flag probiert:
1
volatile uint8_t pcf = 0;
2

3
// midi rx interrupt
4
ISR(USART0_RX_vect)
5
{
6
  if(pcf)
7
  {
8
    printf("%d\n", UDR0);
9
    pcf = 0;
10
  }
11
  if((UDR0 & 0b11110000) == 0b11000000)  // filter program change command on any channel
12
    pcf = 1;  
13
}


Das funktioniert auch fast prima. Nur bekomme ich neben dem program 
change wert, kurz darauf noch einen weiteren (immer 177) ausgegeben. Als 
würde vor dem löschen des flags ein interrupt eintreten, was in der ISR 
aber kaum sein kann.

Ich bin bei beiden Varianten ratlos. Kann mir jemand weiterhelfen?
#1461964
Lesenswert?

okay, wunderbar, jetzt gehts, wobei ich das polling problem nochnicht 
ganz versteh. in der ISR kann ja kein interrupt auftreten.

So funktionierts jetzt:
1
// midi rx interrupt
2
ISR(USART0_RX_vect)
3
{
4
  uint8_t data = UDR0;
5
  if(pcf)
6
  {
7
    printf("%d\n", data+1);
8
    pcf = 0;
9
  }
10
  if((data & 0b11110000) == 0b11000000)  // filter program change command on any channel
11
    pcf = 1;  
12
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren