RGB-LED an WS2801 dimmen
Moderator: T.Hoffmann
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?
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).
viewtopic.php?f=31&t=2950&hilit=atmega168
Allerdings in Basic (BASCOM AVR).
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
Gruß Flo
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);
}
}
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
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
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.
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.
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
Gruß Flo
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
Ist hier beschrieben: http://www.rn-wissen.de/index.php/Portexpander_am_AVR
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.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)?
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.
Allerdings habe ich auch gelesen, dass die Ansteuerung recht bescheiden sein soll.
Guten Morgen Borax,
ich versteh auch so allmählich das Problem nicht mehr.....
Hier mal noch ein kleines Beispielprogramm zur Ansteuerung von den WS2801....
Gruß Flo
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)));
}
Zuletzt geändert von stromflo am So, 15.04.12, 16:11, insgesamt 1-mal geändert.
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.
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.
Ja, da hast du natürlich recht. Kommischerweise passt es in meinem Code auf dem Pc....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.
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.
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
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!
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
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!



