Forum: Mikrocontroller und Digitale Elektronik Midi Control Change empfangen


von Fabian F. (fabiii9)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe es mitlerweile geschafft ein Midisignal von einen Fader an den 
Computer zu senden.
Mit angehängtem "Schaltplan".
Über den ADC Eingang am Atmega8 habe ich den Fader abgefragt. (Ich weiß 
das das nicht alzu genau ist. Reicht aber denkne ich aus.)

Nun will ich aber das Midisignal was ich von einem PC aus sende, am 
Mikrocotnroller empfangen und den gesendeten Midi Wert (Byte1 soll in 
eine Variabel, Byte 2 soll in eine Variable und Byte 3 soll auch in eine 
Variable (Byte 3 = 0...127)

Jetzt bin ich auf der Suche nach einem Codeschnipsel zum Einlesen dieser 
Mididaten mit einem Atmega8

Vielen Dank
Gruß
Fabi

von Karl H. (kbuchegg)


Lesenswert?

Fabian Müller schrieb:

> Jetzt bin ich auf der Suche nach einem Codeschnipsel zum Einlesen dieser
> Mididaten mit einem Atmega8

Das kommt mir ein wenig komisch vor.

Auf der einen Seite hast du selber Code geschrieben, der eine Midi 
Nachricht versendet, musst also wissen, dass das jeweils erste Byte in 
der Sequenz, welches das Kommando beinhaltet (das 'Statusbyte') dadurch 
erkennbar ist, dass es das Bit 7 auf 1 gesetzt hat. Weiters musst du 
logischerweise mit der UART umgehen können, denn sonst könntest du ja 
nichts wegsenden.
Auf der anderen Seite bist du aber nicht in der Lage, von der UART 
empfangene Bytes wegzuholen, anhand des gesetzten Bit 7 das Kommandobyte 
zu erkennen und dann ganz einfach die nächsten Bytes mitzuzählen um zu 
wissen, welches Datenbyte welche Bedeutung hat.

Jetzt bin ich wirklich verwirrt. Kann es sein, dass dein "ich habe es 
geschafft, das und das zu programmieren' in Wirklichkeit eher ein 'Ich 
habe es geschafft, den Code XYZ zu kopieren ohne ihn verstehen zu 
müssen' darstellt? Wenn ja, dann lass dir gesagt sein, dass das nicht 
funktioniert.

MIDI ist nichts anderes als die Behandlung der UART. Kannst du mit der 
UART umgehen, dann hast du die technische Hürde erst mal gemeistert. Und 
der Rest ist gerade bei Midi die Auswertung eines erst mal äusserst 
simplen Protokolls, dessen Abarbeitung damit beginnt, das man nachsieht 
ob das Bit 7 im gerade empfangenen Byte auf 1 ist oder nicht. Und der 
Rest ist: Eine Zählervariable, die laufend um 1 erhöht wird (und auf 
jeden Fall bei Erhalt eines Kommandobytes auf 0 zurück gesetzt wird), so 
dass dir der Zähler sagt, mit welchem Byte in der Sequenz du gerade zu 
tun hast.
Summa summarum: alles andere als Raketentechnik und für jemanden der 
Senden kann kein Problem.

: Bearbeitet durch User
von San L. (zwillingsfreunde)


Lesenswert?

Fabian Müller schrieb:
> Über den ADC Eingang am Atmega8 habe ich den Fader abgefragt. (Ich weiß
> das das nicht alzu genau ist. Reicht aber denkne ich aus.)

Der dürfte allemal reichen. Gehe mal davon aus, dass du den Fader von 
Hand einstellt. Bereits bei einer Auflösung von 8-Bit wären somit 255 
verschiedene Stufen erkennbar. Denke kaum dass du mit deiner hand 255 
verschiedene Schritte einstellen kannst, von demher ist das kein 
Problem.

Zu deinem Problem:
Laut deiner Beschreibung hast du genau das bereits gemacht, was du 
machen wolltest. Du versendest ein Byte von einem uC zum PC. Nun willst 
du das ganze blos in die andere Richtung machen.
Kannst mir kaum erzählen, dass du lediglich den halben UART eines uC's 
verstanden hast und somit nur fähig bist zu Senden aber nicht zum 
Empfangen?

von Fabian F. (fabiii9)


Lesenswert?

Hallo zusammen,

vielen Dank für eure Antworten !

Habe jetzt das UART-Tutorial durchgearbeitet.

Und mein Problem besteht einfach darin, wie ich den UAR so umrechnen 
kann, dass am Ende in Variable 1 der Midikanal steht, in Variable 2, Der 
Befehl und in Variable 3 der Value.

Wäre dankbar wenn mir da jemand helfen könnte.
Es wird nämlich ein so ein tolles Projekt. (Lichtmischpult)
Werde dann auch eine BAuanleitung dafür verfassen.

Code vom senden:
1
#include <avr/io.h>
2
#include <avr/io.h>
3
#define F_CPU 1000000              
4
#define BAUD 31250                
5
#include <util/setbaud.h>
6
void adc_init (void){
7
8
  ADMUX = 0xC0;
9
10
11
  ADCSRA = 0x80; 
12
13
14
  ADCSRA |= 0x05; //Vorteiler 32
15
16
17
  ADCSRA |= (1<<6); 
18
19
while(ADCSRA & (1<<6)){}; 
20
21
uint16_t ergebnis = 0;
22
23
ergebnis = ADCL;
24
ergebnis += (ADCH<<8);
25
26
}
27
28
uint16_t adc_read (uint8_t kanal){
29
30
  static uint8_t init = 0;
31
32
  if(init==0){adc_init(); init++;} 
33
34
  ADMUX &= (0xE0);
35
36
  ADMUX |= (kanal&(0x1F));
37
38
  ADCSRA |= (1<<6); 
39
40
41
42
  while(ADCSRA & (1<<6)){}; 
43
44
  uint16_t ergebnis = 0;
45
46
  ergebnis = ADCL;
47
  ergebnis += (ADCH<<8);
48
49
  return ergebnis;
50
51
}
52
53
int main(void){
54
  uint16_t schweller;
55
  uint16_t alterWert;
56
57
  uart_init();
58
  adc_init();
59
60
  alterWert = adc_read( 2 ) / 8;
61
  
62
  while( 1 )
63
   {
64
     schweller = adc_read( 2 ) / 8;
65
     if( schweller != alterWert )
66
     {
67
       alterWert = schweller;
68
69
       uart_putc(schweller);
70
     }
71
   }
72
}
73
  
74
void uart_init(void){
75
  UBRRH = UBRRH_VALUE;
76
  UBRRL = UBRRL_VALUE;
77
  
78
  #if USE_2X                 
79
  UCSRA |= (1 << U2X);
80
  #else                   
81
  UCSRA &= ~(1 << U2X);
82
  #endif
83
  UCSRB |= (1<<TXEN);              
84
  UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
85
}
86
87
void uart_putc(unsigned char c){
88
  while (!(UCSRA & (1<<UDRE))){}  
89
  UDR = c;                 
90
}
91
  
92
void Sendmidicontrol(void){
93
  uart_putc(176);          
94
  uart_putc(100);          
95
  uart_putc(100);          
96
}
Vielen Dank
Gruß
Fabi

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Fabian Müller schrieb:

> Habe jetzt das UART-Tutorial durchgearbeitet.

Sieht nicht so aus, als ob du viel davon verstanden hättest.
Und von Midi offenbar auch nicht.

> Und mein Problem besteht einfach darin, wie ich den UAR so umrechnen
> kann, dass am Ende in Variable 1 der Midikanal steht, in Variable 2, Der
> Befehl und in Variable 3 der Value.

Du musst nichts 'umrechnen'. Du musst einfach nur die Bytes, die an der 
UART ankommen, entsprechend verteilen.

Dazu benutzt du am besten den Empfang per Interrupt (siehe jedes UART 
Tutorial), zusammen mit der Kenntnis das
* im MIDI 'Befehls-byte' das Bit 7 gesetzt ist. Das gibt dir die 
Information, dass hier der nächste Befehl anfängt.
* danach nur noch Datenbytes kommen, die kein gesetztes Bit 7 haben

1
volatile uint8_t Command;
2
volatile uint8_t Byte1;
3
volatile uint8_t Byte2;
4
5
ISR( USART_RXC_vect )
6
{
7
  static uint8_t byteCounter = 0;
8
9
  uint8_t nextByte = UDR;
10
11
  if( nextByte & 0x80 ) {    // ist Bit 7 gesetzt, wenn ja dann
12
                             // ist das hier ein Kommando, in MIDI
13
                             // nennt sich das ein Statusbyte
14
    Command = nextByte;
15
    byteCounter = 0;
16
  }
17
18
  else {                     // Nope, war kein Kommando
19
                             // muss also ein Datenbyte sein
20
                             // Die meisten MIDI Datenbytes kommen
21
                             // in Pärchen, so dass nach dem Statusbyte
22
                             // noch 2 Bytes kommen.
23
    if( byteCounter == 0 )
24
      Byte1 = nextByte;
25
    else
26
      Byte2 = nextByte;
27
28
                             // nach jeweils 2 Datenbytes ist damit
29
                             // 1 Kommando abgeschlossen
30
                             // mach was damit
31
                             // Fehlt das Statusbyte, dann gilt das zuletzt
32
                             // empfangene Kommando als zu wiederholen (nur halt
33
                             // mit anderen Daten)
34
    if( byteCounter == 1 )
35
      ProcessMIDI( Command, Byte1, Byte2 );
36
37
    byteCounter = 1 - byteCounter;
38
  }
39
}

> Es wird nämlich ein so ein tolles Projekt. (Lichtmischpult)
> Werde dann auch eine BAuanleitung dafür verfassen.

Sieh lieber zu, dass du erst mal die Basics lernst. Bis du genügend 
Wissen hast um eine sinnvolle Bauanleitung zu verfassen, rinnt noch viel 
Wasser die Donau hinunter, wenn dir dieser Trivialcode (der 
zugegebenermassen nicht ganz vollständig ist) schon Schwierigkeiten 
macht.
Du brauchst niemanden mit einer möglichen Bauanleitung ködern. Das wäre 
so, wie wenn ich anbieten würde eine leicht verständliche Anleitung für 
Herzoperationen zu schreiben, nur weil ich es mit Anleitung geschafft 
habe ein Pflaster unfallfrei abzunehmen - das wird nichts.

> ich habe es mitlerweile geschafft ein Midisignal von einen Fader an den Computer 
zu senden.
Mit dem Sendecode aus deinem letzte Post?
Das wage ich zu bezweifeln.
Du sendest den Messwert per UART, das stimmt. Aber MIDI ist das noch 
lange nicht. Die Funktion Sendmidicontrol wird überhaupt nicht 
aufgerufen und selbst wenn sie aufgerufen werden würde, sendet die immer 
den gleichen Wert (100), der nichts mit dem Ergebnis vom ADC zu tun hat. 
Man kann das natürlich ändern, was für jeden Programmierer trivial ist. 
Allerdings hast du das bisher anscheinend nicht gemacht.

: Bearbeitet durch User
von Fabian F. (fabiii9)


Lesenswert?

Hallo,
erstmal vielen Dank für deine Bemühungen.
Ja, ok.

Was kannst du denn für ein Tutorial empfehlen was wirklich von null 
(oder von so "LED-blink-Wissen" :)) aufbaut??
Hab da jetzt schonmal gegoogelt auch was gefunden, aber nicht so recht 
passendes.
Such was für C.
Am liebsten wäre mir eine PDF (Soll ausdruckbar sein).

Vielen Dank
Gruß
Fabi

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.