-
        

Ergebnis 1 bis 7 von 7

Thema: Atmega Led Fading Software PWM

  1. #1
    Tux12Fun
    Gast

    Atmega Led Fading Software PWM

    Anzeige

    Hallo,

    im Moment versuche ich gerade mit einer RGB Led und meinem ATMEGA32 ein Fading der Farben zu bekommen. Erste Gehversuche werden euch wohl sehr kompliziert vorkommen. Deshalb, meine Frage, wie könnte ich so etwas einfach Realisieren.

    Mein Code sieht im Moment so aus und macht auch noch nicht ganz was er soll. Das ich bisher nur eine Farbe je heller und dunkler bringe.

    Leider habe ich bisher ach noch keine Erfahrung mit den Timern im ATMEGA. Ich brauche wohl dazu noch sowas wie Threads, falls es die im ATMEGA gibt.

    Mein Code:
    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <stdio.h>
    #include <inttypes.h>
    #include <string.h>
    #include <util/delay.h> 
    
    #define MCU = AVR_ATmega32 
    #define F_CPU  16000000       
    
    #include <inttypes.h>
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/pgmspace.h>
    
    #define DEF_MAX 3000
    
    int main(void){
    
     
        DDRC |= (1<<PC0);           
    	DDRC |= (1<<PC1);           
    	DDRC |= (1<<PC2);           
     
    	PORTC &= ~(1<<PC0);	  //AUS
    	PORTC &= ~(1<<PC1);	  //AUS
    	PORTC &= ~(1<<PC2);	  //AUS
    	 
    	 _delay_ms(5000);
    	 
        while(1) {
     
    		//Fade in Red
    		for (int i=DEF_MAX; i > 0; i--){		
    			PORTC &= ~(1<<PC0);	  //AUS
    			_delay_us(i);
    			PORTC |= (1<<PC0);   //AN
    			_delay_us(1600);
    			
        	}
    		_delay_ms(3000);
    	
    		//Fade out Red
    		PORTC |= (1<<PC0);   //AN
    		_delay_ms(3000);
    		for (int i=0; i < DEF_MAX +800; i++){  //Rot geht aus, evtl. Ist es heller (+800)
    			PORTC &= ~(1<<PC0);	  //AUS
    			_delay_us(i);
    			PORTC |= (1<<PC0);   //AN
    			_delay_us(1600);
    			
        	}
    		PORTC &= ~(1<<PC0);	  //AUS
    
    		
    		
    		//Fade in Blue
    		for (int i=DEF_MAX; i > 0; i--){
    			PORTC &= ~(1<<PC1);	  //AUS
    			_delay_us(i);
    			PORTC |= (1<<PC1);   //AN
    			_delay_us(1600);
    			
        	}
    		_delay_ms(3000);
    	
    		//Fade out Blue
    		PORTC |= (1<<PC1);   //AN
    		_delay_ms(3000);
    		for (int i=0; i < DEF_MAX; i++){
    			PORTC &= ~(1<<PC1);	  //AUS
    			_delay_us(i);
    			PORTC |= (1<<PC1);   //AN
    			_delay_us(1600);
    			
        	}
    		PORTC &= ~(1<<PC0);	  //AUS
    
    
    		
    		//Fade in green
    		for (int i=DEF_MAX; i > 0; i--){
    			PORTC &= ~(1<<PC2);	  //AUS
    			_delay_us(i);
    			PORTC |= (1<<PC2);   //AN
    			_delay_us(1600);
    			
        	}
    		_delay_ms(3000);
    	
    		//Fade out green
    		PORTC |= (1<<PC2);   //AN
    		_delay_ms(3000);
    		for (int i=0; i < DEF_MAX; i++){
    			PORTC &= ~(1<<PC2);	  //AUS
    			_delay_us(i);
    			PORTC |= (1<<PC2);   //AN
    			_delay_us(1600);
    			
        	}
    		PORTC &= ~(1<<PC2);	  //AUS
    
    
    		
    	}
     
        return 0;
    }
    Meine Beschaltung. ATMEGA Minimalverkabelung mit Quarz.
    An PDC0 - 3 hängt die RGB Led und an Minus über einen Widerstand.
    An jedem + - Pärchen der Led hängt ein 220µF Elko

    PCD0 = rot
    PDC1 = blau
    PDC2 = grün

    PDC0 -------------- Elko+ ---------- LED+
    MINUS ------------- Elko- ----------- LED -

    Ich hoffe ich konnte meinen bisherigen Aufbau ein wenig rüber bringen.

    Danke schon im Voraus für eure Hilfe.

  2. #2
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    13.05.2007
    Alter
    26
    Beiträge
    183
    Ich hab sowas für zwei RGB-LEDs mal per Software-PWM gemacht.
    => http://johannesneumann.net/index.php...pwm-mit-fading
    Vielleicht hilft dir das ein bisschen.

    Ansonsten: Ja, Timer kannst du im Prinzip wie Threads benutzen. Du kannst beim Overflow einen Interrupt auslösen lassen, der dann alle X Prozessortakte das Programm unterbricht und eine ISR ausführt. In die kannst du deine PWM-Erzeugung packen: In jedem Durchlauf wird eine Variable hochgezählt. Hat sie den Wert der Helligkeit deiner LED erreicht, so wird der Pin auf LOW gezogen. Wenn diese Variable den Maximalwert erreicht hat, wird sie auf Null gesetzt und alle Pins auf HIGH gezogen und dann gehts von vorn los.

    Das Faden kann in einer Schleife passieren, insofern du nicht was anderes abarbeiten willst, während gefadet wird. Unter dem Link oben findest du nen c-File, was genau das macht. Das Faden wird über einen anderen Timer geregelt, sodass du im Programm schon was anderes machen kannst während die LEDs ihre Farbe wechseln.


    Wieso packst du da eigentlich einen Elko ran? Das ist doch sinnlos: Der läd sich auf, wenn die PWM gerade High ist und wenn sie Low geht, leuchtet die LED mit der gespeicherten Energie weiter... Damit hast du kein Dimmen mehr, sondern kontinuierliches Leuchten. Nimm die Elkos weg, dann wirds gehen.

    Bääääär

    [Edit] Aschso, für richtiges Dimmen wäre Gamma-Korrektur noch ne sinnvolle Sache. Siehe ebenfalls mein Link und Sourcecode.

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    1.892
    Im Prinzip hat der ATMEGA32 3 Hardware PWM Quellen mit dazugehörigen Ausgängen.

    OCR1A, OCR1B und OCR2.
    Da der Timer 2 nur ein 8Bit Timer ist, kann man damit nur 256 Helligkeiten einstellen.

    Bei meinem LED Spot ( DMX ) hab ich auch den Timer 1 als 8 Bit PWM laufen lassen, da das DMX Protokoll ohnehin nur 256 Dimmstufen zulässt.

    Die Gamma Korrektur könnte man über Look Up Tables für jede Helligkeit realisieren. Allerdings wird man hier nicht das volle Helligkeitspotential der LED's nutzen können, da Grüne und Rote LED's effektiver sind als Blaue.

    Rot und Grün werden also auch bei Voller Helligkeit immer noch gedimmt werden müssen.

  4. #4
    Tux12Fun
    Gast
    Die Elkos sorgen im Moment bei mir dafür dass die LED langsam die Helligkeit ändert. Ich schalte quasi immer einer konstante Zeit ein und eine immer länger werdende Zeit aus. Dadurch hat der Elko immer weniger Saft den die Led zieht. Ohne den Elko ist es bei mir im Moment so dass die Led zum Blinken anfängt. Zumindest wenn ich dann die Zeiten ändere.

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    13.05.2007
    Alter
    26
    Beiträge
    183
    Den Elko braucht man nicht, wenn die PWM Frequenz hoch genug ist. Das Auge ist echt träge in der Hinsicht.
    Bei deinem Programm ist das Problem, dass du die An-Zeit unangetastet lässt und die Aus-Zeit verlängerst. Das Problem dabei ist, dass du damit de-facto die PWM-Frequenz kontinuierlich veränderst. Richtig wäre:
    X Takte an, Y-X Takte aus. Wenn du die LED also einen Takt länger an hast, ist sie auch einen Takt weniger aus, sodass die Zyklus-Zeit immer gleich lang bleibt.

    Hast du dir mal meinen Link zu Gemüte geführt? Da ist das genau so erledigt.
    Code:
    ISR(TIMER2_OVF_vect) {	
    	
    	TimerCounter++;
    	if (TimerCounter > 1023 ) {
    		TimerCounter = 0;
    		if (lr1 != 0) { n1_Port |= (1 << n1_Pin);}
    		if (lr2 != 0) { n2_Port |= (1 << n2_Pin);}
    		if (lr3 != 0) { n3_Port |= (1 << n3_Pin);}
    		if (lr4 != 0) { n4_Port |= (1 << n4_Pin);}
    		if (lr5 != 0) { n5_Port |= (1 << n5_Pin);}
    		if (lr6 != 0) { n6_Port |= (1 << n6_Pin);}
    	} 
    	if (TimerCounter > lr1) {
    		n1_Port &= ~(1 << n1_Pin);
    	}
    	if (TimerCounter > lr2) {
    		n2_Port &= ~(1 << n2_Pin);
    	}
    	if (TimerCounter > lr3) {
    		n3_Port &= ~(1 << n3_Pin);
    	}
    	if (TimerCounter > lr4) {
    		n4_Port &= ~(1 << n4_Pin);
    	}
    	if (TimerCounter > lr5) {
    		n5_Port &= ~(1 << n5_Pin);
    	}
    	if (TimerCounter > lr6) {
    		n6_Port &= ~(1 << n6_Pin);
    	}
    }
    lr1..lr6 Das sind die Helligkeitswerte der LEDs. Diese Function wird vom Timer aufgerufen (Overflow des Timers). Was passiert sollte anhand des Codes eigentlich ersichtlich sein: Erreicht die Laufvariable 1024, so wird sie auf Null gesetzt und alle LEDs eingeschaltet. Dann läuft sie wieder hoch bis 1024. Erreicht sie dabei den Helligkeitswert einer LED so wird diese Ausgeschaltet. Die Gesamtlaufzeit dieses Zyklus ist also immer 1024 Durchläufe (also eine konstante Zeit). Das Verhältnis von An und Aus ergibt also die Helligkeit der LED.

    Bääääär

  6. #6
    Erfahrener Benutzer Roboter Genie Avatar von Rabenauge
    Registriert seit
    13.10.2007
    Ort
    Osterzgebirge
    Alter
    49
    Beiträge
    1.245
    http://www.mikrocontroller.net/articles/LED-Fading

    Hab ich erst die Tage drinnen gestöbert, da ich für mein Display auch was ähnliches machen möchte, nur so plumps, an und plumps, aus ist mir zu öde..

  7. #7
    Tux12Fun
    Gast
    Hallo,

    ja, ich habe deinen Quellcode gerade schon am ATMEGA bei mir laufen und studiere den Code. Danke noch für die Takterklärung.

Berechtigungen

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