RGB-LED an WS2801 dimmen

Fragen zu Schaltungen, Elektronik, Elektrik usw.

Moderator: T.Hoffmann

Terminus
User
User
Beiträge: 19
Registriert: Di, 10.04.12, 11:19

Do, 12.04.12, 16:57

Bisher ist ein ATMEGA8 mit externem 16MHz Takt geplant.
Borax
Star-Admin
Star-Admin
Beiträge: 12243
Registriert: Mo, 10.09.07, 16:28

Do, 12.04.12, 19:51

Und warum willst Du dann noch einen WS2801 'nachschalten'? Der Mega8 hat doch 4 PWM Kanäle. Da musst Du nur noch einen Mosfet pro Farbe als 'Verstärker' dran hängen und schon ist das 'fertig'. Ok, halt noch passende Vorwiderstände für die LEDs, aber das ist ja eigentlich kein Problem. Womit programmierst Du?
Terminus
User
User
Beiträge: 19
Registriert: Di, 10.04.12, 11:19

Fr, 13.04.12, 09:28

Ja, die Möglichkeit habe ich auch in Betracht gezogen. Aber ich muss leider bis 6 Farben gleichzeitig erzeugen.

Ich programmiere überwiegend in C, aufgrund der Größe des Projektes werde ich das hierbei auch machen.
Borax
Star-Admin
Star-Admin
Beiträge: 12243
Registriert: Mo, 10.09.07, 16:28

Fr, 13.04.12, 12:01

Dann nimm halt einen Atmega168 oder ATMEGA88. Ist pinkompatibel zum Mega8 und hat 6 PWM Ausgänge. Oder hat der µC noch sehr viel 'anderes' zu tun? Einen grob passenden Beispielcode gibt es hier:
viewtopic.php?f=31&t=2950&hilit=atmega168
Allerdings in Basic (BASCOM AVR).
stromflo
Mega-User
Mega-User
Beiträge: 304
Registriert: Mi, 31.12.08, 12:16

Fr, 13.04.12, 15:28

Guten Tag,

wenn man mit relativ einfachen mitteln die Helligkeit der erzeugten Farben verändern will, eignet sich das HSV Farbmodell ganz gut. H drückt den Farbton als Farbwinkel aus, S drückt die Sättigung in Prozent aus und V drückt die Helligkeit in % aus.

Bevor man die Werte dann auf die Ausgänge bzw. über SPI an die Treiber weitergbit, wandelt man die HSV Farbe in RGB um und gibt diese aus.

Hier mal ein Beispiel von einem kleinen Attiny13 Fader. Die HSV --> RGB Routine ist vom Forum mikrocontroller.net. Als Software-PWM Variante habe ich hier eine relativ einfache Form mit einem Timer gewählt.

edit Programmbeschreibung:
Das Programm geht den Hue Farbkreis durch.
Es kann die Geschwindigkeit verstellt werden.
Außerdem kann eine Pause durch Tastendruck hervorgerufen werden. Die Farbe bleibt dann bestehen.

PB3 = Geschwindigkeit
PB4 = Pause/Standfarbe

Code: Alles auswählen

/*
 * main.c
 *
 *  Created on: 20.10.2010
 *      Author: Florian Grotz (stromflo)
 *      Abwandlung der Easy_Strip_Software
*       Taster an : PB4,PB3
*       LED an: PB0,1,2
 */

#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>

//Attiny13

/*DEFINES*/

#define LED_DDR		DDRB
#define LED_PORT	PORTB


#define	LED_R	(1<<PB0)
#define LED_G	(1<<PB1)
#define LED_B	(1<<PB2)

//Variablen zählt auch für Interrupts
volatile uint8_t pwm_r,pwm_g,pwm_b;
volatile uint8_t pausenflag;


uint8_t i = 0;
uint8_t g = 0;
uint8_t speedvalue = 50;

//Funktionen
uint8_t tasteGedrueckt(volatile uint8_t *port,uint8_t pin);
void hsv_to_rgb (unsigned char h, unsigned char s, unsigned char v);
void speed(uint8_t wiederholen);

