[Tutorial] DMX Empfang mit AVRs / Strobe Interface

  • Um eine schöne hohe Auflösung zu bekommen, wollen wir für die Strobes den 16bit-Timer (T1) nutzen.
    Dieser zählt von 0 bis 2^16 und fängt dann wieder von vorn an. Jeder Timer eines AVRs hat einen eigenen Vorteiler (Prescaler), um den Zähltakt dem Systemtakt anzupassen.


    Nun zur Berechnung:


    PMN möchte einen Frequenzbereich von 1..15Hz.
    Wir wollen nun herausfinden, wie weit der Timer von 0 an zählen muss, um auf 1Hz oder 15Hz zu kommen. (Nach Erreichen der Zahl resetten wir den Timer und zählen erneut...)


    Die Formel lautet:
    Y= f_quarz/(f_pmn * Prescale)


    Unser Quarz hat 8MHz. Die möglichen Vorteiler findet Ihr auf S.122 im Datenblatt. Was ist der kleinste Vorteiler, damit wir mit unserem Wertebereich (2^16 = 65536) hinkommen?

  • Wenn Ihr das datenblatt nicht habt:


    Zur Auswahl stehen: 1; 8; 64; 256; 1024


    Keiner eine Idee? :wink:


    Auflösung: Wir müssen bei der langsamsten Frequenz am weitesten zählen -> 1Hz interessant


    also: Y_max= 8*10^6/Prescale, wobei Y_max < 65536 und Prescale möglichst klein


    -> 64 reicht nicht, 256 passt.


    Somit lautet die Formel für den Timer, um auf PMNs Frequenzen zu kommen:
    Y= 8*10^6/(256*f_pmn), wobei f_pmn= 1..15Hz.

  • Hmm, irgendwie häng ich da grad beim ausrechen. Liegt wohl dran, dass ich keine 2h nach nem 27h tag geschlafen hab... :?


    Die Formel Y= f_quarz/(f_pmn * Prescale) hätte ich nach Prescale aufgelöst:
    Prescale = f_quarz/(f_pmn * Y)
    f_quarz = 8000Hz


    für Y hätte ich ausm kontext raus 65536 genommen, und für f_pmn bin ich noch unschlüssig ob ich 1 Hz oder 15Hz nehmen soll.
    So kommen, meiner meinung nach, nur unsinnige Ergebnisse raus.


    edith ist der meinung, dass 8MHz keine 8000Hz sind, sondern 8000000Hz sind. Ich sag ja, ich war zu lange wach.

  • Eure Herangehensweise ist super, wenn man den Prescaler beliebig aussuchen kann.
    Wenn man sich auf einen von 6 (?) möglichen Werten festlegen muss, geht ausprobieren schneller :D



    Ach ja: Wenn ich die Formel durch Matlab jage, erhalte ich folgende Tabelle:


    Diese Tabelle wird als Konstante direkt im Flash (PROGMEM) abgelegt und belastet so nicht das RAM.

  • @PMN:
    Die Formel ist richtig umgestellt ->
    8*10^6/(1Hz*2^16)= 122


    also Vorteiler 256 (s.o.)


    Eigentlich habt Ihr Recht: Umstellen ist doch besser...



    Edit:
    Ich bereite jetzt mal den Code vor...

  • so...


    Sorry für die Verzögerung - ich hatte aus Versehen das falsche Universum angestöpselt und habe mich bis eben gewundert, warum nichts funktionierte...


    Da wir Timer1 als Frequenzgenerator nutzen und möglichst genau arbeiten wollen, nutzen wir ihn im CTC mode. Das bedeutet, dass wir ihn automatisch bei Erreichen von unserem Zielwert (abgelegt im Vergleichsregister OCR1A) zurücksetzen.


    Die Initialisierung gehört in die Funktion init_system() und lautet:

    Code
    TCCR1B = (1<<CS12)|(1<<WGM12);	//set T1 @clk/256, CTC mode
    TIMSK  = (1<<OCIE1A);
    OCR1A  = 5000;


    Die erste Zeile setzt Prescaler und mode. Die Zweite aktiviert einen Interrupt bei Erreichen des Zielwertes und die dritte lädt schon einmal eine Dummy-Frequenz, damit was blinkt...

  • Nun zur neuen main:


    Wir möchten Werte direkt aus dem Flash lesen und benötigen dafür die Lib:
    #include <avr/pgmspace.h>


    Wir brauchen eine neue globale Variable:
    uint8_t DmxBuf;


    Der Code lautet:


    Kann mir jemand erklären, was ich wohl gemacht habe?



    ach ja:
    Die Interrupt Service Routine (ISR) zum Blinken lautet:

    Code
    ISR (TIMER1_COMPA_vect)
    {
    PORTD ^= (1<<PD7);
    }


    Hier mein derzeitiges Projekt:
    http://www.hoelscher-hi.de/hendrik/forum/anastrobe.zip

  • Wenn sich unser DMX-Wert geändert hat, lade ich die neue Frequenz aus der Tabelle.
    Wenn der Timer schon weiter gezählt hat, als unser Vergleichswert groß ist, müssten wir für den nächsten Blitz so lange warten, bis der Timer nach dem Überlauf das nächste Mal wieder vorbeikommt. Da wir solche Aussetzer nicht wollen, setzen wir in diesem Fall den Timer kurz vor unseren Vergleichswert.
    Abschließend aktualisieren wir den Vergleichswert. Da dieser eine Größe von 16bit hat, müssen wir darauf achten, dass keine ISR dazwischen funken kann und sperren deshalb kurz alle Interrupts.


    Die Timer-ISR selbst lässt nur die rote LED blinken.

  • Der DMX-Bereich sollte in drei Felder aufgeteilt werden: Aus, normal, Einzelblitz
    Zusätzlich wollen wir kein Blinken sondern ein kurzes Flashen.
    Deshalb nehme ich das zweite Vergleichsregister (OCR1B) und nutze es, um kurz vor dem anderen Interrupt mit dem Blitz zu beginnen. Über das alte Vergleichsregister (OCR1A) wird dann der Blitz nur noch abgeschlossen.


  • Sorry, bin gestern Abend geflogen, da meine Sync vom DSL immer wieder nach ca. 30 Sekunden Onlinezeit abriss... Werde mal versuchen, das gestern erarbeitete zu begreifen und umzusetzen.


    Schon mal vielen Dank für deine Mühe, Hendrik!

  • Sodenn... das Modul macht schon mal annähernd was es soll. Proband war bei mir ein Eurolite Superstrobe 2700.


    Zu unserem Glück ist der Eingang an dem Strobo mittels eines 4N35 ausgeführt, also können wir uns schon mal weitere Optokoppler sparen, da ja bereits eine saubere Trennung vorliegt. Der 4N35 erwartet am Eingang ca. 6 Volt, die 5 Volt die unser Transceiver liefert sind also durchaus angemessen.


    Einziges Problem hier: Die vom Transceiver gelieferten Impulse scheinen zu kurz zu sein, da der Blitz nicht immer zuverlässig auslöst...