Forum: Mikrocontroller und Digitale Elektronik MIDI Meter Bridge mit Mackie Control Protokoll


von Stefan M. (mannitb303)


Lesenswert?

Hallo,

folgende Problematik:

Habe als DAW Cubase 7, möchte gerne eine VU Meter Bridge bauen welche 
mir 8 Kanäle als Mono anzeigt. Habe nun 2x 74LS595 für 12 LEDs benutzt 
für eine Kanalspalte und ein 74LS595 für die 8 Kanäle. Habe in Cubase 
Mackie Control als Fernbediengerät ausgewählt. Im MIDI-Monitor gibt mir 
Cubase nun die Kanaldaten und die Meterdaten raus.

von Cubase:
D0 0B
D0 17
D0 23
D0 35
usw.

Erstes Byte D0=Channel Aftertouch
Zweites Byte 0B = Channel 0(1) VU-Wert B
Das untere Nibble ist der Kanal das obere der VU Wert, eigentlich ganz 
einfach.

Die Date laufen sauber durch, d.h. das 2.Byte wechselt die Kanäle durch 
(0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7 usw.) Also habe ich im Code das Byte in 
zwei Bytes geteilt (Obere und untere Nibble ausmaskiert). Die Daten für 
die Schieberegister werden aus einer Tabelle ausgelesen und nacheinander 
in die Register geschoben. KanalByte,Oberes VU Byte, unteres VU Byte, 
die Register sind kaskadiert.
Eigentlich geht auch alles soweit ausser das ein flimmern wahrnehmbar 
ist welches sich nicht ändert wenn ich weniger Kanäle im Cubase benutze. 
Das einzige was sich ändert ist die helligkeit, d.h. nehme ich nur zwei 
Kanäle leuchten die LEDs heller, nehme ich 8 Kanäle sind sie dunkler. 
Flimmern tut es aber immer gleich.

Als AVR nehme ich ein Arduino Uno, die Daten werden per SPI in die 
Register geschrieben. Ist der Arduino zu langsam??

Gruß
Stefan

von Joe F. (easylife)


Lesenswert?

Stefan M. schrieb:
> Ist der Arduino zu langsam?

Nein.
In deiner Firmware wird ein Fehler sein.

von oog (Gast)


Lesenswert?

Stefan M. schrieb:
> Habe als DAW Cubase 7, möchte gerne eine VU Meter Bridge bauen welche
> mir 8 Kanäle als Mono anzeigt. Habe nun 2x 74LS595 für 12 LEDs benutzt
> für eine Kanalspalte und ein 74LS595 für die 8 Kanäle. Habe in Cubase

Hast Du 8 x 12 LED als Matrix verschaltet? Falls ja, wie verstärkst Du 
die Ausgänge der '595?

Schaltplan wäre hilfreich, ggf. hilft Dir die Suche nach "LED-Matrix" 
weiter.

von Stefan M. (mannitb303)


Angehängte Dateien:

Lesenswert?

Hi,

so habe mal einen Schaltplan erstellt. Ist allerdings ohne Widerstände 
etc.... nur um Verständniss gedacht.

@ogg: Nein habe im Moment nur 2x12 LEDs..

Hier der Code:
1
byte commandByte;
2
byte noteByte;
3
byte vumeters[8] = {1,2,4,8,16,32,64,128}; //Kanal Ausgang Schieberegister
4
byte vumetershigh[17] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0xFF}; //High Byte da 2x8Bit Register
5
byte vumeterslow[17] =  {0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF}; //Low Byte
6
#include <SPI.h>
7
byte noteOn = 0xD0; //ChannelAftertouch
8
byte datahigh = 0;
9
byte datalow = 0; 
10
byte vudata = 4;
11
byte vudataAlt = 4;
12
byte channel =0;
13
byte channelAlt =0;
14
byte empty = 0;
15
byte vurow ;
16
17
const int slaveSelectPin = 10;
18
SPISettings settingsA(16000000, MSBFIRST, SPI_MODE0);
19
20
void setup(){
21
  Serial.begin(31250);
22
  pinMode(13,OUTPUT);
23
  digitalWrite(13,LOW);
24
  pinMode(slaveSelectPin, OUTPUT);
25
  SPI.begin();
26
  }