int main (void){
	    LED_DDR &= ~((1<<PB3)|(1<<PB4));
	    LED_PORT |= (1<<PB3)|(1<<PB4);
		TIMSK0 |= (1 << TOIE0);				// Timer0 Interrupt
		TCCR0B |= (1<<CS00);				// Prescale 1
		sei();

	while(1){

		 if (tasteGedrueckt (&PINB,PB4)) {
			          //toggelt das Pausenflag
				      pausenflag = ~pausenflag;
				     }

		 if (tasteGedrueckt (&PINB,PB3)) {
			   //Verringert die Geschwindigkeit
			   if (speedvalue < 250){speedvalue = speedvalue + 5;}else{speedvalue = 0;}
			}

		 //Wenn keine Pause Effekt weiter laufen lassen
		 if (pausenflag == 0){
			//Umrechnung HSV to RGB
			hsv_to_rgb (i, 255, g);
			if (g<32){g++;}else{g=0;};
			 if(i < 255){i++;}else{i=0;};
			 speed(speedvalue);
	}
	}
}


ISR (TIM0_OVF_vect)
{
	static uint8_t pwm_count;
	if (pwm_count < 255){pwm_count++;}else{pwm_count = 0;}
	if (pwm_count < pwm_r) {LED_PORT |= LED_R;}else{LED_PORT &= ~LED_R;}	// rot ein
	if (pwm_count < pwm_g) {LED_PORT |= LED_G;}else{LED_PORT &= ~LED_G;}
	if (pwm_count < pwm_b) {LED_PORT |= LED_B;}else{LED_PORT &= ~LED_B;}
}


//hsv_to_rgb Umrechnung aus mikrocontroller.net Forum
void hsv_to_rgb (unsigned char h, unsigned char s, unsigned char v)
{
	//Variablen Deklaration
	unsigned int p, q, t,i,f;
    //Wenn die Sättigung bei 0 ist
	if( s == 0 )
 	{	pwm_r= pwm_g = pwm_b =v;
 	}

	else
	{	i=h/43;
		f=h%43;
		p = (v * (255 - s))/256;
		q = (v * ((10710 - (s * f))/42))/256;
		t = (v * ((10710 - (s * (42 - f)))/42))/256;

		switch( i )
		{	case 0:
				pwm_r = v; pwm_g = t; pwm_b = p; break;
			case 1:
				pwm_r = q; pwm_g = v; pwm_b = p; break;
			case 2:
				pwm_r = p; pwm_g = v; pwm_b = t; break;
			case 3:
				pwm_r = p; pwm_g = q; pwm_b = v; break;
			case 4:
				pwm_r = t; pwm_g = p; pwm_b = v; break;
			case 5:
	 			pwm_r = v; pwm_g = p; pwm_b = q; break;
		}
	}
}

/* Entprellter Tastendruck
  */
uint8_t tasteGedrueckt(volatile uint8_t *port,uint8_t pin) {
      /* Wenn Pin B0 low ist, wurde der Taster gedrückt
        */
      if (! (*port & (1 << pin))) {
             /* warte um das Drücken zu entprellen
              */
             _delay_ms(50);
             /* warte bis losgelassen wurde
              */
             while (! (*port & (1 << pin))) {}
             /* warte um das Loslassen zu entprellen
              */
             _delay_ms(50);
             /* melde den Tastendruck
              */
             return 1;
      }
      /* wurde die Taste nicht gedrückt
        * melde negatives Ergebnis
        */
      return 0;
}

void speed(uint8_t wiederholen){
	uint8_t j;
	for (j = 0;j<wiederholen;j++){
		_delay_ms(10);
	}
}

Gruß Flo
Terminus
User
User
Beiträge: 19
Registriert: Di, 10.04.12, 11:19

Fr, 13.04.12, 17:22

Mit 6 PWM Kanälen kann ich aber trotzdem nur 2 Farben gleichzeitig erzeugen.

Kann ich im HSV-Raum denn alle Farben darstellen und auch dimmen?
stromflo
Mega-User
Mega-User
Beiträge: 304
Registriert: Mi, 31.12.08, 12:16

Fr, 13.04.12, 17:31

Was willst du denn eigentlich im Endeffekt realisieren?

Prinzipiell kannst du im HSV Farbraum auch die Farben die du mit RGB darstellen kannst, darstellen. Allerdings gehen unter Umständen bei Umrechnungen etc. auch ein paar verloren....

Außerdem, wenn man die Leds weit runterdimmt, dann vermischen sich meist die Farben nicht mehr so gut.....

Gruß Flo
Terminus
User
User
Beiträge: 19
Registriert: Di, 10.04.12, 11:19

Fr, 13.04.12, 17:41

