Hallo, ich suche eine Möglichkeit per Arduino 256 DMX Kanäle auf einmal (also als Paket) zu senden. Ich habe einen DMX fähige Strahler der 256 LEDs besitzt die als Matrix angeordnet sind und die sich per DMX steueren lassen. (American DJ Revo 4) Ich habe schon ein paar DMX Projekte mit den allgemein bekannten Libraries aufgebaut, allerdings besitze ich leider nicht die tiefe Kenntnis, wie ich die Befehle optimieren kann. Ich möchte auf Kopfdruck verschiedene Muster auf der Martix abrufen. Ich habe versucht die Infos in ein Array zu speichern und dann abzurufen, aber das ist viel zu langsam. Jetzt suche ich Hilfe, ob mir evtl Jemand sagen kann wie ich die 256 DMX Befehle in einem Rutsch senden kann. Bin leider nicht der erfahrenste Programmierer und würde mich über Hilfe sehr freuen. Vielen Dank und Grüße
@andyK (Gast) >ich suche eine Möglichkeit per Arduino 256 DMX Kanäle auf einmal (also >als Paket) zu senden. Das sollte relativ leicht gehen. >Ich habe schon ein paar DMX Projekte mit den allgemein bekannten >Libraries aufgebaut, Dann sollte es noch leichter sein. >allerdings besitze ich leider nicht die tiefe >Kenntnis, wie ich die Befehle optimieren kann. Also eher nahezu NULL Programierkenntnisse? >Ich möchte auf Kopfdruck verschiedene Muster auf der Martix abrufen. Das ist leicht. >Ich habe versucht die Infos in ein Array zu speichern und dann >abzurufen, aber das ist viel zu langsam. Das ist ein Irrtum. Genau so macht man das. Und mit den richtigen Aufruf kann man die Daten auch problemlos und schnell senden. >Jetzt suche ich Hilfe, ob mir evtl Jemand sagen kann wie ich die 256 DMX >Befehle in einem Rutsch senden kann. Zeig doch erstmal deinen aktuellen Quelltext. Dann reden wir weiter. SIehe Netiquette.
(jetzt als Nicht-Mehr-Gast) Hallo Falk, danke für die schnelle Reaktion. Es gibt noch keinen Quelltext da ich es erst mal theoretisch abklären wollte. Ich nutze meist die SimpleDMX Library Da werden die DMX Kanäle sehr einfach angesprochen: DmxSimple.write(KANAL, WERT); Ich dachte es wäre sinnvoll mir einen Editor zu schreiben, in dem ich auf dem 16x16 Matrix Muster generieren kann und in irgendeiner Form abspechern kann. Im Grunde dachte ich an einen String aus 256 mal 1 oder 0 der dann für 1 Muster steht. Dann müsste der String wieder ausgelesen werden. Das Ganze kann natürlich auch in ein Array geladen werden - Ich nutze einen Arduino Mega, damit sollte es vom Speicher her kein Problem sein. Ich dachte nur, man könnte den binären String irgendwie umwandeln um Speicher zu sparen und dann wieder zurückwandeln zum auslesen. Ich habe schon ein wenig Programmierkenntnisse - aber ich lerne noch und passe Beispiele so an daß es irgendwie funktioniert. Es gibt sicher Leute die schöneren und effektiveren Code schreiben. Ich hatte das mit dem Array mal versucht und über eine Schleife die 256 Werte ausgelesen und per Befehl DmxSimple.write(KANAL, WERT); an die DMX Lampe gesendet - war sehr langsam was sich bei einem Wechsel der Muster bemerkbar gemacht hat. Also wenn dir etwas einfällt wie man die 256 Werte schneller sendet, würde ich mich über Vorschläge oder Beispiele sehr freuen. Vielen Dank und Gruß.
:
Bearbeitet durch User
Wenn du das als String sendest brauchst 256 Byte für dein Muster , wenn du das als 32 x uint8 sendest brauchst du nur 32 Bytes. Zum senden vom PC kannst du da HTerm nutzen. Gruß JackFrost
:
Bearbeitet durch User
Und genau hören bei mir leider die Fähigkeiten auf. Nehmen wir mal an ich würde ein Muster binär speichern: 0000111100001111 0000111100001111 0000111100001111 0000111100001111 0000111100001111 0000111100001111 0000111100001111 0000111100001111 0000111100001111 0000111100001111 0000111100001111 0000111100001111 0000111100001111 0000111100001111 0000111100001111 0000111100001111 256 Werte (16 x 16): 000011110000111100001111000011110000111100001111000011110000111100001111 000011110000111100001111000011110000111100001111000011110000111100001111 000011110000111100001111000011110000111100001111000011110000111100001111 0000111100001111000011110000111100001111 Wie kann ich das Platzsparend speichern und wieder schnell auslesen? mit einer Schleife? Im Grunde würde ich gerne 20-40 Muster speichern.
:
Bearbeitet durch User
Bastian W. schrieb: > Zum senden vom PC kannst du da HTerm nutzen. Ich fürchte eher nicht, jedes Datenpaket auf dem DMX-Bus fängt mit einem Break an, das man mit normalen Terminalprogrammen nicht so einfach erzeugen kann. Ausserdem muss ständig ein neues Paket kommen, sonst vermuten die Empfänger einen Kabelbruch und gehen in einen Notlauf. Man müsste mal den Quelltext von
1 | DmxSimple.write() |
durchstöbern. Der legt das eine Byte vermutlich in einem Array ab, welches er dann im Interrupt ausgibt.
Beine 256 Bits sind ja 32 Byte. Als String sind es 256 Byt. Wenn es kleiner als 32 Bytes sein soll musst du komprimieren aber für das senden über DMX wieder entpacken. Zum senden der 32 Bytes als 256 Kanäle musst du nur eine For-Schleife nutzen in der dann das entsprechende Bit maskiert wird und wenn es 1 ist wird eine 1 gesendet sonst eine 0. Gruß JackFrost
Bastian W. schrieb: > Wenn du das als String sendest brauchst 256 Byte für dein Muster , wenn > du das als 32 x uint8 sendest brauchst du nur 32 Bytes. > > Zum senden vom PC kannst du da HTerm nutzen. > > Gruß JackFrost Ich denke nicht. Der Wert für einen DMX Kanal ist immer ein Byte. Auf dem Bus hast du also bei normalerweise 512 DMX Kanälen also 512 Byte. Sendest du nur die ersten 256 Byte, was durchaus möglich ist, dann benötigst du auch 256 Byte. Du kannst keine 32x uint8 senden.
Ich bin vom ersten Post ausgegangen das es in seiner Matrix nur an und aus gibt. Gruß JackFrost
@ Andy Koa (andykoa) >Es gibt noch keinen Quelltext da ich es erst mal theoretisch abklären >wollte. Dann hast du uns Märchen erzählt! "Ich habe schon ein paar DMX Projekte mit den allgemein bekannten Libraries aufgebaut," Man könnte es auch neudeutsch Fake News nennen! >Ich nutze meist die SimpleDMX Library Link? >Da werden die DMX Kanäle sehr einfach angesprochen: >DmxSimple.write(KANAL, WERT); Da gibt es sicher andere Funktion, um die Daten dort reinzuschreiben. Im Extremfall greift man direkt auf die Membervariablen zu. Oder man schreibt eine einfache, neue Methode, um Arrays zu kopieren. >Ich dachte es wäre sinnvoll mir einen Editor zu schreiben, Laß das erstmal. Vorerst reicht eine manuelle Definiton deiner Daten per Hand. Ggf. nimmt man eine Exceltabelle oder sogar old school Papier! >Ich dachte nur, man könnte den binären String irgendwie umwandeln um >Speicher zu sparen und dann wieder zurückwandeln zum auslesen. Was willst du denn bei 256 Bytes für 256 DMX-Kanäle sparen? >Ich habe schon ein wenig Programmierkenntnisse - aber ich lerne noch und >passe Beispiele so an daß es irgendwie funktioniert. Hmmm. >Es gibt sicher Leute die schöneren und effektiveren Code schreiben. Dann schreib erstmal welchen! Den kann man dann verbessern! >Ich hatte das mit dem Array mal versucht und über eine Schleife die 256 >Werte ausgelesen und per Befehl DmxSimple.write(KANAL, WERT); an die >DMX Lampe gesendet - war sehr langsam was sich bei einem Wechsel der >Muster bemerkbar gemacht hat. Kann sein, weil du erstens 256 mal die Funktion aufrufen mußt und diese wahrscheinlich ziemlich aufgeblasen und langsam ist, wie viele andere Arduino-Funktionen auch. Das ist aber ein lösbares Problem.
@Andy Koa (andykoa) >Nehmen wir mal an ich würde ein Muster binär speichern: >0000111100001111 >0000111100001111 >0000111100001111 >0000111100001111 >0000111100001111 >0000111100001111 >0000111100001111 >0000111100001111 >0000111100001111 >0000111100001111 >0000111100001111 >0000111100001111 >0000111100001111 >0000111100001111 >0000111100001111 >0000111100001111 >256 Werte (16 x 16): Bit "Ich habe einen DMX fähige Strahler der 256 LEDs besitzt die als Matrix angeordnet sind und die sich per DMX steueren lassen. (American DJ Revo 4)" Wie werden denn die einzelnen LEDs dieses Strahlers adressiert? Eine LED/DMX-Kanal (0-255, dimmbar) oder 8 LEDs/DMX-Kanal (nur ein/aus pro LED) Das ist nämlich die Frage. >Wie kann ich das Platzsparend speichern und wieder schnell auslesen? >mit einer Schleife? Fürs Erste mußt du keinen Platz sparen. Pack die Muster einfach direkt in den Flashspeicher und lies sie aus. Der Mega hat mehr als genug davon. Wie das geht, steht in der Arduino-Referenz.
Wie Du die Daten senden musst, bestimmt der Empfänger. Wenn Du den später auch noch baust und jede Lampe nur an oder aus kennt, kannst Du natürlich die Werte bitkodieren und hast dann die Info für 8 Lampen in einem Byte. Willst Du die Lampen dimmen, könntest Du 4 Helligkeitsstufen für 4 Lampen in ein Byte packen oder 16 Helligkeitsstufen für 2 Lampen. Normalerweise hat man 256 Helligkeitsstufen in einem Byte pro Lampe. Aber auch 65536 Helligkeitsstufen in zwei Byte pro Lampe sollen schon gesehen worden sein. Jedenfalls ist bei 512 Bytes Nutzdaten pro Datenblock Schicht am Schacht bei DMX512. Es steht Dir natürlich frei mehrere Busse zu nutzen. Wenn Du irgendwo den Begriff "universe" liest, dann werden da mehrere Busse genutzt und durchnumeriert. Übrigens, wenn Du die vollen 512 Nutzdatenbytes ausnutzt, kommen die Datenblöcke mit ungefähr 40 Hz, schneller blinkt da also nix.
Ich werde mal das Programm neu schreiben und Posten. Ist sicherlich einfacher. Auf jeden Fall schon mal Danke für die Tipps und Infos.
fop schrieb: [..] > Übrigens, wenn Du die vollen 512 Nutzdatenbytes ausnutzt, kommen die > Datenblöcke mit ungefähr 40 Hz, schneller blinkt da also nix. Ja in Sachen Speed ist DMX schon manch mal eine Spaßbremse, besonders wenn man bei LEDs ein sauberers Fading hinlegen will. Aber es steht einem frei, DMX auch mit 1Mb oder mehr statt mit 250kb zur fahren, wenn man Sender und Empfänger selber baut. Ist dann zwar nicht mehr normkonform aber 4x schneller. Gruß Jürgen
:
Bearbeitet durch User
American DJ Revo 4 ist ja nicht gerade das HighEnd DMX Endgerät. Kann in der Tat 256 Kanäle je 26 x R G B / W Dürfte dann wohl auf jeweils 8 Bit PWM umgesetzt werden. Fraglich ist ob der dort eingetzte Prozessor auch in der Lage ist, innerhalb eines DMX Frame (ca. 20 ms) alle Werte umzurechen und auch synchron auszugeben. Das Teile wird ja auch lediglich als Flower Effekt beworben. und die einzelnen R/G/B/W Punkte liegen auch nicht übereinander, also 256 Punkte mit unterschiedlicher Helligkeit aber kein Mischfarben.
@Mikki Das mit den Einschränklungen Revo ist mir absolut bewusst. Deswegen versuche ich ja auch etwas mehr herauszukitzeln. Leider kann er nur eine handvoll Muster auf Knopfduck darstellen. Das mit der internen Verarbeitungsgeschwindigkeit des Revos ist natürlich eine große Unbekannte.
Hier ist mein kleines Programm was momentan 4 Muster (das erste ist leer, also alle Leds aus) anzeigt. Nur leider in einer sehr inakzeptablen Geschwindigkeit - man kann den LED fast zuschauen wie sie nacheinander aufleuchten.
1 | #include <DmxSimple.h> |
2 | #include <MIDI.h> |
3 | |
4 | //MIDI_CREATE_DEFAULT_INSTANCE();
|
5 | MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI); |
6 | |
7 | byte incomingByte; |
8 | byte note; |
9 | byte velocity; |
10 | byte midichannel; |
11 | |
12 | int revo_array[] = { |
13 | 124,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
14 | 125,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, |
15 | 126,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1, |
16 | 127,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0 |
17 | };
|
18 | |
19 | int revo_array_size = 1028; |
20 | |
21 | void setup() { |
22 | |
23 | // MIDI SETUP
|
24 | |
25 | MIDI.setHandleNoteOn(handleNoteOn); // Put only the name of the function |
26 | MIDI.setHandleNoteOff(handleNoteOff); |
27 | MIDI.begin(MIDI_CHANNEL_OMNI); |
28 | |
29 | // DMX SETUP
|
30 | DmxSimple.usePin(3); |
31 | DmxSimple.maxChannel(512); |
32 | |
33 | }
|
34 | |
35 | void loop () { |
36 | MIDI.read(); |
37 | |
38 | }
|
39 | |
40 | void handleNoteOn(byte channel, byte note, byte velocity) |
41 | {
|
42 | // NOTE ON
|
43 | // combine midi channel and midi note number
|
44 | int channelnote = (channel*100)+note; |
45 | |
46 | // search for value in array
|
47 | |
48 | for (int i=0; i<=revo_array_size; i=i+257) { |
49 | |
50 | if (channelnote == revo_array[i]) { |
51 | |
52 | // DMX OUTPUT
|
53 | |
54 | for(int d=1;d<=256;d++) { |
55 | |
56 | DmxSimple.write(d, (revo_array[i+d])*255); |
57 | |
58 | }
|
59 | |
60 | break; |
61 | |
62 | }
|
63 | |
64 | }
|
65 | |
66 | }
|
67 | |
68 | void handleNoteOff(byte channel, byte pitch, byte velocity) |
69 | {
|
70 | // NOTE OFF
|
71 | }
|
Zur Erklärung: Der erste Eintrag 124 ist die Kombination aus MIDI Kanal und MIDI Note - in diesem Fall Kanal 1 und Note 24 - Wenn diese Kombination im Array gefunden wird, werden die folgenden 256 Werte per DMX an die Lampe geschickt. Der Suchpointer macht natürlich 257er Sprünge. Ich hoffe das ist alles so einigermaßen verständlich. würde mich freuen wenn hier Jemand eine Idee hätte wie das effizienter geht. Evtl. ganz ohne DMX Library sondern direkt.
@ Andy Koa (andykoa) >Hier ist mein kleines Programm was momentan 4 Muster (das erste ist >leer, also alle Leds aus) anzeigt. Und warum hat dein Array dann nur eine Dimension? int revo_array[4][256] wäre da deutlich sinnvoller. > Nur leider in einer sehr >inakzeptablen Geschwindigkeit - man kann den LED fast zuschauen wie sie >nacheinander aufleuchten. Tja, du bist auch so ein Künstler, der das Problem scheibchenweise präsentiert. Denn von MIDI war bisher noch keine Rede! >#include <DmxSimple.h> Ich fragte dich nach einem Link für deine DMX-Bibliothek. Naja. https://github.com/PaulStoffregen/DmxSimple Und wenn man da mal in den Quelltext schaut, erschaudert man! /** Transmit a complete DMX byte * We have no serial port for DMX, so everything is timed using an exact * number of instruction cycles. Die machen das alles in Software! So ein Mist! > MIDI.setHandleNoteOn(handleNoteOn); // Put only the name of the function > MIDI.setHandleNoteOff(handleNoteOff); > MIDI.begin(MIDI_CHANNEL_OMNI); Auch hier muss man fragen, wie das MIDI wirklich gemacht ist? Per Software wäre auch hier ein ziemlicher CPU-Killer. // DMX SETUP > DmxSimple.usePin(3); > DmxSimple.maxChannel(512); Warum 512 Kanäle, wenn du nur 256 nutzt? >} >void loop () { >MIDI.read(); > >} Wo werden hier die verschiedenen Muster angezeigt? Auch so, über die im Midi verstecken Funktionsaufrufe. >Der erste Eintrag 124 ist die Kombination aus MIDI Kanal und MIDI Note - >in diesem Fall Kanal 1 und Note 24 - Wenn diese Kombination im Array >gefunden wird, werden die folgenden 256 Werte per DMX an die Lampe >geschickt. Der Suchpointer macht natürlich 257er Sprünge. Das halte ich für nicht sonderlich gescheit. Naja, es fehlen halt Grundlagen. Das sollte man trennen. Ein 2D Array für die Muster, ein 1D Array für die Midi-Noten. Das ist übersichtlicher. Man kann es auch mit einem Struct machen, das wäre professioneller, aber für dich im Moment wahrscheinlich zuviel Ablenkung vom eigentlichen Problem. >würde mich freuen wenn hier Jemand eine Idee hätte wie das effizienter >geht. Evtl. ganz ohne DMX Library sondern direkt. Ja, aber dazu fehlt die viel zuviel Wissen.
:
Bearbeitet durch User
Also das mit dem Ausrechnen und ausgeben lassen wir mal.. Denn selbst mit einen ARM ist das eine Spannende und Rechenintensive Aufgabe. Vor allem dann wenn alle 44ms der nächste Frame ausgegeben werden muss. Was geht ist die Matrix und die Effekte mit einen externen Programm z.Bsp jinx zu erzeugen. Jinx kann die Ausgabe speichern und das Format ist recht simpel. Das File packt man auf eine SD. Lesen und Ausgeben -> fertig.
Das mit dem MIDI ist absolut unproblematisch und funktioniert so wie es soll. Ich habe ein weiteres Projekt in dem ich ein MIDI 2 DMX Shield entworfen und gebaut habe. Da werden Konfigurationsvariablen von einer SD Karte gelesen und RGB LED Strahler angesteuert - das funktioniert alles perfekt. > DmxSimple.usePin(3); > DmxSimple.maxChannel(512); ich habe den Wert auf 256 reduziert und es läuft auch etwas schneller. > int revo_array[4][256] > Ein 2D Array für die Muster, ein 1D > Array für die Midi-Noten. Das ist übersichtlicher. Man kann es auch mit > einem Struct machen, das wäre professioneller, aber für dich im Moment > wahrscheinlich zuviel Ablenkung vom eigentlichen Problem. könnte ich hier einen Tipp bekommen? Die Frage ist ja hier dann wirklich, ob es eine Verbesserung der Geschwindigkeit bewirkt. Danke auf jeden Fall für die Unterstützung!
@Marco Jinx nutze ich für meine RGB Matrixen sehr erfolreich. Ich suche eher eine kleine und kompakte Möglichkeit ohne PC und Windows(Jinx). Aber Danke :)
Andy K. schrieb: > könnte ich hier einen Tipp bekommen? > > Die Frage ist ja hier dann wirklich, ob es eine Verbesserung der > Geschwindigkeit bewirkt. > > Danke auf jeden Fall für die Unterstützung! Du hast ein uint16 Array dafür das die meisten deiner Werte nur 0 oder 1 bzw 255 sind. Du kannst die Noten in eine uint16 array packen und dann in dem kleinen Array suchen. Der Index ist der erste Index in deinem Musterarray. Zudem spar dir die unötige Multiplikation
1 | DmxSimple.write(d, (revo_array[i+d])*255); |
indem du direkt im Array 0 bzw 255 verwendest. Gruß JackFrost
@Andy Koa (andykoa) >> Ein 2D Array für die Muster, ein 1D >> Array für die Midi-Noten. Das ist übersichtlicher. Man kann es auch mit >> einem Struct machen, das wäre professioneller, aber für dich im Moment >> wahrscheinlich zuviel Ablenkung vom eigentlichen Problem. >könnte ich hier einen Tipp bekommen? >Die Frage ist ja hier dann wirklich, ob es eine Verbesserung der >Geschwindigkeit bewirkt. Kann sein, muss nicht. https://www.arduino.cc/en/Reference/PROGMEM Siehe Anhang.
Funktioniert leider nicht.
Bin mir nicht sicher ob
> memcpy_P ((void*)dmxBuffer, dmx_data[i], 256);
von der DMX Simple Library verstanden wird.
Scheint aber genau an dieser Zeile zu liegen, dass nichts passiert bzw
nichts ausgegeben wird.
Danke schon mal für die Mühe!
:
Bearbeitet durch User
Korrektur! Es funktioniert. ich habe die im Array die Werte auf 256 geändert anstelle der 1. Es kommt mir so vor als wäre es einen Tick schneller - kann mich aber auch irren. Den erhofften Geschwindigkeitszuwachs hat es leider nicht bewirkt. Danke trotzdem!
Hast die Daten auf zwei Arrays gesplittet? 256 ist zu hoch, über die If Abfrage wird das auf 255 gesenkt kostet aber wieder einen unnötigen Takt. Ein uint16 ( int ) Array kostet auch unnötig Takte da der Zugriff über zweimal 8 Bit erfolgt. Gruß JackFrost
@ Andy Koa (andykoa) >ich habe die im Array die Werte auf 256 geändert anstelle der 1. Das geht gar nicht, denn das sind 8 Bit Daten, die können nur 0-255 sein. >Es kommt mir so vor als wäre es einen Tick schneller - kann mich aber >auch irren. Den erhofften Geschwindigkeitszuwachs hat es leider nicht >bewirkt. Da sollte man vor allem erstmal testen, WO die niedrige Geschwindigkeit herkommt. ALso ohne Midi, nur mit DMX und dem Reinkopieren.
Das Problem dürfte das DmxSimple.write(KANAL, WERT); sein. DMX kennt keine Adressen, d.h. es werden jedesmal alle 256 Byte gesendet, auch wenn nur eins geändert wurde. Du sendest in der Loop also nicht 256 Bytes sondern 256*256=65536 Byte. Das kann dauern. Sende einfach nach dem Start alle 256 Byte aus dem Array, dauert ~10ms bei 250kBaud.
@peda Hört sich interessant an, aber ich habe keine Ahnung wie ich das umsetzen kann. Könnte ich evtl ein Beispiel haben wie das machbar wäre? Danke!
Peter D. schrieb: > Das Problem dürfte das DmxSimple.write(KANAL, WERT); sein. > DMX kennt keine Adressen, d.h. es werden jedesmal alle 256 Byte > gesendet, auch wenn nur eins geändert wurde. > Du sendest in der Loop also nicht 256 Bytes sondern 256*256=65536 Byte. > Das kann dauern. > > Sende einfach nach dem Start alle 256 Byte aus dem Array, dauert ~10ms > bei 250kBaud. Laut dem Github Code wird mit dem DMX.write die Werte des Kanals nur in den DMX Puffer geschrieben. Der Puffer wird per Timer ISR dauernd gesendet. Die Frage ist wie viel CPU Zeit gibt es noch für die Main. Mit den ganzen 16 Bit Zugriffen kostet das halt zusätzlich noch unnötige Zeit. Gruß JackFrost
@Peter Dannegger (peda) >Das Problem dürfte das DmxSimple.write(KANAL, WERT); sein. Jain. Es ist zwar eine nicht ganz so kurze Funktion, aber das hält sich in Grenzen. >DMX kennt keine Adressen, d.h. es werden jedesmal alle 256 Byte >gesendet, auch wenn nur eins geändert wurde. Nein. >Du sendest in der Loop also nicht 256 Bytes sondern 256*256=65536 Byte. >Das kann dauern. Unsinn! Er kopiert 256 Bytes aus seinem Array in das interne DMX-Array. Und in meiner Version sogar per memcpy_P. Das dauert nur ein paar Dutzend us. >Sende einfach nach dem Start alle 256 Byte aus dem Array, dauert ~10ms >bei 250kBaud. Das macht das Programm schon längst. Ich vermute eher, daß die DMX-Lampe recht lahmarschig ist und viele DMX-Frames braucht, um die neuen Daten intern zu verarbeiten. Das kann man leicht prüfen.
@Andy Koa (andykoa) >@peda >Hört sich interessant an, Ist aber Unsinn. >umsetzen kann. Könnte ich evtl ein Beispiel haben wie das machbar wäre? Ergänze mal dein neues Programm von mir. In Setup() stellst du ein IO-Pin auf Ausgang, dort kommt eine Test-LED ran, aber bitte mit Vorwiderstand! #define TEST_LED 7 // nutze IO 7 als Ausgang für die Test-LED pinMode(TEST_LED, OUTPUT); Loop() wird dann so gemacht.
1 | void loop () { |
2 | static int i; |
3 | |
4 | digitalWrite(TEST_LED, HIGH); |
5 | memcpy_P ((void*)dmxBuffer, dmx_data[i], 256); |
6 | i++; |
7 | if (i>3) i=0; |
8 | delay(10); |
9 | digitalWrite(TEST_LED, LOW); |
10 | delay(1000); |
11 | }
|
Damit wird zum Beginn der Kopieraktion die LED angeschaltet und danach wieder ausgeschaltet. Damit sieht man, wann der Kopiervorgang beginnt und wann der DMX-Strahler reagiert. Die delay(10) sind drin, damit der Lichtblitz nicht zu kurz wird. Dieser Test schaltet im 1s Rhythmus die Muster um. Damit ist auch MIDI als mögliche Quelle für Langsamkeit ausgeschlossen.
Ich hab mal versucht, das CPP zu verstehen. Da steht was von T2 Interrupt alle 64*510 Zyklen, das sind nur 2ms [16MHz]. Benötigt werden aber für 256 Byte ~10ms, d.h. die Mainloop wird massiv ausgebremst (alle 10ms wird nur ein Befehl ausgeführt). Die Interruptperiode sollte auf mindestens 20ms verlängert werden.
Der Code ist totaler Quark. Die Berechnung des Frames muss in der Mark des DMX erfolgen diese könnte man bis 1s strecken. Dann geht aber die Framerate stark zurück. Da kein DMA im Spiel ist wird die Main nicht ausgeführt wenn die Übertragung läuft.
Wenn man eine der 4 UARTs benutzt, könnte man im Hintergrund mit maximaler Rate senden, ohne das Main zu bremsen (2 Byte je Interrupt). 250kBaud mit SW-UART ist ziemlich suboptimal.
Es kommt darauf an wie man die ISR gestaltet. Man kann ja nach jedem byte +start+2xstop die ISR auslösen. Wenn man das intelligent macht bleibt auch genug Rechenzeit übrig. Ich habe das sogar mit RDM und einen AVR realisiert. Illusion ist es aber Frames online zu berechnen. Bis auf einfach Muster geht da nicht viel.
@Peter Dannegger (peda) >Ich hab mal versucht, das CPP zu verstehen. Da steht was von T2 >Interrupt alle 64*510 Zyklen, das sind nur 2ms [16MHz]. Ja. >Benötigt werden aber für 256 Byte ~10ms, Nein, denn er sendet pro ISR nur einen Teil der DMX-Daten. Ist ein wenig verquer. >Die Interruptperiode sollte auf mindestens 20ms verlängert werden. Nicht nötig.
(88+8+44+512*44) = 22668 us Zwischen den Channels bleiben 44µS ob die reichen? Also in Assembler mit gewissen Umständen bekommt man das irgend wie hin aber bestimmt keine Plasma Effekte ;) . In der Theorie würde ich immer um ein Channel Versatz rechnen, sofort wenn dieser übertragen wurde wird der neue Wert ausgerechnet und in den Buffer geschrieben. Einen Zeiten Buffer braucht man nicht. Der Zugriff ist beim AVR und ohne DMA Atomar. Wenn man länger braucht verschiebt sich das in der MARK Time die bis zu 1sec lang sein darf. Auf 44,1HZ wird man mit einen AVR nicht kommen aber wenn man 30HZ erreicht ist doch das schon was tolles. Das mit der SD Karte lesen klappt auch nur mit einen ARM da der AVR mit der FAT schon reichlich zu hätte.
:
Bearbeitet durch User
@ Marco H. (damarco) >(88+8+44+512*44) = 22668 us Zwischen den Channels bleiben 44µS ob die >reichen? Das weißt du doch gar nicht! Schau dir den Quelltext an!
1 | #define BITS_PER_TIMER_TICK (F_CPU / 31372)
|
2 | |
3 | ...
|
4 | |
5 | |
6 | ISR(ISR_NAME,ISR_NOBLOCK) { |
7 | |
8 | // Prevent this interrupt running recursively
|
9 | TIMER2_INTERRUPT_DISABLE(); |
10 | |
11 | uint16_t bitsLeft = BITS_PER_TIMER_TICK; // DMX Bit periods per timer tick |
12 | bitsLeft >>=2; // 25% CPU usage |
Er nutzt hier BEWUßT nur 25% der CPU-Zeit für die DMX-Generierung!
1 | while (1) { |
2 | if (dmxState == 0) { |
3 | // Next thing to send is reset pulse and start code
|
4 | // which takes 35 bit periods
|
5 | uint8_t i; |
6 | if (bitsLeft < 35) break; |
7 | bitsLeft-=35; |
8 | *dmxPort &= ~dmxBit; |
9 | for (i=0; i<11; i++) delayMicroseconds(8); |
10 | *dmxPort |= dmxBit; |
11 | delayMicroseconds(12); |
12 | dmxSendByte(0); |
1 | } else { |
2 | // Now send a channel which takes 11 bit periods
|
3 | if (bitsLeft < 11) break; |
4 | bitsLeft-=11; |
5 | dmxSendByte(dmxBuffer[dmxState-1]); |
6 | }
|
Er sendet hier die DMX-Daten per SOFT-UART. Aber eben nur soviele, wie es 25% der Bitzeiten / ISR-Aufruf braucht. Das bedeutdet allerdings im Umkehrschluß, daß er nur 1/4 der maximalen Framerate von DMX schafft. Bei 256 Kanälen sind das ~ 80 Hz, diese Software schafft nur 20Hz. >In der Theorie würde ich immer um ein Channel Versatz rechnen, sofort >wenn dieser übertragen wurde wird der neue Wert ausgerechnet und in den >Buffer geschrieben. Da muss gar nichts gerechnet werden. Der Op muss nur nacheinander die vorberechneten muster ausgeben, fertig. >sich das in der MARK Time die bis zu 1sec lang sein darf. Auf 44,1HZ >wird man mit einen AVR nicht kommen Woher weißt du das? Hast du das schon mal gemacht? >Das mit der SD Karte lesen klappt auch nur mit einen ARM da der AVR mit >der FAT schon reichlich zu hätte. Unsinn! Ich hab vor Jahren einen DMX-Rekorder mit einem ATmega64 gebaut, der hat bei voller Bandbreite 512 Kanäle/44 Hz von/nach SD-Karte gelesen und geschrieben. Mittlere CPU-Last ca. 30% bei 16 MHz CPU-Takt.
:
Bearbeitet durch User
Ja habe ich allerdings nicht mit einen AVR ;) Auch die FAT habe ich nicht genutzt sondern die SD selbst organisiert. Da schnell und die Daten brauchte auch kein Schwein zum lesen. Wenn es doch so einfach ist warum nicht den Weg gehen den ich oben beschrieben habe? Einfach die Animationen als File einlesen und ausgeben.
:
Bearbeitet durch User
44,1 Hz (22 ms) Refresh selbst bei 2 aktiven UART DMX Output, da langweilt sich ein 16 MHz ATmega AVR.
Es ging ja darum Animationen live zu berechnen und auszugeben. Da wird es schon spannend.
Laut dem TO geht es darum fertige Muster aus einem Array an den Strahler zu senden. Die Musterauswahl erfolgt über MIDI Noten. Gruß JackFrost
Vielen Dank für die Vorschläge. Ich bin schwer begeistert wie viele Leute hier das Thema diskutieren und auch tiefe Kenntnisse auch beim DMX Protokol haben - leider ist es für mich teilweise schwer verständlich - aber dann lerne ich ja auc noch was dazu :) @falk Ich glaube nicht daß MIDI das Problem ist, aber ich teste das Programm heute Abend man wenn ich ohne MIDI direkt die Muster aufrufe. Es ist nicht so, daß man das Programm mit der momentanen Geschwindigkeit nicht nutzen könnte. Beim Umschalten der Muster wird es fast nicht deutlich, aber beim Auschalten aller LEDs - 256* den Wert 0 senden - nach einem Muster macht es erst deutlich. Vielleicht wird mein Problem etwas deutlicher wenn ich ein kleines Video mache.
@Andy Koa (andykoa) >Es ist nicht so, daß man das Programm mit der momentanen Geschwindigkeit >nicht nutzen könnte. Beim Umschalten der Muster wird es fast nicht >deutlich, aber beim Auschalten aller LEDs - 256* den Wert 0 senden - >nach einem Muster macht es erst deutlich. Mein Gott, wird doch mal KONKRET! Wie lange dauert es, bis ein Muster von dem Leermuster gelöscht wird? 1s? 100ms? >Vielleicht wird mein Problem etwas deutlicher wenn ich ein kleines Video >mache. Möglicherweise.
Wie gesagt, mit einer der HW-UARTs könnte man im Hintergrund den Puffer mit der maximalen Refreshrate ausgeben lassen ohne merkbare CPU-Last, d.h. 11,44ms für 256 Byte. Für das Break stellt man die Baudrate auf 1/3 um und sendet 0x00 (9*3 = 27 Bitzeiten).
Wenn es unglücklich läuft muss man 256x22ms rechnen So lange braucht es bis wenn im unglücklichsten Moment nur ein Wert pro Frame geändert wird.
Marco H. schrieb: > Wenn es unglücklich läuft muss man 256x22ms rechnen So lange braucht es > bis wenn im unglücklichsten Moment nur ein Wert pro Frame geändert wird. Danach hört es sich fast an.
@Marco H. (damarco) >Wenn es unglücklich läuft muss man 256x22ms rechnen So lange braucht es >bis wenn im unglücklichsten Moment nur ein Wert pro Frame geändert wird. Das wird es aber nicht! Zumindest nicht in DIESEM Sender! Und wenn es der Empfänger so macht, ist er Schrott! Wobei, im DMX-Bereich scheint es davon reichlich zu geben. Beitrag "Re: DMX Steuerung 24 Kanal" Dort wurde eine klapprige China-Steuerung mit DREI CPUs durch EINEN ATmega644@20MHz ersetzt.
Der Emfänger hat er weniger damit zu tun, sondern der Sender = Controller. Der muss beim fading die Framezeit mit berücksichtigen und natürlich auch den Zeitpunkt wann Daten in den Buffer geschrieben werden. Die Funktion die er da benutzt schreibt plump in den Buffer und wenn er pech hat ist der Channel gerade raus und er muss auf den nächsten Frame warten. Channel++ erzeugt kein Fade jedenfalls nicht wenn noch was anderes nebenbei läuft ;) Es entsteht er zufällig. Der Weg etwas plump zu kopieren geht in die Hose.
:
Bearbeitet durch User
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.