Dmx2rgb: Unterschied zwischen den Versionen
Krisha (Diskussion | Beiträge) K (→Platine: !nutzen) |
|||
(4 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt) | |||
Zeile 12: | Zeile 12: | ||
== Beschreibung == | == Beschreibung == | ||
− | Um diverse LED-Stripes in unserer Lounge steuern zu können, wurde eine Platine benötigt. Hierfür | + | Um diverse LED-Stripes in unserer Lounge steuern zu können, wurde eine Platine benötigt. Hierfür bot sich DMX an, da schon diverse LED-Bars & [http://de.wikipedia.org/wiki/Moving_Head Movingheads] vorhanden sind und somit der Bus mitgenutzt werden kann. Ausserdem bietet dieser Bus die Möglichkeit später mehrere dmx2rgb-Platinen einzubinden. |
[[Benutzer:krisha|krisha]] entwickelte hierfür in EAGLE eine Platine in der Größe 95x90mm. [[Benutzer:schinken|schinken]] schrieb hierfür in kurzer Zeit eine Software für den µC und richtete hierfür einen Raspberry Pi mit [http://opendmx.net/index.php/Open_Lighting_Architecture OpenLighting] ein. | [[Benutzer:krisha|krisha]] entwickelte hierfür in EAGLE eine Platine in der Größe 95x90mm. [[Benutzer:schinken|schinken]] schrieb hierfür in kurzer Zeit eine Software für den µC und richtete hierfür einen Raspberry Pi mit [http://opendmx.net/index.php/Open_Lighting_Architecture OpenLighting] ein. | ||
Zeile 20: | Zeile 20: | ||
== Hardware == | == Hardware == | ||
=== Story === | === Story === | ||
− | [[Datei:Dmx2rgb pcb drill fail.jpg|thumb|200px|right|CNC | + | [[Datei:Dmx2rgb pcb drill fail.jpg|thumb|200px|right|CNC Fehlversuch]] |
Die Hardware wurde auf einer eigenen Platine aufgebaut, da der Umfang für ein Breadboard zu groß gewesen wäre. Um die eigene Platine herzustellen, wollten wir diese zuerst selber ätzen. Nachdem das hierfür benötigte Material allerdings leicht alt war (es war wortwörtlich steinhart), entschieden wir uns dafür die Platine so zu bauen, dass wir sie [[CNC|selbst fräsen]] können und haben dafür möglichst wenige Durchkontaktierungen verwendet, sowie eine Massefläche auf der Oberseite der Platine plaziert. | Die Hardware wurde auf einer eigenen Platine aufgebaut, da der Umfang für ein Breadboard zu groß gewesen wäre. Um die eigene Platine herzustellen, wollten wir diese zuerst selber ätzen. Nachdem das hierfür benötigte Material allerdings leicht alt war (es war wortwörtlich steinhart), entschieden wir uns dafür die Platine so zu bauen, dass wir sie [[CNC|selbst fräsen]] können und haben dafür möglichst wenige Durchkontaktierungen verwendet, sowie eine Massefläche auf der Oberseite der Platine plaziert. | ||
Zeile 141: | Zeile 141: | ||
Das letzte Bit bestimmt, ob der Zugriff lesend oder schreibend erfolgt. In unserem Fall reicht es, dieses Bit auf 0 zu setzen. | Das letzte Bit bestimmt, ob der Zugriff lesend oder schreibend erfolgt. In unserem Fall reicht es, dieses Bit auf 0 zu setzen. | ||
+ | |||
+ | === Problem Lasteinbruch === | ||
+ | Die PWM Chips werden von einer internen Clock (25MHz) gespeist. Das hat zur Folge, das ohne weitere Beachtung, alle Kanäle eines ICs zur selben Zeit das PWM Signal starten. Dies führt zu einem hohem Schaltimpuls und Spannung bricht bei uns mit 16 Kanälen um ca. 1 Volt ein. | ||
+ | |||
+ | Verwendet man nun zusätzlich Kanäle des zweiten Chips, kommt es in regelmäßigen Abständen zu einer Überlagerung und Aufsummierung des Spannungseinbruchs. Dies äußert sich durch flackern. Hintergund: Die beiden Clocks sind nicht synchron und minimal verschieden. Dadurch verschieben sich die Clocks zeitlich zu einander. Im Worstcase befinden sich die PWM Startflanken der unterschiedlciehn ICs mehrere Takte zeitlich aufeinander. | ||
+ | |||
+ | ==== Lösung Startoffset ==== | ||
+ | Eine saubere Lösung wäre hier die PWM Flanken immer zu unterschiedlichen Zeitpunkten einzuschalten. So kann die Last relativ gleichmäßig auf den Zeitraum des internen Zählers (4096 Stufen) verteilt werden. Diese Lösung wäre optimal, da sie alle 16 Kanäle eines einzelnen Chips beachtet. | ||
+ | |||
+ | Leider hat dieser Lösungsweg nicht funktioniert. Das Flackern ist deutlich größer geworden. Eventuell gibt es hier auch einen HW-Bug im Chip selbst. Das Problem wurde auch von anderen Nutzern berichtet. | ||
+ | |||
+ | Idealerweise könnte bei dieser Lösung auch der Clock der PWM Chips über eine Hardwareverdrahtung synchronisiert werden und der Offset über alle Chips angewandt werden. | ||
+ | |||
+ | ==== Workaround unterschiedliche Clocks ==== | ||
+ | Würden sich die PWM Startflanken der verschiedenen Chips nur kurz treffen, würde man diesen Helligkeitsausfall vermutlich nicht bemerken. Zu diesem Zweck haben wir die PWM Frequenzen für die einzelnen Chips unterschiedlich ausgelegt. Wichtig ist, dass die einzelnen Frequenzen unabhängig von einander sind, also die harmonischen Schwingungen (Oberwellen) nicht auf die Grundfrequenz des anderen Chips oder auf deren harmonische Schwingungen fallen. | ||
+ | |||
+ | Dieser Workaround ist auch in unserer aktuellen Software zu finden. Problematisch wird er allerdings, wenn Verbraucher mit größerer Last an nur einem Chip hängen. Bei uns zum Glück nicht der Fall :> | ||
== Sonstiges == | == Sonstiges == |
Aktuelle Version vom 19. Mai 2014, 10:12 Uhr
dmx2rgb Status: stable | |
---|---|
Beschreibung | DMX empfangen, LEDs dimmen! |
Autor: | krisha, schinken |
PayPal |
Beschreibung
Um diverse LED-Stripes in unserer Lounge steuern zu können, wurde eine Platine benötigt. Hierfür bot sich DMX an, da schon diverse LED-Bars & Movingheads vorhanden sind und somit der Bus mitgenutzt werden kann. Ausserdem bietet dieser Bus die Möglichkeit später mehrere dmx2rgb-Platinen einzubinden.
krisha entwickelte hierfür in EAGLE eine Platine in der Größe 95x90mm. schinken schrieb hierfür in kurzer Zeit eine Software für den µC und richtete hierfür einen Raspberry Pi mit OpenLighting ein.
Der Sourcecode und die EAGLE-Dateien stehen hier zur Verfügung: dmx2rgb
Hardware
Story
Die Hardware wurde auf einer eigenen Platine aufgebaut, da der Umfang für ein Breadboard zu groß gewesen wäre. Um die eigene Platine herzustellen, wollten wir diese zuerst selber ätzen. Nachdem das hierfür benötigte Material allerdings leicht alt war (es war wortwörtlich steinhart), entschieden wir uns dafür die Platine so zu bauen, dass wir sie selbst fräsen können und haben dafür möglichst wenige Durchkontaktierungen verwendet, sowie eine Massefläche auf der Oberseite der Platine plaziert.
Nach etlichen Fräsversuchen und dem mehrmaligen Kauf neuer Fräser sowie darauffolgendem Fehlschlag, entschieden wir die Platine fertigen zu lassen. Nach nur 3 Tagen hatten wir eine geätze Platine mit Durchkontaktierungen in der Hand.
Danke an p.t.flea für den Fräs-Support.
Aufbau
Platine
Für die Herstellung der Platine wurde der Shop pcb-devboards gewählt, da dort Platinen für wenig Geld gefertigt werden. Durch diesen Shop ergab sich auch die ungewöhnliche Platinengröße. Außerdem liefert dieser Hersteller Platinen mit chemisch hergestellten Durchkontaktierungen. Auf einen Lötstopplack muss allerdings verzichtet werden.
DMX
Der DMX Bus basiert auf RS-485. Um die differentiellen Pegel zwischen -7V bis +12V zu verarbeiten, wurde ein SN75176B verbaut. Dieser Chip wandelt die Differenzialspannung auf TTL Pegel. Hierbei ist unbedingt auf die Reihenfolge der Eingänge zu achten (DMX Hot, DMX Cold), damit das Signal nicht invertiert am Prozessor anliegt.
Control & Accessoires
Das TTL Signal wird mit einem Atmega 168P über den eingebauten UART empfangen. Am µC befinden sich zudem 3x LEDs zur Statusanzeige, sowie 8 Lötbrücken um die DMX Adresse zu vergeben. Für die Spannungsversorgung der Platine wurde ein einfacher 78L05 eingesetzt. Der Prozessor wird über einen 16 MHz Quarz in Schwingung versetzt, damit auch die 250kHz von DMX ohne Abweichungen möglich sind. Die Ausgangstreiber sind über i²c mit 400kHz angebunden.
Output
Der I²C Bus ist mit 3 PWM Chips von NXP verbunden. Diese ICs erzeugen 16 unabhängige PWM Kanäle. An diese sind Dual N-FETs als Treiber angeschlossen. Diese FETs können bis zu 5A Peak und sind eigentlich für unseren Anwendungsfall und die Leiterbahnbreite zu groß gewählt. Aufgrund von 2 FETs in einem Gehäuse und dem günstigen Preis wurden sie dennoch verbaut.
Alternativ kann hier aber auch ein schwächerer FET eingesetzt werden (kompatibel: IRF7301). Es empfiehlt sich die 12V Leiterbahn zu verstärken, z.B. durch Auftragen von Lötzinn oder einem seperaten Kabel, sollte etwas mehr Strom benötigt werden. Für den I²C Bus empfiehlt es sich bei 400kHz jeweils einen 1,5k Ohm Pullup zu verwenden.
Bauteile
Menge | Bauteil | Beschreibung | Preis |
---|---|---|---|
1 | Atmega168P | Microcontroller | ? |
3 | PCA9685 | 16-Kanal PWM Chip | 0,89 € |
24 | IRF7303 | n-Kanal MOSFET Treiber | 1,22 € |
1 | SN75176B | RS-485 Differenztreiber | 0,26 € |
1 | 78L05 | Spannungsregler | 0,16 € |
1 | 16Mhz Quarz | Quarz | 0,18 € |
x | Kondensatoren | zur Stabilisierung | |
x | Widerstände | als Pull-Ups |
Software
Für den Atmega 168P wurde eine Software mit avr-gcc in C entwickelt. Die Aufgabe beschränkt sich auf das Empfangen von DMX-Signalen in einem bestimmen Kanalbereich und dem Ansteuern der PWM-Chips. Der Prozessor wurde über ISP mit einen AVR ISP mkII Klon (USBprog) programmiert.
DMX empfangen
Um DMX zu empfangen werden die Bytes im USART-Interrupt empfangen. Eine beginnende DMX übertragung wird mit einem Stop-Bit markiert. Das erste empfangene Byte muss hier den Wert 0x00 enthalten um als gültige Übertragung erkannt zu werden. Das Interrupt-Register muss mit 2 Stop-Bits und 8 Daten-Bits konfiguriert werden.
In unserem Fall haben wir nur die DMX-Kanäle gespeichert, die für uns interresant sind. Dies wird über die Konstante DMX_CHANNEL und DMX_NUM_CHANNELS gesteuert und beginnend mit dem "1" für den ersten Kanal im Buffer abgelegt.
Die Frequenz von DMX ist 250kHz und kann mit der einfachen Formel:
UBRR0 = (F_CPU / (DMX_BAUD * 16L) - 1);
im USART-Register gesetzt werden. Hierbei ist F_CPU die Frequenz in Hertz (in unserem Fall 16000000 Hz ≙ 16MHz). Sollte die Baudrate etwas abweichen, kann auch
UBRR0 = ((F_CPU+DMX_BAUD*8)/(DMX_BAUD*16)-1)
verwendet werden, um eine genauere Taktfrequenz zu erreichen.
PWM setzen
Um mit den PCA9685-Chips zu kommunizieren wird i²c mit 400 kHz verwendet. Hierbei hat jeder vorhandene Chip eine eigene i²c-Adresse, welche per Drahtbrücken auf der Hardware festgelegt wurden. Um auf den PWM-Chip zu schreiben wird die Basis-Adresse verwendet. Die LED_ENABLE-Leitung muss ausserdem auf GND gelegt werden, um eine PWM-Ausgabe zu erwirken.
Um Daten vom IC zu lesen, muss die Basis-Adresse+1 verwendet werden. Da wir keinerlei Daten zurücklesen, wird diese Funktionalität nicht verwendet. Hierüber wäre es möglich die aktuellen PWM-Werte rückzulesen.
Für die i²c-Kommunikation wurde die twimaster-Bibliothek von Peter Fleury verwendet.
Um die Helligkeitskurve von LEDs dem menschlichen Auge anzugleichen wurde ein CIEL12-Lookup-Array mit 256 Werten verwendet. Mit der Funktion pca9685_led_pwm kann im Wertebereich von 0-255 die Helligkeit der LED gesetzt werden, was dem Kanal-Wertebereich von DMX entspricht. Jeder Kanal wird zurzeit noch einzeln gesetzt - es besteht aber die Möglichkeit durch dem Auto Register Increment des Chips alle Kanäle auf einmal zu setzen, ohne für jeden Kanal eine neue I²C-Kommunikation zu starten.
Chip | Ausgänge | Adresse |
---|---|---|
1 | 0-15 | 0b1000001x |
2 | 16-32 | 0b1000011x |
3 | 17-48 | 0b1000111x |
Das letzte Bit bestimmt, ob der Zugriff lesend oder schreibend erfolgt. In unserem Fall reicht es, dieses Bit auf 0 zu setzen.
Problem Lasteinbruch
Die PWM Chips werden von einer internen Clock (25MHz) gespeist. Das hat zur Folge, das ohne weitere Beachtung, alle Kanäle eines ICs zur selben Zeit das PWM Signal starten. Dies führt zu einem hohem Schaltimpuls und Spannung bricht bei uns mit 16 Kanälen um ca. 1 Volt ein.
Verwendet man nun zusätzlich Kanäle des zweiten Chips, kommt es in regelmäßigen Abständen zu einer Überlagerung und Aufsummierung des Spannungseinbruchs. Dies äußert sich durch flackern. Hintergund: Die beiden Clocks sind nicht synchron und minimal verschieden. Dadurch verschieben sich die Clocks zeitlich zu einander. Im Worstcase befinden sich die PWM Startflanken der unterschiedlciehn ICs mehrere Takte zeitlich aufeinander.
Lösung Startoffset
Eine saubere Lösung wäre hier die PWM Flanken immer zu unterschiedlichen Zeitpunkten einzuschalten. So kann die Last relativ gleichmäßig auf den Zeitraum des internen Zählers (4096 Stufen) verteilt werden. Diese Lösung wäre optimal, da sie alle 16 Kanäle eines einzelnen Chips beachtet.
Leider hat dieser Lösungsweg nicht funktioniert. Das Flackern ist deutlich größer geworden. Eventuell gibt es hier auch einen HW-Bug im Chip selbst. Das Problem wurde auch von anderen Nutzern berichtet.
Idealerweise könnte bei dieser Lösung auch der Clock der PWM Chips über eine Hardwareverdrahtung synchronisiert werden und der Offset über alle Chips angewandt werden.
Workaround unterschiedliche Clocks
Würden sich die PWM Startflanken der verschiedenen Chips nur kurz treffen, würde man diesen Helligkeitsausfall vermutlich nicht bemerken. Zu diesem Zweck haben wir die PWM Frequenzen für die einzelnen Chips unterschiedlich ausgelegt. Wichtig ist, dass die einzelnen Frequenzen unabhängig von einander sind, also die harmonischen Schwingungen (Oberwellen) nicht auf die Grundfrequenz des anderen Chips oder auf deren harmonische Schwingungen fallen.
Dieser Workaround ist auch in unserer aktuellen Software zu finden. Problematisch wird er allerdings, wenn Verbraucher mit größerer Last an nur einem Chip hängen. Bei uns zum Glück nicht der Fall :>
Sonstiges
Bugs/Mögliche Verbesserungen:
- USBProg: Binäres File darf nicht size % 64 == 54 sein
- Aufgrund, dass die Platine anfangs für das selber ätzen ausgelegt war, sind nicht alle Leitungen optimal verlegt
- Massepad für DMX fehlt - auch wenn es nicht unbedingt benötigt wird, sollte die Schirmung angeschlossen werden
- Leiterbahnbreite der 12V Leitung zu gering, aber durch Platinengröße beschränkt.
- FETs nicht optimal verlegt - es ist ein Software-Mapping nötig und Durchkontaktierungen könnten sich einsparen lassen.