Jednoduchý DMX - RGB modul



  Jeden môj priateľ, ktorý hráva rôzne akcie, ma požiadal, či by sme nedokázali vyrobiť svetlo, ovládane DMXom. Tak som začal na túto tému hľadať na internete rôzne informácie.
  Našiel som stránku, kde táto téma bola veľmi dobre vysvetlená [1]. Kedže AR čítam rád kvôli tomu, že sa niečo naučím a "odkukám", pokúsím sa vysvetliť tento protokol DMX čo najlepšie, aby si každý prišiel na svoje. Či už ide len o ideu, alebo princíp.

    Zapojenie
  Ako srdiečko zapojenia som použil ATMega8A, ktorý je nataktovaný na 16MHz. Zo vstupného konektoru putuje DMX signál cez ochranné rezistory 10R do prevodníka rozhrania RS485/USART SN75176. Z neho putuje signál RxD do MCU. Prevodník je zapojený tak, že dáta zo DMX zbernice sa iba prijímajú. Rozhranie RS485 má by byť zakončené rezistorom 120R. My sme to vyriešili tak, že vo svetlách sme použili dva konektory JACK 6,3 so kontaktom. Obidva konektory sú priamo prepojené. Teda jeden ako Vstup a druhý ako Výstup. Výstupný konektor má pripajkovaný rezistor 120R na svojich kontaktoch, ktoré sa odpoja pri zasunutí jacku.
  Výstupný stupeň je v zapojení tranzistora ako spínač - (principiálne so spoločným "source"). Kvôli kapacite medzi G a S som použil ochranný rezistor 470R medzi výstupom MCU a G tranzistora. Tranzistory sú typu IRLZ44, no je ich možno nahradiť akýmkoľvek HEX-FETom, ktorý znesie požadovanú prúdovú zátaž a je určený pre spínanie napäťovou úrovňou 5V (IRL540, IRLU7833...).
  Pri projektovaní sme v napájaní ešte nemali veľmi jasno. Kvôli tomu sú na vstupe 3 diódy a stabilizátor na 5V. Takto sa môže modul napájať buď vlastným zdrojom, alebo sa napája zo zdrojov pre žiarovky, LED pásiky, LED...
  Adresa sa nastavuje veľmi jednoducho. Na DMX pulte sa všetky kanály nastavia na nulu. Potom sa na požadovanej adrese zdvihne bežec nad polovicu (Teda nad hodnotu 128). A stlačí sa tlačítko "Uloženie". Ak sa rozsvieti Led D2, adresa bola uložená do pamäte EEPROM.
  Led D1 je dvojfarebná kontrolka, ktorá oznamuje zelenou - "prijatý paket dát" a červenou - "chybu v prijatých dátach".

    Rozhranie
  Protokol DMX komunikuje rýchlosťou 250Kb/s a používajú sa dva "stop" bity bez parity. Nič sa nestane, keď si USART nastavíme iba na jeden "stop" bit. Funguje to jednoducho. Zbernica je stále na úrovni H (log.1). Akonáhle sa dostane do úrovne L (log. 0), začne USART plniť register. Po poslednom dátovom bite musí nasledovať "stop" bit, ktorý je na úrovni H. Ak sa stane, že na stop bite bude namiesto úrovne H úroveň L, vyhlási sa chyba FE (Frame error). Viď obrázok 1.

  Na spomínanej stránke [1] môžte nájsť celkový popis celého paketu. Dokonca aj pomenovanie jednotlivých časti a ich dĺžky. Nás to až tak nemusí zaujímať.. (neskôr sa dozvieme prečo).
  Zo začiatku paketu spadne úroveň na zbernici do L, ktorý trvá 88us. Potom sa zdvihne úroveň do H a vyšle sa prvý byte s hodnotou 0. To je "Start byte". Po ňom nasledujú hodnoty (dáta) kanálov. Podľa typu protokolu, teda či ide o DMX256, alebo DMX512, je vyslaný príslušný počet hodnôt jednotlivých kanálov (bajtov). Viď obrázok 2.

  Najprv som sa zameral na ošetrenie 88us "Resetu". No zrejme nie všetky DMX ovládače dodržujú túto dĺžku, tak mi to až tak dobre nefungovalo. Ale po dlhom hľadaní po internete som našiel jednu knižnicu ku DMX a v nej to vyriešili veľmi zaujímavo.
  Keďže pri vyslani signálu "Reset" spadne úroveň zbernice do L, spustí sa USART. Ten vyhlási chybu FE (Frame Error), lebo USART na stop bitoch najde logickú 0, keďže je ešte stále na zbernici úroveň L. (Signál "Reset" trvá dĺhšie, ako trvá načitanie jedneho bytu USARTom) To je znamenie, že sme v "Resete" a nasleduje "Štart byte".
  Celkový proces načítavania je odkrokovaný. V mojom programe je tento register označený písmenkom "F".
    0 - Čakanie na chybu FE. Ak je vyhlásenia chyba, do F vloží 1.
    1 - Načítanie prvého (Štart) byte a porovnanie. Ak načítaný byte je 0, do F vloží 2. Inač vynuluj F.
    2 - Počkanie na byte podľa adresy. Teda, ak je adresa 10. Tak 9 byte sa ignorujú a desiaty byte sa načíta. V našom prípade načitáme hodnotu farebnej zložky R (Red). Do F vloží 3.
    3,4,5,6 - Načítanie G (Green), B (Blue), Y (Celkovy jas), Strobo. Po poslednom načítanom byte sa F opäť vynuluje.

    Softwate
  Program je písaný pre ATMegu8 na 16MHz v assemblery AVRA [2]. Teda neviem zaručiť úplnú kompatibilitu s AVR štúdiom. No každopádne sa to pokúsim vysvetliť tak, aby si to mohol „nakodiť“ každý vo svojom jazyku a prostredí.
  Pre ATMegu mám napísanú knižnicu, ktorá je vlastne prepísaná knižnica „m8def.inc“ (teda jej základne časti. Ďalej priraďuje vektory prerušenia, nastavuje „stack pointer“ a v poslednom rade makrá pre jednoduchšie písanie.
  Začnem tabuľkou prerušení. Všetky vektory mám zapísané v takom tvare:

.equ URXCaddr = 0x000b ; USART, Rx Complete
  .org URXCaddr
  .ifdef Interupt_USART
    .message "Event of URXC -> USART"
    RJmp Interupt_USART
  .else
    RetI
  .endif

Tento zápis mi zaručuje, že ak niekde v programe napíšem kód s adresou "Interupt_USART" :

Interupt_USART: ; Adresa obsluhy USART
    ...
    ...
  RetI

  Priradí k nej rutinu od USARTu. Teda ak USART prijme nový údaj, vyvolá sa v bežiacom programe prerušenie a skočí na túto adresu. Vykoná sa obslužný podprogram a na inštrukcii „reti“ sa vráti na hlavný program, odkiaľ odbehol.
  Počas podprogramu sa môžu zmeniť hodnoty v registroch, alebo príznaky v SREG. Preto sa pri prerušení všetky používané registre a SREG uložia do zásobníka. Ošetril som si to makrom s názvom PushA a PopA. Názov je prevziatý z inštrukčnej sady x86 (ta inštrukcia funguje až od 286ky).

; Makra
  .Macro PushA
    Push T ; Ulož register T (temp)
    Push A ; Ulož register A (akumulátor)
    Push B ; Ulož register B (pomocný akumulátor)
    In T , SREG ; Ulož Status register
    Push T ; - pomocou registra T
    Cli ; Zakáž iné prerušenie
  .EndMacro

  .Macro PopA
    Pop T ; Obnov Status register
    Out SREG , T ; - pomocov registra T
    Pop B ; Obnov register B
    Pop A ; Obnov register A
    Pop T ; Obnov register T
  .EndMacro

;Rutina od USART
  Interupt_USART:
    PushA ; Zalohuj registre
      ..
      ..
    PopA ; Obnov registre
  RetI ; Koniec rutiny

  Teraz si nastavíme USART. Prvým registrom pre obsluhu USART je UCSRA. Ide skôr o stavový register, ako by sa ním malo niečo nastavovať. Preto nás až tak nebude zaujímať. Druhým podstatnejším registrom je UCSRB. Viď obrázok 3.

RXCIE je povolenie vyvolať prerušenie, ak USART príjme bajt.
TXCIE je povolenie vyvolať prerušenie, ak USART odošle bajt.
UDRIE je povolenie vyvolať prerušenie, ak je dátový bajt nula.
RXEN je povolenie prijímania dát.
TXEN je povolenie odosielania dát.
UCSZ2 je v kombinácii s UCSZ0,1 nastavuje dĺžku dát. USART može odoslať aj 9 bitov.
RXB8 a TXB8 je práve tým deviatim bitom.

  Tretím registrom je UCSRC. Tento register ma dve funkcie. Ak je bit URSEL v log.1, Správa sa tento register podľa obrázku 4. Ak je bit URSEL v log. 0, predstavuje horný bajt baud-rate podľa obrázku 5.

UMSEL Synchrónny \ Asynchrónny režim. ( 0 – Asynchrónny )
UPM1,0 Nastavenie paritného bitu. (0,0 – bez paritného bitu)
USBS Počet STOP bitov (0 – 1 stop bit)
USBS Počet STOP bitov (0 – 1 stop bit)
UCSZ1,0 Dĺžka dátového slova. (1,1 – dĺžka 8 bitov)
UCPOL Polarita ( 0 – bežaná )

  Pre nastavenie rýchlosti baud-rate, slúži register UBRRL a UBRRH. UBRRH je, ako sme už spomínali, regiter UCSRC. Viď obrázok 5.

  Protokol DMX ma rýchlosť 250Kbps. Pri taktovacej frekvencii 16Mhz a vypnutom násobiči rýchlosti U2X, je hodnota UBRRL=3. Do UBRRH zapíšeme nulu. Tu treba dať pozor na poradie zápisu horného a dolného bajtu. Totiž AVR si ukladá najprv horný bajt do “bufra“ a pri zápise spodného bajtu, zapíše jedným taktom obidve hodnoty naraz. Týka sa to najme časovačov a AD prevodníka. Treba mať na pamäti, že to isté platí aj pri čítaní, len naopak. Najprv sa načíta spodný bajt a následne horný.
  Poďme sa pozrieť, ako bude vyzerať makro.

.Macro USART_Init;
; Nastavenie baud-rate
  Ldi T , 0x00 ; Do UBRRH vlozime nulu
  Out UCSRC , T ; - UCSRC je UBRRH
  Ldi T , 0x03 ; Do UHRRL vlozime 3
  Out UBRRL , T ; - pri 16Mhz -> 250Kbs
  ; Spustenie USARTu
  Ldi T , 0b10011000 ; Povolenie vysielania/prijimania s prerušením
  Out UCSRB , T ; - RXCIE, RXEN, TXEN
  ; Nastavenie rozhrania
  Ldi T , 0b10000110 ; Nastavenie rozhrania
  Out UCSRC , T ; - 8.bit dlzka, 1 stop bit, bez parity.
.EndMacro

  Dáta sa vyberajú a vkladajú do registra UDR. Ak sa z registra číta, načítávame dáta „RXD“. Ak sa do registra UDR zapisuje, dáta sa zapíšu do registra na odosielanie dát - "TXD".
  Poznámka: Zásobníku, nastavenie portom, časovaču a eepromke sa nebudem v tomto článku venovať. Ak bude podnet, rád to niekedy doplním. No teraz sa zameriame na dekódovanie DMX signálu. Priblížime si rutinu USARTu.

USART_Interupt:
  PushA
  ; Nacitanie registrov USART
  ; - Nacitanie statusu
  In B , UCSRA
  ; - Nacitanie prichadzajuceho bytu
  In A , UDR
  ; Rozvetvenie podla statusu USART
  ; - vyhlasenie chyby FrameError (Pre nas signal, ze sme v BREAK pauze)
  Sbrc B , FE
    Rjmp USART_Interupt_FE
  ; - vyhlasenie chyby DataOverRun
  Sbrc B , DOR
   Rjmp USART_Interupt_DOR
  ; - Nacitanie prichadzajuceho bytu bolo bez chyby
  ; Rozvetvenie podla kroku F
  ; - Hladanie (cakanie na) BREAK pauzu
  Cpi F , 0
    Breq USART_Interupt_End
  ; - Overenie Start bytu
  Cpi F , 1
    Breq USART_Interupt_StartByte
  ; - Hladanie Adresy + Nacitanie prveho bytu farby R
  Cpi F , 2
    Breq USART_Interupt_FindAdres
  ; - Nacitanie 2. bytu platnych dat
  Cpi F , 3
    Breq USART_Interupt_LoadG
  ; - Nacitanie 3. bytu platnych dat
  Cpi F , 4
    Breq USART_Interupt_LoadB
  ; - Nacitanie 4. bytu platnych dat
  Cpi F , 5
    Breq USART_Interupt_LoadY
  ; - Nacitanie 5. bytu platnych dat
  Cpi F , 6
    Breq USART_Interupt_LoadStrobo
  ; Vynulovanie DMX pocitadla
  Clr F
  ; Koniec prerusenia
  USART_Interupt_End:
  PopA
RetI

; Odskoky
; - Status FE
USART_Interupt_FE:
  ; Sme v BREAK pauze. Budeme cakat na START byte
  Ldi F , 1
  ; Vynulujeme status USARTu
  Cbi UCSRA , FE
RJmp USART_Interupt_End

; - Status DOR
USART_Interupt_DOR:
  Clr F
  ; Vynulovanie statusu USARTu
  Cbi UCSRA , DOR
  ; Zasvietenie LED Chyby + Zhasenie LED prijatia dat
  :
RJmp USART_Interupt_End

; - Overenie StartBytu
USART_Interupt_StartByte:
  Cpi A , 0
  ; Ak Start byte je iny ako 0, vyhlas chybu
    Brne USART_Interupt_DOR
  ; Ak je Start byt v poriadku
  ; - Zhasenie LED Chyby + Zasvietenie LED prijatia dat   :
  ; - Posunutie Kroku na hladanie adresy
  Inc F
  ; Vynulovanie pocitadla prichadzajucich bytov
  Clr ZH
  Clr ZL
RJmp USART_Interupt_End

; - Hladanie adresy
USART_Interupt_FindAdres:
  ; Pripocitanie ku pocitadlu prijimanych bytov
  Adiw Z , 1
  ; Kontrola stlacenia tlacidla
  Sbis; od tlacidla..
    Rjmp USART_Interupt_Button
  ; Zhasnutie Led store
  :
  ; Porovnanie Adresy s pocitadlom prijatych bytov
  Cp ZL , XL
  Cpc ZH , ZH
  ; Adresa nenajdena
    Brne USART_Interupt_End
  ; Adresa najdena
  ; - Hned nacitame prvy udaj

  ; - Cervena Farba
USART_Interupt_LoadR:
  Mov cR , A
  ; Krok DMX prijimaca na dalsi byte
  Inc F
RJmp USART_Interupt_End
:
:

  Načítali sme si z USARTu do registra B status rozhrania a do registra A prijatý bajt. Najprv sa porovnáva status:
- Pri zdvihnutej vlajke (bite) FE (Frame Error) sme sa dostali na začiatok vysielania paketu. Ku počítadlu krokov F sa pripočíta jednotka. Teda pôjdeme na ďalší krok.
- Pri zdvihnutej vlajke (bite) DOR (DataOverRun) sa vyhlási chyba, zasvieti červena signálka, zhasne zelená signálka a počítadlo krokov F sa vynuluje. Budeme čakať opäť na FE.
Následne sa bude porovnávať počítadlo krokov F:
- Ak F = 0, koniec rutiny. Čakáme na FE.
- Ak F = 1, kontrola štart bajtu. Štart bajt ma byť „nula“. Ak nieje, vyhlás chybu, ako pri DOR. Ak je načítaný bajt nulový, posuň krokovač F ďalej (na vyhľadanie adresy).
- Ak F = 2, kontroluje sa najprv stlačené tlačídlo.
    a.)Ak je tlačídlo stlačené, ignoruje všetky dáta, kým nenarazí na hodnotu väčšiu ako 128. Ak sa najde adresa, ktorá má hodnotu väčšiu ako 128, rozsvieti sa kontrolka „Uložené“ a adresa (kde bola hodnota väščia ako 128) sa vloží do pamäte EEPROM.
    b.)Ak tlačídlo nieje stlačené, ignorujú sa všetky dáta, pokiaľ nenájde požadovanú adresu. Ak sa hľadaná adresa zhoduje s poradovým čislom prijatého bajtu, máme v registri A platný prvý dátový udaj. Preto ho hneď uložíme do registra „červenej farby“. A samozrejme posunieme počítadlo krokov F na ďalší krok.
- Ak F = 3, načíta sa ďalší údaj, atď...


   [1] projekt.cvut.org
   [2] http://avra.sourceforge.net/