Das Fnordlicht(Der Name wurde aus dem ähnlichen Projekt von www.lochraster.org übernommen, da er mir gut gefiel und mein Fnordlicht v1 ein Nachbau sein sollte.) ist ein DMX gesteuertes 5-Kanal LED-Licht. Damit kann ich RGBWY(Rot, Grün, Blau, Weiß, Gelb) einzeln Dimmen und so sehr viele verschiedene Farben erzeugen. Das genau gleiche Prinzip findet Anwendung bei professionellen LED-Bühnenscheinwerfern. Das Herzstück des Fonrdlichts ist ein Atmega 48 und für das Licht sorgen ~80LEDs. Die Materialkosten pro Einheit würde ich auf ca 15 - 20€ schätzen.
Das Fnordlicht besteht damit aus 3 wesentlichen Teilen:
Punkt 3 ist noch der einfachste, man schaltet 3 - 5 LEDs(je nach Spannung pro LED) in reihe und schließt sie über einen Vorwiderstand an 12V an. Dann wird jedes dieser Cluster über ein Transistor geschaltet. Dieser braucht nun das PWM Signal, damit wir gescheit dimmen können.
Das in Punkt 2 erwähnte PWM(Puls-Weiten-Modulation), das ein verfahren zum Dimmen von DC-Geräten genutzt wird und darauf aufbaut, den Strom in einem Gewissen Verhältnis An, bzw. Aus zu schalten und das so schnell, das wir das z.B bei LEDs nicht mehr wahrnehmen oder bei DC-Motoren der Schwung des Ankers erhalten bleibt. Da Atmel uns sehr entgegen kommt und den Atmegas eine Hardware-PWM Funktion spendiert hat, ist auch das kein großes Problem für den Amateur Elektroniker ;)
Kommen wir nun zum etwas trickreicheren Unterfangen mit dem DMX(Digital Multiplex, ein auf RS485 Aufbauendes Protokoll mit Anwendung in der Bühnen- und Veranstaltungstechnik zum steuern von Beleuchtungsgeräten, das keine Terminitaion benötigt und wo jeder Empfänger parallel zu den Datenleitungen geschaltet wird). Wir brauchen einen RS-485 Transreciver und einen DMX sender(ich verwende ein selbstgebautes uDMX: uDmx Projektseite). Als Transreciever verwende ich einen auf moderner CMOS Technologie basierenden MAX485, der Pingleich mit dem SN75176 ist.
Code:
#define F_CPU 16000000 #define dmx_size 7 // number of used DMX channels #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #define BAUD 250000L // DMX512 #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) #if ((BAUD_ERROR>10) || (BAUD_ERROR<-10)) #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! #endif // global variables volatile uint8_t DmxArray[dmx_size]; // DMX data volatile uint8_t flag; // new data available int main(void) { DDRB = 0xff; DDRD = (0xff & (~(1<<PD0))); PORTB = 0; PORTD = 0; flag = 0; //PWM config TCCR0A = (1 << COM0A1) | (1 << COM0B1) | (1 << WGM01) | (1 << WGM00); TCCR0B = (1 << CS02); TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM10); TCCR1B = (1 << CS12)| (1 << WGM12); TCCR2A = (1 << COM2A1) | (1 << COM2B1) | (1 << WGM20) | (1 << WGM21); TCCR2B = (1 << CS22) | (1 << CS21); OCR0A = 128; OCR0B = 128; OCR1B = 128; OCR1A = 128; OCR2A = 128; // UART config UBRR0H = UBRR_VAL >> 8; UBRR0L = UBRR_VAL & 0xFF; UCSR0B = (1<<RXCIE0) | (1<<RXEN0); for(int i = 0; i < dmx_size; i++) { DmxArray[i] = 255; } sei(); // main loop while (1) { if (!flag) { set_sleep_mode(SLEEP_MODE_IDLE); sleep_mode(); } else { flag=0; OCR0A = 255 - DmxArray[0]; OCR0B = 255 - DmxArray[1]; OCR1B = 255 - DmxArray[2]; OCR1A = 255 - DmxArray[3]; OCR2A = 255 - DmxArray[4]; } } } // UART RX complete interrupt ISR(USART_RX_vect) { static uint16_t dmx_channel=0, dmx_base=1; uint8_t status, data; int16_t index; // read UART data, also clears interrupt flag status = UCSR0A; data = UDR0; if (status & (1<<FE0)) { // frame error if (data==0) { // break -> DMX Reset dmx_channel=0; dmx_base = /*(~PINB & 0xFF)+1*/1; //if (~PIND & (1<<PD6)) dmx_base +=256; flag=1; // trigger update } else // rx error dmx_channel++; } else { index = dmx_channel-dmx_base; if (index>=0 && index<dmx_size) DmxArray[index]=data; dmx_channel++; } }
Da 80 LEDs schon eine ganze Menge sind und es mit allen anderen Bauteilen zusammen weit über 100 Teile ergeben hat, habe ich mir ein Layout gemacht und auf Platine geätzt:
Da mir aber der Ätzvorgang etwas misslungen war, musste ich mit Kupferlackdraht(Gefühlte 500m ;) ) nachhelfen, was zu einem ziemlichen Chaos unter der Platine führte :
Das Bild zeigt nur einen Ausschnitt des Chaos, mit dem ich mich stundenlang beschäftigte, nur um alle Fehler zu beseitigen. Aber die Arbeit hat sich gelohnt.
TODO: Bilder vom Laufenden betrieb einfügen