27
28
29
30
void loop(){
31
  checkMIDI();
32
  vurow = vumeters[channel];
33
  datahigh = vumetershigh[vudata];
34
  datalow = vumeterslow[vudata]; 
35
  shift();
36
}
37
void checkMIDI(){
38
 
39
  if (Serial.available()>2){
40
   commandByte = Serial.read();
41
42
    if (commandByte == noteOn){
43
      noteByte = Serial.read();
44
      delayMicroseconds(130);
45
      empty = Serial.read();
46
      channel = noteByte & B11110000; //Nibble maskieren
47
      channel = channel >>4; //4 x nach rechts schieben um Kanal u erhalten 
48
      vudata = noteByte & B00001111; Nibble maskieren um VU-Wert zu erhalten 
49
      Serial.write(channel);  // zum überprüfen im MIDI-Monitor
50
      Serial.write(vudata);   // ob Daten fehlen/doppelt sind
51
    }
52
53
  }
54
55
}
56
void shift(){
57
 digitalWrite(slaveSelectPin, LOW);
58
 SPI.beginTransaction(settingsA);
59
 SPI.transfer(vurow);   //Byte für letztes Schieberegister (Kanal)
60
 SPI.transfer(datahigh); // Highbyte für die letzten 4 LEDs
61
 SPI.transfer(datalow);  // Lowbyte für die ersten 8 LEDs
62
 digitalWrite(slaveSelectPin, HIGH);
63
 SPI.end();
64
}

Hoffe es ist verständlich. Bei Fragen einfach an mich wenden. :)

Gruß
Stefan

von Joe F. (easylife)


Lesenswert?

Stefan M. schrieb:
> Das einzige was sich ändert ist die helligkeit, d.h. nehme ich nur zwei
> Kanäle leuchten die LEDs heller, nehme ich 8 Kanäle sind sie dunkler.
> Flimmern tut es aber immer gleich.

Stefan M. schrieb:
> so habe mal einen Schaltplan erstellt. Ist allerdings ohne Widerstände
> etc.... nur um Verständniss gedacht.

Falsch plazierte oder falsch dimensionierte Widerstände können genau der 
Grund für das Flimmern sein.

Zeichne sie bitte ein.

Ausserdem ist die Ausführungszeit deiner Funktion checkMIDI() abhängig 
von den empfangenen Daten.
Entsprechend ändert sich auch das Timing für dein LED Multiplexing - und 
damit die LED Helligkeit...

Gehe doch lieber den einfacheren Weg, und spendiere jeder LED einen 
Schieberegister-Ausgang.

Bei 8 Kanälen à 12 LEDs kommst du dann auf insgesamt 12 Schieberegister, 
die nicht die Welt kosten.

Wenn du an der Multiplexing-Lösung festhalten willst:
Nimm einen Timer-Interrupt, um deine LED-Anzeige in immer gleichen 
Zeitabständen zu aktualisieren (Kanal für Kanal).
Weiss allerdings nicht, wie sich das mit der seriellen Kommunikation 
(MIDI) verträgt...

: Bearbeitet durch User
von Stefan M. (mannitb303)


Lesenswert?

Danke Joe,

nehme ich den Timer Interrupt für die Serielle Abfrage oder wirklich nur 
zum aktualisieren der LEDs?

Gibt es ein gutes Tut für Interrupts?


Im Moment habe ich jeweils einen 220 Ohm Widerstand an der Basis der 
Transistoren, mehr nicht.

von Joe F. (easylife)


Lesenswert?

Und noch etwas:
Um die LEDs einigermaßen hell leuchten zu lassen, benötigst du ja 
vermutlich mindestens 5mA pro LED.
Wenn du das jetzt durch das Multiplexing nur 1/8 der Zeit machst, muss 
die LED 8x heller leuchten, also mit ca. 40mA.
An bis zu 8 Pins eines Schieberegisters macht das dann 320mA.
Das ist viel zu viel für ein 74HC595. Du bräuchtest in jedem Fall 
externe Treiber.

