RGB-LED-Steuerung, für die, die es haben wollen...

Microcontroller, Steuerungen, Protokolle und und und.

Moderators: thomasf, random

Post Reply
User avatar
random
Posts: 2161
Joined: Fri 03 Aug, 2001 12:00 pm
Do you already have Laser-Equipment?: Dynamics, Easy-/NetLase, NetLaseLC
Some devices that emit light.
Location: München - 85540 Haar
Contact:

RGB-LED-Steuerung, für die, die es haben wollen...

Post by random » Sun 26 Feb, 2006 6:33 pm

Tach,

wer's haben will hier der Quellcode zur Ansteuerung einer RGB-LED.
Wer schimpfen will, solls tun, und es besser machen!
Dies ist für die Einsteiger gedacht, die Input zum uC-Lernen suchen ;-)


Code: Select all

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <stdlib.h>


/****************************
 RGB-LED-Steuerung
 26.02.06 Th. de Buhr
 
 Ansteuerung einer RGB-LED
 Port B: 0=R, 1=G, 2=B
****************************/ 


#define CLK 8000000

#define delay_ms(ms) _delay_loop_2(ms * (CLK/4000))
#define delay_us(us) _delay_loop_2(us * (CLK/4000000))

#define bit_on(BYTE, BIT)  BYTE |= 1 << BIT;
#define bit_off(BYTE, BIT) BYTE &= ~(1 << BIT);


volatile char colour=1, led_out=0;
volatile int time=0, pwm=0;
volatile char palette[12]={0,1,2,4,1,2,3,4,5,6,7};


SIGNAL(SIG_OVERFLOW0)
{	
	TCNT0 = 0x80;
	time++; 
	
	if(time>=100) time=0;
	
	if(time>pwm)
	{
		led_out=0;			
	}
	
	else
	{
		led_out=palette[colour];	
	}
	
	PORTB = led_out;		
}



int main()
{
	char i=0;
	//pwm = 0...100%, colour = 0...10
		
	DDRB=0xFF;
	PORTB=0x00;
	
	DDRD=0xFF;
	PORTD=0x00;
		
	//Timer 8Bit setup
	bit_off(TCCR0, CS00);		//Int. CLK/8
	bit_on(TCCR0, CS01);
	bit_off(TCCR0, CS02);
	 
	TCNT0 = 0x00;				//Timer-Reg. löschen
	 
	bit_on(TIMSK, TOIE0);		//Overflow-Int. enable


	sei();

	delay_ms(20);				//Pause, falls Programmierfehler den Programmierport überschreibt
	
	
	while(1)
	{	
		for(i=0; i<=100; i++)
		{
			pwm=i;					
			delay_ms(20);				
		}
		
		if((++colour) > 10) colour=1;
 	} 	
}


edit:
-----

Das ganze läuft auf einem Atmel AVR (AT Mega 8) und ist unter WinAVR geschrieben (d.h. main.c - file & Makefile)

PWM ist bei Mikrocontrollern die gängige Variante, wenn es darum geht, Lampen (oder Motoren :lol: ) zu dimmen.
Man legt nicht einen analogen Pegel auf die LED (Scheinwerfer, Gleichstrommotor), sondern schaltet den maximalpegel ständig an/aus.

Durch den Tastgrad (=An-Zeit / Aus-Zeit oder andersherum ;-) ) wird die Leistung im "Verbraucher" bestimmt und dadurch z.B. die Leuchtkraft einer LED, eines Scheinwerfers etc...

Das Programm verwendet zum Erzeugen des PWM (=Pulsweitenmodulation) einen 8Bit-Timer. In der ISR (Interrupt - Service-Routine) Wird der PWM generiert. Mit 2 Variablen lassen sich Farbe und Tastgrad (in %) bestimmen, die gesamte Impulslänge wird durch den Timer festgelegt.
Je höher die Periodendauer des PWM-Signals, desto "ruckelfreier" läuft das Dimmen bzw.der Motor.
Aber auch hier sind Grenzen gesetzt (z.B. die Induktivität eines Motors, die mag ja bekanntlich schnelle Spannungsänderungen gar nicht gerne und geht die Änderung ganz gemächlich an (anderes Thema!).


btw: Wens interessiert: "Architektur" des Programms ist Round Robin mit Interrupt. Wohl für solche Anwendungen das Gängigste...

edit: Bug korrigiert, s. unten.



Greetz
medra
Last edited by random on Mon 27 Feb, 2006 8:59 pm, edited 2 times in total.

schobi
Posts: 272
Joined: Mon 26 Sep, 2005 9:28 am
Location: Regensburg
Contact:

Post by schobi » Sun 26 Feb, 2006 7:50 pm

Hallo,

finde ich gut dass du deinen Quellcode veröffentlichst. Vielleicht wäre es noch interessant gewesen etwas näher zu erläutern auf welcher Plattform das läuft und wie es funktioniert. Sieht nach Atmel AVR aus. Nicht jedem Anfänger dürfte klar sein dass die Dimmung per PWM erfolgt (und was PWM überhaupt ist -> Pulsweitenmodulation).

Ich habe auf einem AVR einen 24kanal-Dimmer laufen (für 8 RGB Scheinwerfer), allerdings dürfte der spärlich kommentierte Assemblercode wenig hilfreich sein.

Was steuerst du damit an? Eine einzelne RGB-LED oder einen grossen Scheinwerfer mit vielen LEDs?

Gruß Tobias

User avatar
random
Posts: 2161
Joined: Fri 03 Aug, 2001 12:00 pm
Do you already have Laser-Equipment?: Dynamics, Easy-/NetLase, NetLaseLC
Some devices that emit light.
Location: München - 85540 Haar
Contact:

Post by random » Sun 26 Feb, 2006 8:21 pm

Hi,

ich steuer damit eine RGB-LED. Hab mir bei ebay 5 stück kommen lassen, um mal damit zu spielen. Das ist herausgekommen. Der ganze Aufbau ist auf einem Steckbrett (Mega8, ULN2803, 8MHz, 22pF, 7805 mit drumherum, RGB-LED mit Anode an +12V und Kathoden über 680Ohm an den ULN. Dazu ein Steckbrett-tauglicher Adapter für mein Programmierkabel :lol: )
Also wirklich denkbar einfacher Aufbau.

Bei uCs steckt die meiste Denkarbeit eh im Code.

Wenn einer den Schaltplan zum Nachbauen haben will, dann pinsel ich das gerne eben auf (Target 3001 bzw. als tif) :lol:


Ich schreibe meinen Code idR in C. Bin etwas zu faul für assembler (geht auch, C ist aber einfacher und lesbarer), dafür aber sehr für kryptische C-Fragmente zu haben :twisted:
Last edited by random on Mon 27 Feb, 2006 8:58 pm, edited 1 time in total.

User avatar
random
Posts: 2161
Joined: Fri 03 Aug, 2001 12:00 pm
Do you already have Laser-Equipment?: Dynamics, Easy-/NetLase, NetLaseLC
Some devices that emit light.
Location: München - 85540 Haar
Contact:

Post by random » Mon 27 Feb, 2006 8:57 pm

Haha ... nen Bock geschossen ;-)
Keiner gefunden ?

Hier:

if((++colour) > 10) colour=1;

der muss latürnich erst erhöhen und dann testen, ob > 10 :lol:


Greetz,
medra

User avatar
lightfreak
Posts: 644
Joined: Tue 09 Oct, 2001 12:00 pm
Do you already have Laser-Equipment?: of course...
Location: Nitzahn
Contact:

Post by lightfreak » Mon 27 Feb, 2006 9:12 pm

if((++colour) > 10) colour=1;

der muss latürnich erst erhöhen und dann testen, ob > 10
Tut er doch, ist doch nen preinkrement und kein postinkrement.

Gruß

Simon
----------------------------------------------------------------------------------
http://www.simon-light.de

User avatar
random
Posts: 2161
Joined: Fri 03 Aug, 2001 12:00 pm
Do you already have Laser-Equipment?: Dynamics, Easy-/NetLase, NetLaseLC
Some devices that emit light.
Location: München - 85540 Haar
Contact:

Post by random » Wed 01 Mar, 2006 10:19 pm

Lightfreak wrote:
if((++colour) > 10) colour=1;

der muss latürnich erst erhöhen und dann testen, ob > 10
Tut er doch, ist doch nen preinkrement und kein postinkrement.

Gruß

Simon
richtig, aber das Feld war da schon zuende, so zählt der nämlich bis 11.
Hab mich gewundert, dass eine "AUS"-Phase mit drin war ;-) Glücklicherweise stand da NULL im Speicher ;-) (zumindest auf den unteren 3 Bits, die ich nutze)

Hab das schon im Code oben bereits geändert ("edit: Bug korrigiert, s. unten."), anfangs stand da colour++

Greetz,
Medra


PS: Jetzt wäre zu überlegen, wie man einen 3-Kanal PWM (also alle 3 Kanäle unterschiedlich) in eine Timer-ISR bekommt ... :twisted:

Post Reply

Return to “Microcontroller & Steuerungen”

Who is online

Users browsing this forum: No registered users and 1 guest