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ß.
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
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.
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.
@ 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.
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
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.
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.
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!
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.
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
voidloop(){
2
staticinti;
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.
@ 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_tbitsLeft=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_ti;
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.
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.
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).
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.