Daher: lieber mehr Schieberegister.
Der Update-Zyklus spielt dann keine Rolle mehr und die Anforderungen an 
ein gleichmäßiges Update-Timing entfällt dann komplett.

von Joe F. (easylife)


Lesenswert?

Stefan M. schrieb:
> Im Moment habe ich jeweils einen 220 Ohm Widerstand an der Basis der
> Transistoren, mehr nicht.

Ja, das ist Mist.
An jedem Schieberegister Ausgang gehört ein LED Vorwiderstand hin, und 
der Transistor sollte auch ein PNP (nicht NPN, wie bei dir) sein.
Die zusätlichen Low-Side (Zeilen-)Treiber (hinter den Vorwiderständen) 
wären dann PNPs.

: Bearbeitet durch User
von Joe F. (easylife)


Lesenswert?

Hier ist ein Beispiel:
https://www.mikrocontroller.net/wikifiles/6/64/LED_Matrix_8x5.png

Ich würde allerdings Q1 bis Q8 durch PNP Transistoren ersetzen, und 
zwischen die Ausgänge von IC1 und den Basen der PNPs je einen 
Basiswiderstand (470R).

: Bearbeitet durch User
von Stefan M. (mannitb303)


Lesenswert?

Super viel Input, Danke. Werde mir deine Tipps zu Herzen nehmen und es 
mal testen. Wenn ich wirklich 12 Schieberegister verwenden sollte, ist 
es dann Programmiertechnisch nicht wesentlich aufwendiger, da sich ja 
dann zwei Schieberegister quasi 2 Kanäle teilen? Also 8 Ausgänge vom 
ersten Register = ersten 8 LEDs von Kanal eins, erste 4 Ausgänge vom 
zweiten Register letzte 4 LEDs von Kanal eins und letze 4 Ausgänge von 
Register zwei erste 4 LEDs von Kanal zwei, usw..
Oder bin ich falsch?

von Joe F. (easylife)


Lesenswert?

Stefan M. schrieb:
> ist
> es dann Programmiertechnisch nicht wesentlich aufwendiger, da sich ja
> dann zwei Schieberegister quasi 2 Kanäle teilen?

Das ist ein Klacks (ein bisschen Bitshifting...)

Oder du schreibst dir eine eigene transfer() funktion, die 12 statt 8 
Bit in die Shiftregister-Chain schiebt...

von Stefan M. (mannitb303)


Lesenswert?

Ok, werde ich mal ins Auge fassen.

Noch ne blöde Frage was ist der Vorteil wenn ich einen PNP Transistor 
verwende?

von Joe F. (easylife)


Lesenswert?

Stefan M. schrieb:
> Ok, werde ich mal ins Auge fassen.
>
> Noch ne blöde Frage was ist der Vorteil wenn ich einen PNP Transistor
> verwende?

Dass der Strom nur durch den Vorwiderstand begrenzt wird, und nicht 
zusätzlich noch durch den Transistor.

Du wolltest ja aber eh das Multiplexen weglassen, dann brauchst du auch 
keine Transistoren mehr ;-)
Nur mehr Vorwiderstände (an jede LED einen!)

Deine Lookup-Table erweiterst du einfach auf 16-bit (um 12-bit Werte 
unterbringen zu können).

Updaten von 2 Meter geht dann so:
1
uint16_t data_0 = ... // 12-bit wert für 1. kanal aus lookup-table holen
2
uint16_t data_1 = ... // 12-bit wert für 2. kanal aus lookup-table
3
4
// zu 24-bit zusammenbauen:
5
uint32_t data = ((uint32_t)data_1 << 12) | (uint32_t)data_0;
6
7
// 24-bit ausgeben
8
SPI.transfer((uint8_t)(data >> 16));
9
SPI.transfer((uint8_t)(data >> 8));
10
SPI.transfer((uint8_t)(data));

von Stefan M. (mannitb303)


Lesenswert?

Hmmmm,klingt logisch. Ich werde das mal für 2 Kanäe testen.

Danke

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.