Also ich will so eine Art Informationsanzeige realisieren. So als Überwachung von einigen Zuständen.
Je nach dem wie stark die Anlange von irgendeiner Lichtquelle beleuchtet wird muss ich ja die Helligkeit anpassen, um die Sache immer möglichst lesbar zu halten.

Wenn ich bei "normaler" Raumhelligkeit eine Farbhelligkeit von 120 einstelle, dann kann ich mich doch eigentlich recht gut im Farbraum bewegen.
Ich habe mir ein kleines Programm am PC geschrieben, mit dem ich mich mit Hilfe der Windowsfarbpalette durch den Farbraum klicken kann, daher auch meine Annahme von 120 als "normale" Helligkeit.
Farbpalette.png
Farbpalette.png (14.74 KiB) 12083 mal betrachtet
stromflo
Mega-User
Mega-User
Beiträge: 304
Registriert: Mi, 31.12.08, 12:16

Fr, 13.04.12, 17:46

Ja du kannst im HSV Kreis einen Farbton wählen und dann die Helligkeit anpassen. Dann könntest du einen anderen Farbton wählen und die Helligkeit von diesem wiederum anpassen etc. im Prinzip hast du 8-Bit also 255 Schritte zur Verfügung. Allerdings ist mir aufgefallen, dass bei kleinen Dimmstufen (also niedrige Helligkeit) die Farbmischung nicht mehr richtig schön rüberkommt. Das kann aber auch von Led zu Led abweichen--> Du siehst unter Umständen z.B. die einezlnen Ledchips der Led mit den Farben dann relativ deutlich.

Gruß Flo
Borax
Star-Admin
Star-Admin
Beiträge: 12243
Registriert: Mo, 10.09.07, 16:28

Sa, 14.04.12, 12:15

Sehe ich das richtig, Du willst eigentlich mehr oder minder nur 'Grundfarben', davon aber 6 verschiedenen die alle mehr oder minder gleichmäßig auf eine best. Helligkeitsstufe angepasst werden sollen (passend zur 'Umgebungshelligkeit)? In diesem Fall könnte man einfache Schieberegister nehmen und über den 'enable' PWM dimmen.
Ist hier beschrieben: http://www.rn-wissen.de/index.php/Portexpander_am_AVR
Terminus
User
User
Beiträge: 19
Registriert: Di, 10.04.12, 11:19

Sa, 14.04.12, 13:49

Borax hat geschrieben:Sehe ich das richtig, Du willst eigentlich mehr oder minder nur 'Grundfarben', davon aber 6 verschiedenen die alle mehr oder minder gleichmäßig auf eine best. Helligkeitsstufe angepasst werden sollen (passend zur 'Umgebungshelligkeit)?
Nicht ganz. Ich wollte schon eine Mischung der 3 Grundfarben haben. Daher denke ich auch, dass ich Lösung über die Schieberegister für mein Vorhaben eher ungeeignet ist. Aber eigentlich finde ich die Idee ganz gut. Schieberegister hätte ich noch genug hier und die sind preislich auch sehr günstig.
Terminus
User
User
Beiträge: 19
Registriert: Di, 10.04.12, 11:19

Sa, 14.04.12, 14:55

Ich habe gerade von dem MY9221 gelesen. Wie ist das IC denn so? Kann ich damit den gesamten Farbraum ausnutzen und gleichzeitig ohne Verlust der Farbe dimmen?

Allerdings habe ich auch gelesen, dass die Ansteuerung recht bescheiden sein soll.
Borax
Star-Admin
Star-Admin
Beiträge: 12243
Registriert: Mo, 10.09.07, 16:28

Sa, 14.04.12, 18:33

Das kannst Du mit den WS2801 genauso. Und die sind dagegen recht einfach ansteuerbar. Für 6 'unabhängige' frei definierbare Farben brauchst Du dann halt 6 Stück. Ich versteh irgendwie das Problem nicht...
stromflo
Mega-User
Mega-User
Beiträge: 304
Registriert: Mi, 31.12.08, 12:16

So, 15.04.12, 08:22

Guten Morgen Borax,

ich versteh auch so allmählich das Problem nicht mehr.....

Hier mal noch ein kleines Beispielprogramm zur Ansteuerung von den WS2801....

Code: Alles auswählen

/*by stromflo (c)*/
/*WS2801 Testprogramm*/


#include <avr/io.h>  
#include <util/delay.h>
#include <stdint.h>
#include <avr/pgmspace.h>

/*Definition */
#define DDR_SPI DDRB
#define DD_MOSI 3
#define DD_SCK 5
#define DD_SS 2

void spiinit(void);
void spisend(char r, char g, char b);

/* PWM Werte für RGB*/
const uint8_t r[32]  PROGMEM = {255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255};
const uint8_t g[32]  PROGMEM = {0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255};
const uint8_t b[32]  PROGMEM = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255};      
 
int main (void) { 

spiinit();             
  
/* Die Werte aus der RGB Tabelle werden übertragen*/
for (uint8_t i = 0; i < 32; ++i )
{
   spisend(pgm_read_byte(&r[i]),pgm_read_byte(&g[i]),pgm_read_byte(&b[i]));
   }
              
   /*Hauptschleife*/ 
   while(1) {                      
}         
   return 0;                 
}


/*Funktion zur Konfiguration von SPI*/
void spiinit(void)
{
/*Ausgänge definieren*/
DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);
/* SPI aktivieren,Mastermodus,clock/4*/
SPCR = (1<<SPE)|(1<<MSTR);
}

/*Funktion zum senden der RGB Werte an die WS2801*/
void spisend(char r, char g, char b)
{
/*Roten Wert übertragen*/
SPDR = r;
while(!(SPSR & (1<<SPIF)));
/*Grünen Wert übertragen*/
SPDR = g;
while(!(SPSR & (1<<SPIF)));
/*Blauer Wert übertragen*/
SPDR = b;
while(!(SPSR & (1<<SPIF)));
}

Gruß Flo
Zuletzt geändert von stromflo am So, 15.04.12, 16:11, insgesamt 1-mal geändert.
Terminus
User
User
Beiträge: 19
Registriert: Di, 10.04.12, 11:19

So, 15.04.12, 15:27

Meine ursprüngliche Idee bzw. Vorstellung war, dass ich mit dem WS2801 eine beliebige Farbe einstelle und anschließend je nach Helligkeit im Raum die Leds in ihrer Helligkeit veränderte, ohne, dass dabei der eigentlich gewünsche Farbton verloren geht.

Diese Idee ist leider so nicht umsetzbar, wie ihr mir erklärt habt.

Meine jetzige Vorstellung ist, dass ich mir aus dem HSV-Kegel bei mittlerer Helligkeit von 120 eine beliebige Farbe heraussuche. Je nach Helligkeit im Raum regele ich dann die Helligkeit der Leds hoch oder runter, sodass die Farbe entweder heller oder dunkler wird.


Ich glaube in deinem Quellcode ist noch ein kleiner Syntax-Fehler, Flo: Das Array für die Blauwerte ist am Ende nicht geschlossen. Das dürfte einen Compilerfehler geben.
Vielen Dank übrigens für den Code für das SPI. Ich habe das bisher immer per Software gemacht, was sich auf Dauer aber als nervig und zeitaufwändig erweist.
stromflo
Mega-User
Mega-User
Beiträge: 304
Registriert: Mi, 31.12.08, 12:16

So, 15.04.12, 16:18

Ich glaube in deinem Quellcode ist noch ein kleiner Syntax-Fehler, Flo: Das Array für die Blauwerte ist am Ende nicht geschlossen. Das dürfte einen Compilerfehler geben.
Ja, da hast du natürlich recht. Kommischerweise passt es in meinem Code auf dem Pc....
Naja habs oben mal korrigiert.

So wie du jetzt schreibst, sollte das ganze eigentlich machbar sein. Was du halt noch brauchst ist eine optische Möglichkeit um die Helligkeit im Zimmer zu erfassen. Da gibt es natürlich mehrere Wege wie z.B. ein TSL2561 oder Fotowiderstand.....

Einzig kann man evtl. halt nich in die dunkleren Stufen dimmen, hatte ich weiter oben schon angeführt...

Gruß Flo
Zuletzt geändert von stromflo am So, 15.04.12, 16:31, insgesamt 1-mal geändert.
Terminus
User
User
Beiträge: 19
Registriert: Di, 10.04.12, 11:19

So, 15.04.12, 16:20

Ja, solche Sachen bekomme ich hin.

Nur bei der Ansteuerung von RGB-Leds da brauchte ich eben Hilfe. Es kommt häufiger vor, dass meine Ziele ein wenig zu ambitioniert sind und ich sie dann mit meinen Möglichkeiten hinterher gar nicht umsetzen kann :-D
Daher frage ich vorher lieber nach, nicht, dass ich dann da später stehe und nichts funktioniert.

Vielen Dank für eure Hilfe, ihr habt mir sehr geholfen!
Antworten