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

Microcontroller, Steuerungen, Protokolle und und und.

Moderatoren: thomasf, random

Antworten
Benutzeravatar
random
Beiträge: 2160
Registriert: Fr 03 Aug, 2001 12:00 pm
Do you already have Laser-Equipment?: Dynamics, Easy-/NetLase, NetLaseLC
Some devices that emit light.
Wohnort: München - 85540 Haar
Kontaktdaten:

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

Beitrag von random » So 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: Alles auswählen

#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
Zuletzt geändert von random am Mo 27 Feb, 2006 8:59 pm, insgesamt 2-mal geändert.

schobi
Beiträge: 272
Registriert: Mo 26 Sep, 2005 9:28 am
Wohnort: Regensburg
Kontaktdaten:

Beitrag von schobi » So 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

Benutzeravatar
random
Beiträge: 2160
Registriert: Fr 03 Aug, 2001 12:00 pm
Do you already have Laser-Equipment?: Dynamics, Easy-/NetLase, NetLaseLC
Some devices that emit light.
Wohnort: München - 85540 Haar
Kontaktdaten:

Beitrag von random » So 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:
Zuletzt geändert von random am Mo 27 Feb, 2006 8:58 pm, insgesamt 1-mal geändert.

Benutzeravatar
random
Beiträge: 2160
Registriert: Fr 03 Aug, 2001 12:00 pm
Do you already have Laser-Equipment?: Dynamics, Easy-/NetLase, NetLaseLC
Some devices that emit light.
Wohnort: München - 85540 Haar
Kontaktdaten:

Beitrag von random » Mo 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

Benutzeravatar
lightfreak
Beiträge: 644
Registriert: Di 09 Okt, 2001 12:00 pm
Do you already have Laser-Equipment?: of course...
Wohnort: Nitzahn
Kontaktdaten:

Beitrag von lightfreak » Mo 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

Benutzeravatar
random
Beiträge: 2160
Registriert: Fr 03 Aug, 2001 12:00 pm
Do you already have Laser-Equipment?: Dynamics, Easy-/NetLase, NetLaseLC
Some devices that emit light.
Wohnort: München - 85540 Haar
Kontaktdaten:

Beitrag von random » Mi 01 Mär, 2006 10:19 pm

Lightfreak hat geschrieben:
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:

Antworten

Zurück zu „Microcontroller & Steuerungen“

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast