Aller Anfang ist schwer. -> DMX

  • So Feaky,


    den eigentlichen Kern hat Pesi jetzt recht hübsch gemacht, ein paar PWMs kriegst du sicher auch hin, wie man einen MAX485 anschließt, findest du unter anderem auf meiner Homepage, also los! Wir wollen Ergebnisse sehen.


    Schön das du dir so viele sorgen um mich machst :thumbup:


    Hab gestern meine Lieferung von reichelt bekommen, kann allso die Tage los legen.


    Hab mom Leider nicht viel Zeit muss noch andere Sachen weiter/fertig machen. Denke morgen, oder am Montag werde ich mal einen Test DMX, Empfänger zusammen löten( den von Pesi), denn worum es mir hier geht ist, ich will erstmal gucken, wie es aussehen soll wenn es geht :D und wenn das Ding dann läuft kann ich DMX Controll auprobieren. Denn ich muss mir ja für meine Lampen eine eigenen DDF schreiben, sehe da zwar keine Schwierigkeiten( :rolleyes: ), doch dauert halt alles. Da ich den DMX Sender erst so am 6-10 Mai bekomme, wird sich das alles Leider noch etwas hin ziehen, bis ich die ersten richtigen test durch führen kann.


    Ich werde, so wie es aussieht alle 512 Kanäle buffern lassen, da ich eh genug ram im Atmega32 zurverfügung habe, und dadurch die ISR ja wie schon besprochen kürzer angesprungen wird. Ich werde dafür deinen Code benutzen.


    Ich baue es ja für meine Zimmer beleuchtung, und da, ( hab zwar keine ahnung, von takt zeiten und wie lange ein command dauert ,...) aber da ist schon was zu tun für den controller :D Hab nämlich noch nen LCD, Sensoren, daran hängen, die auch noch eingelesen/ mit daten bestückt werden wollen. Und noch so neben bei soll der Fader/Strobo/Farbe angezeigt werden :whistling: :P Bin ja schon gespannt wie ein schieß hund ob das geht, so wie ich mir das vorstelle.


    Genug des geschwaffels, ich poste euch dann wenn ich den Empfänger fertig habe.
    Werde auch nochmal gucken, ob ich den DMX Sender nicht schon früher bekommen kann.


    MfG

  • guenter


    also ich habe das nun mit Deinem Code auf einem Mega8 getestet da es auf einem Mega644p nicht funktioniert hat. Auf dem Mega8 ging es, nur auf einem Mega644p geht es nicht. Der DMX Empfang funktioniert da nur sehr selten mal für paar Sekunden nach einem Reset und dann hängt sich der µC auf. In der kurzen Zeit wo der Empfang geht flackern die LEDs auch komisch in der Gegend rum.


    Ich habe schon das:
    "If Ucsra.fe = 1 Then"


    gegen das ersrtzt:
    "If Ucsr0a.fe0 = 1 Then"


    Meinst Du könntest Dir das mal anschauen?


    Gruß, Benny.

  • Ich weiß nicht wie das in Bascom läuft, in C ist es auf jeden Fall so, dass Arrays immer im Block stehen, sodass er auf die Adresse des ersten Eintrags. D.h. er braucht bei jeder Belegung der Variable noch zusätzlich eine Hardware-Addition. Die sollte denke ich in 1 oder 2 Takten über die Bühne gehen. In der Theorie ist es also effektiver dafür einzelne Variablen zu nehmen.

    Die fragliche Stelle (da, wo Variablen statt Zahlen stehen) *sind* ja einzelne Variablen, nämlich DMX_Start und DMX_End... ;)


    EDIT:

    Generell habe ich aber gelesen, dass Arrays und Mikrocontroller eigentlich zwei Tiere sind, die man nicht in einen Käfig lassen sollte.

    Hm, naja, aber wenn das so läuft wie von Dir beschrieben, dann ist das ja genau so, wie man das in Assembler auch macht: nen Pointer mit der Startadresse des Arrays/RAM-Bereich laden, und dann die Nummer des Eintrags aufaddieren - anders geht das ja gar nicht... also zumindest in C sollte dann bei einem Zugriff auf ein Array so ziemlich der selbe Code bei rauskommen, wie wenn ich in Assembler auf einen Speicherbereich/Eintrag zugreife (z.B. bei der Matrix-SW, oder der asm-DMX-Routine.....)


    Mal was anderes: in asm macht man das ja so, dass man in der ISR / Subroutine selbst alle Register sichert, die man dort benützt - Bascom sichert da beim Aufruf immer "alles" (also auch den ganzen internen Kram) und stellt es dann wieder her, macht jeweils ca. 50 Takte - diese kann man sich sparen, wenn man den Aufruf mit "Nosave" macht (Neni hat da mal was zu geschrieben), muss sich dann aber ggfs. selbst um das sichern kümmern..


    k.A., ob das nur funktioniert, wenn in der aufgerufenen Routine dann Inline-Assembler steht und man die dort benutzten Register sichert, es bei Bascom aber nicht geht, weil das z.B. bei diesem Vergleich, schreiben in's Array etc. andere Register/RAM-Bereiche (den internen Kram eben) überschreibt, die dann anderswo wieder gebraucht werden..?!? - falls nicht, würde diese "Nosave"-Option hier halt auch gleich mal ca. 100 Takte sparen.... was immerhin ca. 5x so viel ist, wie die *komplette* DMX-Routine in Assembler.. :D ;)

    It's only light - but we like it!


    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

    Einmal editiert, zuletzt von Pesi ()

  • Hi,


    aaaalso, ich habe nun den Code von Günter auf dem Mega8, Mega644 und Mega644p getestet. Das Ergenbis ist das der selbe Code nur auf dem Mega8 läuft, auf den anderen beiden läuft der nicht!


    Die Aus- und Eingänge habe ich natürlich auf die anderen beiden Controller angepasst. Irgendetwas muss an denen besonders sein das es nicht funktioniert. Das Ergebnis bei dem Mega644 und dem Mega644p ist genau das selbe, die LEDs flackern nur komisch rum sobald was am Rx der UART ankommt.


    Ich schau mal was ich noch für andere Typen zum testen dahabe und werden dann wieder berichten.


    Gruß, Benny.

  • k.A., ob das nur funktioniert, wenn in der aufgerufenen Routine dann Inline-Assembler steht und man die dort benutzten Register sichert, es bei Bascom aber nicht geht, weil das z.B. bei diesem Vergleich, schreiben in's Array etc. andere Register/RAM-Bereiche (den internen Kram eben) überschreibt, die dann anderswo wieder gebraucht werden..?!? - falls nicht, würde diese "Nosave"-Option hier halt auch gleich mal ca. 100 Takte sparen.... was immerhin ca. 5x so viel ist, wie die *komplette* DMX-Routine in Assembler.. :D ;)

    Ich befürchte, dass der AVR selbst für Zuweisungen auf Registern rumreitet. Bei Additionen sogar ziemlich sicher, vorallem wenn die Var. mehr als 1 Byte haben. D.h. du wirst da kaum drum rumkommen. Leider...

    Die Aus- und Eingänge habe ich natürlich auf die anderen beiden Controller angepasst. Irgendetwas muss an denen besonders sein das es nicht funktioniert. Das Ergebnis bei dem Mega644 und dem Mega644p ist genau das selbe, die LEDs flackern nur komisch rum sobald was am Rx der UART ankommt.

    Was mir dazu spontan einfällt wäre, dass die Register eventuell nicht bei beiden Typen gleich heißen. Keine Garantie, aber überprüf mal zur Sicherheit ob die Register wirklich bei beidem vorhanden sind und die Bits im Register den gleichen Namen tragen.

  • Hi,


    naja, die heissen in Bascom schon mal nicht gleich.


    Bei Mega8: If Ucsra.fe = 1 Then


    Bei Mega644 und Mega644p: If Ucsr0a.fe0 = 1 Then


    Mehr unterschiede konnte ich bisher noch nicht feststellen. Werd aber dazu nochmal das Datenblatt durchgraben müssen ;( Wenn da ein Fehler drin wäre dann wäre ja die Definitionsdatei des Mega644 und Mega644p falsch. Dann würde ich echt gern wissen wo die Progger von Bascom wohnen :cursing: :D


    Gruß, Benny.

  • Hallo benkly,


    du bist auf dem richtigen Weg. Doch mit Bascom hat das wenig zu tun. Das sind die Namen der Register, diese sind im Datasheet beschrieben. Das ist auch immer die einzige und richtige Quelle für sowas. Die Register heißen desshalb auch in ASM, C und Pascal so.


    Guck dir auch mal den Bereich an, wo die USART eingestellt wird:


    Code
    Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 2 , Databits = 8 , Clockpol = 1
    
    
    On Urxc Empfang
    
    
    Enable Urxc
    
    
    Enable Interrupts


    Günter

  • Hehe, ich habs. So halb zumindest. Es muss ein Fehler in der Definitionsdatei von Bascom vorliegen! Denn mit der 2. UART des Mega644p funktioniert alles wie es soll.


    Komisch an der Sache ist das der Fehler anscheinend schon bei der Definitionsdatei des Mega644 bestanden haben muss da es mit diesem ja auch nicht funktioniert. Aber in den Foren findet man so eingentlich keine Infos das beim Mega644 die 1. UART nicht funktioniert hätte. Also gehe ich mal davon aus das es schon mir irgendeinem Register zu tun haben muss auf das wir direkt schreiben oder abfragen was man normalerweise bei einer normalen RS232 Abfrage gar nicht tut. Wird für die RS232 das Frame Error Flag auch in der Art benutzt wie wir das hier mit dem DMX tun?


    Gruß, Benny.

  • Bei normaler UART Kommunikation wird das ErrorFlag eigentlich eher selten benutzt. Du kannst FrameErrors abfangen, aber die meisten tun das wohl nicht. Ich glaube aber immernoch wie guenter, dass die Register im mega644 andere Namen haben, das hängt aber dann nicht mit Bascom zusammen, sondern ist ein generelles Problem in allen Sprachen.

  • Hmmmm, also ich dachte das Bascom in der .Dat-Datei eines jedes µC die Register quasi übersetzt. Und wenns da falsch übersetzt ist dann gehts nicht. Daher ist es für mich schon ein Fehler von Bascom wenn die .Dat-Dateien nicht stimmen. Für was habe ich einen Hochsprache-Compiler wenn er mir die Hochsprache nicht für die Maschine in nen verständlichen Code übersetzen kann? Wenn ich da mit Sachen wie z.B.:

    Code
    $asm                                                    	'Dat.-Datei des M644P korrigieren
    .equ Timsk = Timsk0
    $end Asm


    anfange dann kann ich mich bald gleich hinsetzen und lernen wie man mit ASM proggt.


    Naja, mal schauen ob ich den Übersetzungsfehler finde.


    Gruß, Benny.


    @ Pesi


    gibt es irgendwelche besonderen Schaltungstipps für die DMX Seite damit das sauber und ohne Störungen funktioniert?

  • Hi Günter,


    danke das Dir das mal anschaust. Bisher habe ich da auch keine Fehler gefunden. Ich kann mir da eigentlich nur noch einen Fehler in der .Dat-Datei des Mega644p vorstellen.


    Was den Controller angeht, ich habe noch 3 bis 4 von den Mega644 hier und benötige diese eigentlich nicht. Der Mega644 hat halt nur eine UART aber die müsste den gleichen Fehler haben da ich es mit diesem auch schon getestet habe. Ich denke mal das die Bascom Entwickler das File vom 644 einfach auf den 644p kopiert haben und nur die 2. UART richtig eingepflegt haben.
    Ich könnte Dir die Mega644 zukommen lassen.


    Andere Frage noch, könntest Du mir den ASM Teil für das senden von DMX auf 20MHz umrechnen? So Zeitenberechnung kann ich noch nicht und das wäre wohl die beste Lösung für eine Master-Slave Lösung.


    Vielen Dank schon mal das Dich hier so toll um uns kümmerst :D


    Gruß, Benny.

  • Also ohne die Routine von Guenter jetzt "schlecht reden" zu wollen (wie gesagt,finde das echt ne geniale Idee!), nimm' doch einfach den USART zum senden, der macht das dann "automatisch", brauchst Du gar nix groß berechnen.


    Prinzip ist folgendes:


    Du initialisierst erst mal den USART (250 kbit/s, 8 Datenbit, usw.) und schickst ein Byte raus - aktivierst vorher den Tx complete Interrupt.


    Das senden selbst erfolgt in einer ISR: sobald der USART dieses Byte verschickt hat, wird die zum ersten Mal aufgerufen.


    Dort schaltest Du temporär die Geschwindigkeit wieder runter und sendest ein Nullbyte - dadurch erzeugst Du diesen Frame-Error. Sobald das verschickt ist (währenddessen kann der µC anderes machen, weil der USART sich ja selbst drum kümmert), wird die ISR natürlich wieder aufgerufen.


    Also als nächstes wieder auf 250 kBit/s hochschalten und ein Byte "0" schicken, das ist das Startbyte. Macht der USART wieder selbst, wenn er fertig ist wird wieder die ISR aufgerufen.


    Also schickst Du als nächstes das erste Datenbyte, wenn das durch ist, wird wieder die ISR aufgerufen, nächstes Datenbyte usw., bis alle durch sind, dann das Spiel von vorne...


    Das ganze ist timingunkritisch, ist der µC z.B. gerade mit ner anderen ISR beschäftigt und ein Byte ist durch, dann dauert's halt ein bisschen länger, bis er das nächste sendet, das macht ja nix... das Timing *innerhalb* eines Datenbytes stimmt jedenfalls exakt, weil das macht der USART per Hardware... diese ISR wird auch ca. alle 44 µs aufgerufen (weil so lange ein Byte ca. dauert...)


    Die Routine von Guenter erzeugt ja das serielle Signal per Bitbanging - da sich bei 250 kBit/s 250.000 mal pro Sekunde der Pegel auf der Leitung ändern kann, muss diese Routine auch 250.000 mal pro Sekunde aufgerufen werden! - Und zwar möglichst exakt! - wenn hier z.B. gerade ein Flankenwechsel stattfinden soll, der µC aber in diesem Moment in ner anderen ISR "feststeckt", dann kommt der Wechsel verzögert, d.H. Du hast kein sauber getimtes serielles Signal mehr...


    250.000 Aufrufe/sek bei 20 MHz wären dann alle 80 Takte* - da ist der µC schon ziemlich beschäftigt... bei der USART-Methode hast Du zwischen 2 Aufrufen ca. 880 Takte zur Verfügung, da sollte die Sende-Routine auch komplett in Bascom gehen...


    Wenn ich das "Timer0 = 70" richtig interpretiere (wie gesagt, ich und Bascom....) wird die Routine sogar alle 70 Takte aufgerufen*? - und für den FrameError ist dann noch die Zeile "Waitus 88" drin...? - also *in ner ISR* einfach mal 88 µs nur zu warten finde ich schon etwas heftig, wie weiter oben schon angemerkt wurde, macht man Interrupt-Routinen ja möglichst kurz... ;)


    *EDIT: OK, übersehen, dass die Routine ja für 8 MHz gebastelt ist - bei 20 MHz sollten es dann alle 175 Takte sein...? (was immer noch deutlich öfter ist als alle 880 Takte...)

    It's only light - but we like it!


    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

    Einmal editiert, zuletzt von Pesi ()

  • Hi,


    Pesi
    Das hört sich gut an, nur wie umsetzen. Da muss ich mich mal hinsetzen und schauen wie das mit der UART so alles funktioniert. Die Empfangsroutine von Günter finde ich ja sehr gut bisher, das der alle Kanäle Buffert stört mich da eigentlich auch nicht da mein sender nicht alle sendet :P Und selbst wenn dann ist das ja nicht schlimm. So könnte man später den Code anpassen und manche Kanäle für andere Abfragen oder Funktionen mit einbinden. So nach dem Motto, mache das was in Deinen Kanälen steht ausser es steht xy im Kanal yx der Lampe xz.


    @Günter
    Die Idee von Pesi hört sich sehr gut und universell an, glaubst Du könntest da mal ein klein wenig mitwirken da was funktionierendes zu basteln. Ich werd mich da auch noch ransetzen, nur mit dem Umgang der UART bin ich bisher noch nicht so vertraut, vor allem wenns um Timings geht.


    Gruß, Benny.

  • Hallo Benny,


    da hat Pesi schon recht, wenn es nur so ums Senden geht, ist mein Code suboptimal. Er bildete bei mir die Grundlage zu einem Testsender.


    Pesi,

    Zitat

    - also *in ner ISR* einfach mal 88 µs nur zu warten finde ich schon etwas heftig

    Das freut mich, daß du das so siehst. Das Ziel meines Testsenders war eine absolut exakte Nachbildung des DMX-Protokolls. Das stimmt auch auf die Mikrosekunde. Durch den Einbau von zusätzlichen Schleifen anstatt der NOPs hat man die Möglichkeit überall am Timing zu drehen und so Empfänger zu testen. Es wäre aber fatal, wenn der eigene Microcontroller da ungewollt auch am Timing dreht ;) , weil er gerade mit I2C, RC5 und Display beschäftigt ist. Deshalb alles im Interrupt.


    Günter

  • Ah, OK, für den Zweck kann man das natürlich so machen.... steht halt leider nirgendwo auf der Seite drauf, dass das für nen Testsender gedacht ist und für "hier Dein genialer Code" nicht mehr sooo viel Takte über bleiben ;) - wie genau das Bascom die 88 µs einhält ist übrigens ne andere Frage, da wurde hier auch schon diskutiert - natürlich, für den Hausgebrauch/die meisten Fälle reicht's locker, aber wenn das für nen Testsender ist, wo man das Timing wirklich *exakt* haben will.... ?


    Benny: mach' Dir keinen so großen Kopf, schau' Dir mal das DMX-Protokoll an - da gibt's nen ziemlich großen Toleranzbereich, innerhalb dessen das alles in der Norm ist, der RESET kann z.B. von 88 µs bis beliebig lange (macht natürlich keinen Sinn, den zu lange zu wählen) sein, die Pausen zwischen zwei Bytes von 0 bis 1 Sekunde (was natürlich auch wieder keinen Sinn macht, wegen der Datenrate)... Aber es macht garantiert nix, wenn zwei Bytes nicht direkt aufeinanderfolgen, sondern da ne kurze Pause ist - aus 15 Jahren praktischer DMX-Erfahrung kann ich Dir sagen, dass es eher Probleme gibt wenn der Sender zu schnell ist, weil da manche Empfänger nicht mehr hinterherkommen mit Bytes "wegschaufeln"...


    Drum sind viele DMX-Interfaces ja auch auf "etwas langsamer" eingestellt, bei meinem e:cue-Butler z.B. ist der Reset 96 µs und die Pause zwischen 2 Bytes 10 µs - meine Chinesenpulte machen sogar ca. 50µs Pause zwischen 2 Bytes, entweder können sie nicht schneller :D oder die rechnen schon damit, dass jemand dann auch einen Billig-Empfänger anschliesst, der bei 0 Interdigit evtl. nicht mehr mitkommt....


    Andersrum ist's wurscht: sowohl die Routine von Guenter wie auch die von mir, bzw. die asm-Version empfangen auch noch zuverlässig, wenn nur alle 100 ms oder 2 Stunden ein Byte kommt - weil's dem USART einfach wurscht ist, das nächste Byte wird gesendet, er empfängt das als "das nächste Byte", und das ist immer so, egal ob zwischen 2 Bytes nun 0 Sekunden oder 2 Stunden liegen - dafür gibt's eben diesen Reset/Frame Error, damit man zuverlässig anzeigen kann "hier beginnt ein neuer Block"


    wichtig ist jedoch, dass die Zeiten der *Bits* recht genau stimmen, sonst kommt der empfangende USART ducheinander, weil er ja daraus das Taktsignal regenieren muss - Und die stimmen *exakt*, wenn Du über den USART sendest, weil der das per Hardware macht, da *kann* nix dazwischenfunken! - im Gegensatz dazu, wenn Du das Signal per Bitbanging erzeugst - weil auch wenn Du dafür nen Timer-Interrupt benutzt (anders geht's ja gar nicht), dann kann es ja passieren, dass der µC bei einem Timer-Interrupt gerade in ner anderen ISR steckt, und die Timer-ISR dann erst verzögert aufgerufen wird (ausser natürlich, Du setzt das IE-Flag in der anderen Routine wieder, dann kann die nochmals unterbrochen werden, ist aber kein guter Stil....)


    ich kann Dir das schon mal grob zusammentippen, diese Senderoutine - ob das dann alles so richtige Bascom-Syntax ist u.ä., müsste jemand anders mal drüberschauen...

    It's only light - but we like it!


    Da es sich in letzter Zeit häuft: Ich beantworte keine PNs mit Fragen, die sich auch im Forum beantworten lassen!
    Insbesondere solche von Mitgliedern mit 0 Beiträgen, die dann meist auch noch Sachen fragen, die bereits im entsprechenden Thread beantwortet wurden.
    Ich bin keine private Bastler-Hotline, technische Tipps etc. sollen möglichst vielen Lesern im Forum helfen!

  • Hallo Pesi,


    ich muß dir schon wieder recht geben hier müsste auch eine Schleife mit NOPs rein, doch in diesem Fall passt es auch mit Bascom:


    Waitus 88 benötigt 704 Zyklen a 125ns, das macht exakt 88 us ;)


    Kritisch wäre nur eine Wartezeit, die sich nicht durch die Taktzeit teilen lässt. Dann wird Bascom (natürlich) ungenau.


    Achja:

    Zitat

    steht halt leider nirgendwo auf der Seite drauf, dass das für nen
    Testsender gedacht ist und für "hier Dein genialer Code" nicht mehr
    sooo viel Takte über bleiben ;) -

    meine Internetseite habe ich angepasst...