-         

Ergebnis 1 bis 10 von 10

Thema: Ambilight für den PC

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    16.08.2006
    Beiträge
    34

    Ambilight für den PC

    Anzeige

    Hi Leute,

    nachdem ich hier nun schon fleißig mitgelesen habe und die eine oder andere Frage losgeworden bin, wird es Zeit, dass ich mein erstes großes Projekt hier mal vorstelle. Seit einiger Zeit verfolge ich diesen Beitrag, da sich dort im Moment allerdings nicht viel Neues tut, habe ich mich entschlossen, mein eigenes Ambilight für meinen PC zu entwickeln:

    Im Netz habe ich Boblight gefunden, welches über die RS232 Schnittstelle die RGB Daten für den rechten, oberen und linken Teil des Bildschirms bereitstellt. Somit musste ich mich um die PC-seitige Software nicht kümmern. Dies hätte ich eh nicht hingekriegt. Ich musste also nur noch einen µC so programmieren, dass er die Daten empfängt und als PWM auf die LED-Leisten gibt. Aber erstmal zu den LED-Leisten selbst:




    Als RGB Leisten habe ich welche von ebay genommen. Auf einem Strip sind drei Cluster mit je 3x3 Superflux Leds und den entsprechenden Widerständen für einen direkten Betrieb an 12V angebracht. Die Strips lassen sich zwischen den Clustern trennen. Für rechts und links an meinem 22" Monitor passt genau ein Strip, für oben habe ich zwei Strips zusammengefügt, so dass dieser aus 5 Clustern besteht. Die Streifen sind beweglich auf einem, bzw. zwei Alustreifen (Baumarkt-Meterware) gelagert, so dass ich die Strips ausrichten kann. Dazu habe ich 3mm Messingdraht an den Alustreifen geklebt und auf die überstehenden Enden Messingrohrstücke gesteckt, die ich vorher an den Enden etwas zusammengequetscht habe. An diesen Rohrstücken sind die Strips festgeklebt. So lassen sich die Strips ausrichten, ohne dass sie ihre Position aufgrund der Schwerkraft ändern. Die Alustreifen habe ich mit Tesa-Powerstrips auf dem Monitor befestigt.




    Die Hardware besteht aus zwei Mega88, einer empfängt die Daten über UART und bedient die linke Seite, sowie den blauen Kanal, Mitte. Die übrigen Daten werden an den zweiten Mega88 per UART weitergesendet, dieser dient nur als PWM-Chip. Es ist vorgesehen, über ein Poti die Helligkeit zu regeln, des Weiteren soll es ebenfalls möglich sein, anstatt der Steuerung über den PC, mit einem Poti die Farbe einzustellen, so dass man eine einheitliche Hintergrundfarbe für den Monitor einstellen kann. Dies hab ich aber noch nicht implementiert.

    Boblight sendet ein Paket von 9 Bytes, die die Farbinformationen halten. Die einzelnen Bytes kommen in einem Abstand von ca. 0.001 Sekunden an, zwischen den Paketen ist ein Abstand von ca. 0,01 Sekunden (einstellbar). Die Software für die Megas funktioniert bereits sehr gut, normaler Desktopbetrieb, Videos und DVD(mit dem VLC-Player) und Spiele, alles ist möglich. Da ich leider keine Videos aufnehmen kann, hier nur ein paar Standbilder, die vor allem die Ausleuchtung und Farbe der RGB-Leisten demonstrieren:
















    Nur Gelb hat meine Kamera irgendwie nicht gemocht, das sah total komisch aus (also aufm Bild, in Echt ist es super)

    Da die Leisten keine RGB Leds, sondern rote, grüne und blaue Leds nebeneinandern haben, sieht man bei Mischfarben ein paar Streifen oben und unten, aber das stört nicht wirklich.

    Mit einem Problem habe ich allerdings noch zu kämpfen, ab und zu geht die Beleuchung kurz aus und sofort wieder an. Dieses flackern ist recht unangenehm, erklären kann ich es mir aber nicht. Vielleicht könnt ihr ja mal einen Blick über den Code werfen, vielleicht fällt euch ja was auf, worans liegen kann. Dies ist übrigens die "schnelle" Version, ich habe auch noch eine langsamere Version, die vor der Weitergabe der Daten die empfangene Anzahl an Bytes pro Paket checkt, da taucht das Flackern nicht auf. Da aber die Leds auch bei der schnellen Version aktiv ausgeschaltet werden müssen (also per 0 0 0 0 0 0 0 0 0 von Boblight), kann ich mir das Flackern echt nicht erklären.

    Hier der Code für den Master: (an dem hängts, dass es flackert....)

    ambilight.c:
    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <stdavr.h>
    #include "fifo.h"
    #include "uart.h"
    
    #define F_CPU		14745600
    #define BAUDRATE	9600
    
    void initialize_IO(void);
    void initialize_IRQ(void);
    void initialize_TIMER0(void);
    void initialize_TIMER1(void);
    void initialize_TIMER2(void);
    //void initialize_ADC(void);
    
    int main(void)
    {	
    	initialize_IO();
    	initialize_IRQ();
    	//initialize_ADC();
    	initialize_TIMER0();
    	initialize_TIMER1();
    	initialize_TIMER2();
    	initialize_UART(BAUDRATE);
    	
    	// enable global interrupts
    	sei();
    	
    	while(1);
    
    	return 0;
    }
    
    void initialize_IO(void)
    {
    	// PWM-Pins als Output setzen
    	DDRD |= (1<<PD3)|(1<<PD5)|(1<<PD6);
    	DDRB |= (1<<PB3);
    }
    
    void initialize_IRQ(void)
    {
    	// enable Timer1 Overflow Interrupt
    	TIMSK1 = (1<<TOIE1);
    	
    	// enable AD-Converter Interrupt
    	//ADCSRA |= (1<<ADIE);
    }
    
    void initialize_TIMER0(void)
    {
    	// Timer0-Register
    	TCNT0 = 0;
    	
    	// Output Compare Pin Behaviour:
    	// clear OC0A and OC0B on compare match and set on TOP
    	TCCR0A |= (1<<COM0A1)|(1<<COM0B1);
    	
    	// Wave Form Generation:
    	// Fast PWM with TOP at 0xFF.
    	TCCR0A |= (1<<WGM01)|(1<<WGM00);
    	
    	// Initialy set the Ouput Compare Registers to zero:
    	OCR0A = 0x00;	
    	OCR0B = 0x00;
    		
    	// Start Timer with Prescaler of 256 --> f_Timer0 = 225Hz
    	TCCR0B |= (1<<CS02);
    }
    
    void initialize_TIMER1(void)
    {
    	// Timer1-Register initialisieren
    	TCNT1H = 0x00;
    	TCNT1L = 0x00;
    }
    
    void initialize_TIMER2(void)
    {
    	// Timer0-Register
    	TCNT2 = 0;
    	
    	// Output Compare Pin Behaviour:
    	// clear OC02A and OC2B on compare match and set on TOP
    	TCCR2A |= (1<<COM2B1)|(1<<COM2A1);
    	
    	// Wave Form Generation:
    	// Fast PWM with TOP at 0xFF.
    	TCCR2A |= (1<<WGM21)|(1<<WGM20);
    	
    	// Initialy set the Ouput Compare Registers to zero:
    	OCR2A = 0x00;	
    	OCR2B = 0x00;
    		
    	// Start Timer with Prescaler of 256 --> f_Timer2 = 225Hz
    	TCCR2B |= (1<<CS22);
    }
    
    /*void initialize_ADC(void)
    {
    	// Voltage Reference = AREF --> no Bit need to be set
    	// PC0 as first AD-Conversion --> no Bit need to be set
    	
    	// Set ADC Prescaler to 128 (--> F_ADC = 14745.6/128 = 115.2kHz)
    	// Set ADC Prescaler to 64  (--> F_ADC = 8000/128    = 125kHz)
    	ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
    	
    	// Set Auto Trigger Source to Timer1 Overflow --> at each new Datablock the ADC will be run
    	ADCSRB |= (0<<ADTS2)|(0<<ADTS1);
    	
    	//Digital Input Disable
    	//### write to 1, when digital input on this pin is not needed ### 
    	//DIDR0 = (1<<ADC0D)|(1<<ADC1D)|(1<<ADC2D)|(1<<ADC3D)|(1<<ADC4D)|(1<<ADC5D);
    
    	// Auto Trigger Enable
    	ADCSRA |= (1<<ADATE);
    
    	// Left-adjust result for 8-bit accuracy
    	ADMUX |= (1<<ADLAR);
    
    	// Enable ADC
    	ADCSRA |= (1<<ADEN);
    
    	//Start Conversion
    	ADCSRA |= (1<<ADSC);
    }*/
    
    
    
    /*ISR(SIG_ADC)
    {
    	if(BIT_IS_SET(ADMUX, MUX0)) {	// if ADC1 was selected
    		adc_value[COLOUR] = ADCH;
    		CLEAR_BIT(ADMUX, MUX0);		// select ADC0 as new ADC-Channel
    	}
    	else {							// if ADC0 was selected
    		adc_value[BRIGHTNESS] = ADCH;
    		SET_BIT(ADMUX, MUX0);		// select ADC1 as new ADC-Channel
    	}
    }*/
    
    ISR(SIG_OVERFLOW1)
    {
    	/* Timer1 läuft nach 0,00444 Sekunden über. Da er in der UART-
    	   Empfangs-ISR immer wieder zurückgesetzt und neu gestartet wird,
    	   läuft Timer1 nur zwischen zwei Datenpaketen über. Dann wird 
    	   der Counter der UART-Empfangs-ISR zurückgesetzt, um die richtige
    	   Zuordnung der PWM-Werte sicherzustellen */
    	uart_clear_counter();
    }
    uart.c:
    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <stdavr.h>
    #include "uart.h"
    #include "fifo.h"
    
    #define START_TIMER1	SET_BIT(TCCR1B, CS10)		//prescaler = 1
    #define STOP_TIMER1		TCCR1B &= ~((1<<CS12)|(1<<CS11)|(1<<CS10))
    #define CLEAR_TIMER1	TCNT1 = 0
    
    // FIFO-Objekt und Puffer für die Ausgabe
    #define BUFSIZE_OUT 5
    uint8_t outbuf[BUFSIZE_OUT];
    fifo_t outfifo;
    
    // Counter-Variable
    volatile uint8_t k = 0;
    
    void initialize_UART(const uint16_t baudrate)
    {
    	uint8_t sreg = SREG;
    	//uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16L*baudrate) - 1);
    	uint16_t ubrr = (uint16_t) ((uint32_t) 14745600/(16L*baudrate) - 1);
    	
    	UBRR0H = (uint8_t) (ubrr>>8);
    	UBRR0L = (uint8_t) (ubrr);
    	
    	// Interrupts kurz deaktivieren
    	cli();
    
    	// UART Receiver und Transmitter anschalten, Recieve-Interrupt aktivieren
    	// Data mode 8N1, asynchron
    	UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
    	UCSR0C = (1<<USBS0) | (3<<UCSZ00);
    	
    	//Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte)
    	do
    	{
    		UDR0;
    	}
    	while (UCSR0A & (1<<RXC0));
    	
    	// Rücksetzen von Receive und Transmit Complete-Flags
    	UCSR0A = (1<<RXC0)|(1<<TXC0);
    	
    	// Global Interrupt-Flag wiederherstellen
    	SREG = sreg;
    	
    	// FIFO für Ausgabe initialisieren
    	fifo_init (&outfifo, outbuf, BUFSIZE_OUT);
    }
    
    
    int uart_putc(const uint8_t c)
    {
    	int ret = fifo_put(&outfifo, c);
    	
    	UCSR0B |= (1<<UDRIE0);
    	
    	return ret;
    }
    
    void uart_clear_counter(void)
    {
    	k = 0;
    }
    
    
    ISR(SIG_USART_RECV)
    {
    	STOP_TIMER1;
    	CLEAR_TIMER1;
    	START_TIMER1;
    	
    	switch (k++)
    	{
    		case 0: 
    			OCR0B = UDR0;	 // Rot, Links
    			break;
    		case 1:
    			uart_putc(UDR0); // Weitersenden der Daten zum Slave (Rot, Mitte)
    			break;
    		case 2: 
    			uart_putc(UDR0); // Weitersenden der Daten zum Slave (Rot, Rechts)
    			break;
    		case 3: 
    			OCR0A = UDR0;	 // Grün, Links
    			break;
    		case 4: 
    			uart_putc(UDR0); // Weitersenden der Daten zum Slave (Grün, Mitte)
    			break;
    		case 5: 
    			uart_putc(UDR0); // Weitersenden der Daten zum Slave (Grün, Rechts)
    			break;
    		case 6: 
    			OCR2B = UDR0;	 // Blau, Links
    			break;
    		case 7: 
    			OCR2A = UDR0;	 // Blau, Mitte
    			break;
    		case 8: 
    			uart_putc(UDR0); // Weitersenden der Daten zum Slave (Blau, rechts)
    			break;
    	}
    }
    
    
    // Ein Zeichen aus der Ausgabe-FIFO lesen und ausgeben
    // Ist das Zeichen fertig ausgegeben, wird ein neuer SIG_UART_DATA_IRQ getriggert
    // Ist die FIFO leer, deaktiviert die ISR ihren eigenen IRQ.
    ISR(SIG_USART_DATA)
    {
    	if (outfifo.count > 0)
    		UDR0 = _inline_fifo_get(&outfifo);
    	else
    		UCSR0B &= ~(1<<UDRIE0);
    }
    Der Rest vom Code ist im Anhang.


    So, ich hoffe, euch gefällts!

    Markus
    Angehängte Dateien Angehängte Dateien

  2. #2
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    30.10.2005
    Beiträge
    139
    irgendwie traut sich hier wohl keiner zu schreiben sind wohl alle vor ehrfurcht erstarrt.

    also das is mal ein geniales ambilight! fetten respekt! die farbangleichung scheint ja super zu funktionieren. da kriegt man echt lust so ein reil auch mal aufzubauen. (hinter meinem monitor is noch alles dunkel )

    so long an thanks for all the fish

    ps: nonplusultra wäre, wenn du das layout mal als gif reinstellst, mein Eagle macht da irgendwie blöedsinn

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    16.08.2006
    Beiträge
    34
    Hi Felix, danke für Dein Lob!

    ja, es funktioniert echt gut, bis auf wie gesagt das Flackern. Mit einer anderen Version der Software tritt das nicht auf, dafür reagiert es mit ner geschätzten 1/10 Sekunde langsamer. Mal schauen, ob ich noch rausfinde, worans liegt.

    Das die eagle-Dateien nicht gehen ist klar. Mein Fehler. Habe eigene Libs verwendet. Hier die Bilder:





    Markus

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    09.07.2005
    Ort
    127.0.0.1
    Alter
    25
    Beiträge
    824
    Hallo Markus

    Erstmal Respekt, ist wirklich super geworden. Hat mich so begeistert, dass ich mir auch so eins baue.

    Wer die Ledleisten nicht bei ebay kaufen will kann dies auch über Ledsee (selber Händler) tun.

    Hast du BobLight auch schon mit 2 Bildschirmen ausprobiert? Ich habe gesehen das man da Display0 und Display1 auswählen kann, was das aber genau zu bedeuten hat weiss ich leider nicht.

    Gibt BobLight pro Seite eine Farbe an oder mehrere?

    mfg Luca
    Sollte ein Bild von mir nicht angezeigt werden, einfach eine PM schicken!

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    09.09.2006
    Alter
    28
    Beiträge
    841
    Blog-Einträge
    1
    hallo...das projekt gefällt mir.....

    könntest du deinen bildschirm eventuell mal drehen , sodass man sieht wie hell das licht ist wenn es ca 2-3 m von einer wand entfernt ist? auch wäre es schön wenn du mal 2 der 3 leisten zuhalten könntest (stück pappe oder so) das man die helligkeit einer leiste sieht

    danke dir...

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    16.08.2006
    Beiträge
    34
    Hallo,

    @Spion: leider habe ich nur einen Monitor, deswegen kann ich nicht sagen, was die Umschaltung zwischen display0 und display1 bewirkt und ob boblight ggf. die daten bei Anschluss zweier Monitore richtig berechnet.

    @dremler: also meinen Monitor brauche ich nicht zu drehen, um dir zu sagen, dass du in 2-3 Metern Entfernung nix mehr von den Leds sehen wirst. Dazu sind die viel zu schwach und auch der Austrittswinkel der Leds ist dafür zu groß. Aber dafür ist das Ambilight ja auch nicht gedacht. In der Regel steht der Fernseher oder der Monitor an der Wand. Bei dir nicht? Bei mir beträgt die Entfernung zwischen Monitor und Wand ca. 14cm. Für diese Entfernung und bestimmt auch noch bis zu einer Entfernung von 20-25cm sind die Leds ausreichend stark. Bilder, bzw. Fotos sind sowieso nicht sehr aussagekräftig, da man die Wirkung der Leds auf dem Bild mit der Einstellung über Belichtungszeit und Blende stark beeinflusse kann. Ich habe die Fotos so aufgenommen, dass sie ungefähr die wirkliche Ausleuchtung widergeben. Daran kannst Du dich orientieren. Mir langen die Leds von der Leistung. Wenn du mehr brauchst, kannst du ja zwei Leisten nebeneinander verwenden.

    @all: Berichtet dann mal von euren Ergebnissen, wenn ihr das Ambilight gebaut habt!

    Viele Grüße, Markus

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    09.09.2006
    Alter
    28
    Beiträge
    841
    Blog-Einträge
    1
    naja ich wollts ne für ein ambilight haben sondern sner art deckenstrahler bauen

    trotzdem danke

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    05.02.2008
    Beiträge
    38
    hi tolles Projekt, sieht echt klasse aus.

    ich hab gestern mal kurz nach dem Boblight gegoogled und leider nicht gefunden in welches Reihenfolge die Bytes gesendet werden. könntest du die mir bitte mal posten?

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    16.08.2006
    Beiträge
    34
    Code:
       switch (k++)
       {
          case 0:
             OCR0B = UDR0;    // Rot, Links
             break;
          case 1:
             uart_putc(UDR0); // Weitersenden der Daten zum Slave (Rot, Mitte)
             break;
          case 2:
             uart_putc(UDR0); // Weitersenden der Daten zum Slave (Rot, Rechts)
             break;
          case 3:
             OCR0A = UDR0;    // Grün, Links
             break;
          case 4:
             uart_putc(UDR0); // Weitersenden der Daten zum Slave (Grün, Mitte)
             break;
          case 5:
             uart_putc(UDR0); // Weitersenden der Daten zum Slave (Grün, Rechts)
             break;
          case 6:
             OCR2B = UDR0;    // Blau, Links
             break;
          case 7:
             OCR2A = UDR0;    // Blau, Mitte
             break;
          case 8:
             uart_putc(UDR0); // Weitersenden der Daten zum Slave (Blau, rechts)
             break;
       }
    Markus

  10. #10
    Benutzer Stammmitglied
    Registriert seit
    05.02.2008
    Beiträge
    38
    danke das war flott

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •