AVR -> DMX
Beim schlendern durch das größte Kaufhaus des Internets bei der E-Bucht, fiel mir eine Chinesische Reisfeldbeleuchtung auf, auch Umgangssprachlich Sphärischer LED-Pinspot genannt. Für die Steuerung verfügt dieser über einen DMX (Digital Multiplex) Anschluss. Da mich meine Frau sowieso für einen Elektroschott Messie hält, habe ich kurzum das gute Gerät ersteigert. Solche Spots (Eurolite LED PST-9W RGB DMX 6° Pinspot) und LED Strahler (PAR-36 RGB LED) gibt es schon ab 39€ im Handel (RockShop).
Natürlich wollte ich gleich den Spot über einen AVR Mikrocontroller(µC) ATmega88 (Experimentierboard V1) ansteuern. Dieses kann mit einer relativ einfachen Schaltung erfolgen. Der differentielle Pegel (DMX Ausgang) der Schaltung liegt zwischen +/-1V und +/-5V. Die nachfolgende Schaltung generiert aus dem ankommenden TTL Pegel des µC ein Symmetrisches Signal (RS485). Der Ausgangsstrom beträgt maximal 60mA. Das sollte für etwa 32 Geräte reichen. Für mehr Geräte benötigt man einen DMX Booster.
Hier wurden die Signale TXD vom µC kommend, sowie die DMX Signale aufgenommen. Eigentlich kommt nur ein zweiter invertierter Ausgang hinzu. Ein Inverter hätte evt. in diesem Fall als Lowcost Lösung ausgereicht. Allerdings könnte man in diesem Fall nicht 32 Geräte direkt ansprechen.
Nachdem ich die Schaltung aufgebaut und an mein ATmega88 Testboard angeschlossen hatte, benötigte ich auch eine entsprechende Software/Firmware für den µC. Die Software/Firmware muss das zeitliche Protokoll der USITT (United States Institute for Theatre Technology) DMX-512/1990 abbilden.
Das DMX 512 Protokoll für den LED-Pinspot nachzubilden ist relativ einfach. Ich sende dazu für die Kanäle 1 – 512 die 512Bytes hintereinander über den USART0 des ATmega88 raus. Die USART Einstellungen sind dabei 250kbit/s (4µs pro Bit), 8 Datenbits, kein Parity-Bit und zwei Stoppbits.
main.c | |
80 81 82 83 84 |
//Init usart DMX-BUS UBRR0 = (F_CPU / (DMX_BAUD * 16L) - 1); DDRD |= (1<<PD1); //Output TXD Pin ATmega88 UCSR0B |=(1<<TXEN0)|(1<<TXCIE0); // TXEN0 Transmitter enable // TXCIE0 TX complete interrupt enable UCSR0C |=(1<<USBS0); //USBS0 2 Stop bits |
Jedes mal wenn der USART das Datenwort gesendet hat löst dieser einen Interrupt aus. In der Interruptroutine wird dann das nächste Datenwort versendet. Vor jeden 512Byte Datenbolck gehört noch ein Startbyte sowie eine Breakphase welche den Start einleitet. Das Startbyte entspricht den Wert 0. In der Breakphase wird der Bus mindestens 88µs auf "LOW" gezogen und danach mindestens 8µs auf "HIGH". Die Breakphase generiere ich in dem ich das Datenwort 0 mit 80000Baud sende. Das alles erfolgt in der Interruptroutine mittels einer State Machine.
main.c | |
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
//############################################################################ //DMX Senderoutine ISR (USART_TX_vect) //############################################################################ { static unsigned int dmx_channel_tx_count = 0; static unsigned char dmx_tx_state = 0; switch (dmx_tx_state) { case (0): UBRR0 = (F_CPU / (DMX_BAUD_BREAK * 16L) - 1); UDR0 = 0; //RESET Frame dmx_tx_state = 1; break; case (1): UBRR0 = (F_CPU / (DMX_BAUD * 16L) - 1); UDR0 = 0; //Start Byte dmx_tx_state = 2; break; case (2): _delay_us(10); //Ausgabe des Zeichens UDR0 = dmx_buffer[dmx_channel_tx_count]; dmx_channel_tx_count++; if(dmx_channel_tx_count == 512) { dmx_channel_tx_count = 0; dmx_tx_state = 0; } break; } } |
Zu guter letzt funktionierte nun damit mein LED Spot, und ein Samstagnachmittag war gerettet. ;-)
Dateien, DMX Empfangs und Senderoutinen, DMX Mixer
Layout, Source Code uvm. (22.12.2011)
DMX minimal nur für Testzwecke
Vorherige Seite: Tutorial zur ersten Verwendung des ATmega8 Experimentierboards (Teil 2)
Nächste Seite: Data View