Forum: Projekte & Code HSV RGB Led Dimmer, C Code & Video & Doku


von Fly (Gast)


Angehängte Dateien:

Lesenswert?

HSV RGB Led Dimmer;
Veröffentliche hier mal den aktuellen Stand.
C-Programm dimmt 10 RGB Farbtöne. (Vorführspielchen)
Näheres seht ihr im Video, C-Code oder in der Doku.

Kritik, Ideen und natürlich auch Lob sind gerne Willkommen.

Enjoy!

Fly.

von Dirk (Gast)


Lesenswert?

Hi,

vielen Dank für die Veröffentlichung.

Gruß,
Dirk

von Dario (Gast)


Lesenswert?

Hallo Fly,

Super Ding, das mit dem HSV-Farbraum.

Zur Kallibrierung mit den Widerständen habe ich noch eine Idee.
Du gehst ja momentan davon aus, dass die Einschaltzeit der LED 
proportional deren Helligkeit ist, dem ist aber nicht so, daher wäre 
eine Tabelle angebracht, aus der sich für jeden Helligkeitswert (R,G,B) 
der entsprechende PWM Wert ermittelt. Dann kann man die Vorwiderstände 
mit in die Tabelle integrieren, dann brauchst Du nicht einmal diese so 
aufwendig zu bestimmen.
Könnte dann mit einer einmaligen Einstellung erledigt werden, die man im 
EEPROM abspeicehrt.

Ansonsten aber super Arbeit,

Schöne Grüsse aus dem Ruhrgebiet,

Dario

von Fly (Gast)


Lesenswert?

Hallo Dario!

Deine Idee habe ich mir auch schon durch den Kopf gehen lassen. Nur wie 
bestimme ich die Helligkeitswerte? Mir ist schon klar dass die 
Helligkeit nicht linear mit der PWM steigt. Die Helligkeitswahrnehmung 
ist aber subjektiv... Man müsste sie messen können und die PWM 
entsprechend anpassen.
Oder reden wir aneinander vorbei?
Sorry, habe gerade nicht so viel Zeit (Studium)

Gruss, Fly.

von SeppK (Gast)


Lesenswert?

Habe eben ein Projekt am Laufen mit einer RGB-Led. NAch langem Suchen 
fand ich diese hier:

http://cgi.segor.de/user-cgi-bin/sidestep2.pl?foto=1&Q=para-led&M=1

Macht ca. 3,5 cd bei einem Öffnungswinkel von 100 Grad! Der Preis geht 
auch noch.

von Fly (Gast)


Lesenswert?

Naja, meine Led ist einiges heller, dafür habe ich nur einen 
Abstrahlwinkel von 60°

von SeppK (Gast)


Lesenswert?

Tja, viel Licht bei einem engen Abstrahlwinkel können alle. 3,5cd bei 
100 Grad (wie bekommt man denn hier das Gradzeichen hin?) ist schon 
recht gut.

von emil (Gast)


Lesenswert?

Habe den Code von Fly getestet, es funktioniert bei mir einwandfrei. Ich 
betreibe damit 10 RGB LEDs, will mir aber eine grössere RGB Matrix 
bauen.
Nicht ganz in Video-Auflösung (320x240 RGB LEDs hehehehe) sondern ehe 
was mit 4-5 Spalten a 16-20 RGB LEDs jede, ca. 1.5m hoch, sodass man 
doch interessante Farbmuster darstellen kann (vielleicht am PC 
generieren und dann per RS232 an die LEDs schicken).

von Fly (Gast)


Lesenswert?

@Emil
Freut mich das es klappt!
Ist die Doku / der Code einigermassen nachvollziehbar? War mein erstes 
richtiges C Projekt.

Betreibst du die 10 Leds parallel oder hat jede seine eigene HSV/RGB 
Werte?

von emil (Gast)


Lesenswert?

Hi,

ja, der Code ist ganz OK, gut gemacht! Besonders das Dimmen war für mich 
ganz wichtig!

Ich multiplexe die RGB LEDs, somit ist jede einzeln adressierbar. Leider 
machen sie zur Zeit nichts mehr, als per Zufallsgenerator die Farbe zu 
wechseln.

Wie gesagt, ich will eigentlich ca. 100 RGB LEDs einzeln ansprechen 
können, vielleicht jede 10-16 mit eigenem Controller, leider sind die 
RGBs verhältnismässig teuer; habe 50 Stk bei ebay gekauft (Hong Kong, 
was sonst), leider ist die Farbmischung sehr schlecht und noch dazu 
unterschielixh von LED zu LED :(.
Habe eine Anfrage bei Nichia getätigt, die wollen 1.90 Euro / LED 
netto...na ja, als Hobby Projekt ein wenig teuer, schade 
eigentlich...:((

von Fly (Gast)


Lesenswert?

Jo es gibt enorme Qualitätsunterschiede bei den Leds. Ich bin mit meinen 
zufreiden. Ich möchte einen 4x4x4 Led-Cube im Plexiglasgehäuse 
realiseren.

von emil (Gast)


Lesenswert?


von Benedikt K. (benedikt)


Angehängte Dateien:

Lesenswert?

Ich habe die Software mal float-frei gemacht: Die HSV und RGB Werte sind 
jetzt chars (was für eine LED ausreichen sollte).
Es gibt aufgrund der Tatsache, dass sich 256 nicht ohne Rest durch 6 
teilen lässt ein paar Rundungsfehler, aber wenn man die Codegröße und 
die Berechnungszeiten vorher und nachher vergleicht, dann kann man das 
in Kauf nehmen (außerdem sieht man den Unterschied sowiso nicht).

von Fly (Gast)


Lesenswert?

Danke Benedikt, du hast geschafft, woran ich gescheitert bin :)
(Siehe Doku)
Ich kann dein Code zur Zeit nicht testen. Frage:
Sind die Rundungsfehler beim Dimmen sichtbar?

von Benedikt K. (benedikt)


Lesenswert?

Beim dimmen sieht man nichts, nur beim Übergang der Farben (H) von 255 
auf 0 (von violett-rot auf rot) werden 2 Schritte auf einmal gemacht, 
denn eigentlich bräuchte man einen Wertebereich von 0-257, die Farben 
256 und 257 lassen sich daher nicht anzeigen. Aber das fällt 
normalerweise nicht auf.

von emil (Gast)


Lesenswert?

Ein grosser Lob auch an Benedikt!

Habe den "float-freien" Code von Benedikt auch getestet, ganz schön und 
knapp! Der Atmega48 langweilt sich geradezu damit, nur 20% belegter 
Speicher (12%davon von meinem Programm), die LEDs behalten die Farbe 
beim Dimmen perfekt! Und mit den fehlenden Farben 256 und 257 kann ich 
leben :))

Suche jetzt eifrig nach günstigen echten (!) RGB-LED Quellen.

von Fly (Gast)


Lesenswert?

@Benedikt:
Wie sieht es mit den Farbübergängen aus, wenn ich einen Farbwechsler 
möchte und H langsam durchlaufe, ist dann der Farb-Verlauf nicht etwas 
sprunghaft mit 8B Auflösung? Ist mir heute noch spontan in den Sinn 
gekommen :)

von emil (Gast)


Lesenswert?

hehe sorry, vielleicht bin ich hyperaktiv, ist aber doch gut gemeint; 
habe genau das implementiert (mit dem Code von Benedikt), langsamer 
Farbverlauf bei 20 Leds gleichzeitig, jede mit unterschiedlichem 
Grauwert V und die Farbe verläuft recht gleichmässig in die nächste.
Habe hier eine Lampe mit RGB Luxeon, die mit reinen RGB_Werten (wieder 
8B)angesteuert wird, und sie ist viel nervöser beim Farbübergang, als 
mit dem HSV.
Benedikt, jetzt bist Du am Ball :)))

von Benedikt K. (benedikt)


Lesenswert?

Du hast jetzt also die RGB Werte direkt verändert, ohne HSV und was 
heißt nervöser ? Springen die Farben ?

von emil (Gast)


Lesenswert?

ja, genau; bei meiner Lampe generiere ich je einen aktuellen R-, G-, und 
B-Wert per Zufallsgenerator (8-Bit); ich speichere die alten RGB Werte 
und erhöhe/decremenitiere um eins die neuen, bis sie den alten gleich 
sind. Dies sollte effektiv einen fliessenden Farbübergang gewährleisten.
Nun habe ich dasselbe mit deinem Code versucht, indem ich lediglich H 
zufällig wähle und um eins inc./dec. bis er dem alten H gleicht. 
Seltsamerweise ist der Farbübergang jetzt glatter geworden, im Vergleich 
zur alten RGB-Methode.

von Elektrikser (Gast)


Lesenswert?

Ich habe gerade wieder eine Idee, von der ich noch nicht weiß, ob es 
klappt. Mein Problem ist, dass ich eine größere RGB-LED habe, die einen 
Strom von 150mA pro Strang aushält. Wenn ich da normale Vorwiderstände 
nehme, muss ich auf 1W-Widerstände ausweichen. Jetzt meine Idee:
Kann man nicht für die Vorwiderstände LM317 in der Stromregelschaltung 
verwenden und den Widerstand, den man da braucht durch ein Poti 
ersetzen? Hätte den Vorteil, dass nichts warm wird und die Ströme sauber 
eingestellt werden können. Das einzige, was ich nicht weiß ist, wie der 
Regler die PWM verträgt und was er da macht...

Gruß Elektrikser

von Benedikt K. (benedikt)


Lesenswert?

Elektrikser wrote:
> Kann man nicht für die Vorwiderstände LM317 in der Stromregelschaltung
> verwenden und den Widerstand, den man da braucht durch ein Poti
> ersetzen? Hätte den Vorteil, dass nichts warm wird und die Ströme sauber
> eingestellt werden können.

Dann betreib die Schaltung mal mit >20V. Innerhalb kürzester Zeit wirst 
du dir den Finger am LM317 verbrennen.
Davon abgesehen ist der LM317 zu langsam für die Ansteuerung mit PWM.

Wiso brauchst du eigentlich 1W Widerstände ?
Wenn die Betriebsspannung niedrig genug ist (z.B. 5V), dann reichen 
problemlos 1/2W Widerstände.

von Elektrikser (Gast)


Lesenswert?

O.K. wenn ich die Led mit PWM betreibe, reichen die 0,5W-Widerstände. 
Bei Volllast wäre es knapp. Dass der LM317 zu langsam ist habe ich mir 
schon gedacht. War halt ein Schnellschuß...

von Edi _. (edi_2k)


Angehängte Dateien:

Lesenswert?

Hallo.

Klasse Projekt. Ebenso die Doku von Fly.

Ich habe es vorher mit einem RGB-Sweep versucht. Es hat auch 
funktionert, jedoch sind saubere Farbübergänge ziemlich schwierig 
hinzubekommen, da zum einen die LEDs unterschiedliche Sättigung haben, 
die Wahrnehmung des Auges mit einer Wurzelfunktion bestimmt ist, und man 
sich separat um die Helligkeit kümmern muss, damit ein konstantes 
Helligkeitsniveau herrscht.

Ich hätte nicht gedacht, dass die Umsetzung der Gleichungen, die man bei 
Wikipedia zum Thema HSV-Raum findet, so reibungslos funktioniert.
Ich habe das ganze mal auf einen PIC18F4550 (48MHz Intern) ausprobiert.
Ebenso einen kontinuierlichen Sweep über 360 Farben (H=H+1) bei gleicher
(V=0.5) Helligkeit.

Ich verwende 3 einzelne LEDs von OSRAM (wegen der größeren Helligkeit).

R: LS 5435
G: LV5411
B: LB 543C

Deshalb brauche ich auch einen Diffusor: Artikel-Nr.: 183562 - 62 bei 
Conrad.
Falls jemand weiß, wo es diese Diffusorfolien größer und billiger gibt, 
bitte Bescheid geben.

Die Vorwiderstände (siehe Schaltplan im Anhang) wurden mit der Anleitung 
von Fly bestimmt.

:)

von emil (Gast)


Lesenswert?

Hi Stefan,

das mit dem Diffusor finde ich sehr gelungen!

Soweit mir bekannt, verwenden fast alle Werbefirmen die
 3M™ Optical Lighting Film (OLF)-Folie für solche Zwecke,
habe leider noch keine Quelle für Kleinmengen ausfindig gemacht :(

Hast du die Diffusor-Scheiben beim Conrad bestellt oder liegen sie dort 
in der Filialle? Wo denn, bei den Leiterplatten?

Und wieviel ist der Abstand zwischen LEDs und Diffusor bei dir? Kann man 
die LEDs ganz am Diffusor pressen um das ganze flach zu bekommen oder 
ist ein Mindestabstand nötig?

von Edi _. (edi_2k)


Lesenswert?

Hallo emil.

ich erkundige mich vorher in der entsprechenden Filiale (bei mir ist das 
Wernberg), ob die Teile da sind. Das war in diesem Fall nicht so.
Sie wurden bestellt und nach 3 Tagen bekam ich ne sms, dass die 
diffusorscheiben da sind.

Bzgl. Direkt auf die LEDs würd ich sie nicht pressen, da man bei 3 
einzelnen 5mm LEDs diese noch ziemlich gut mit dem Auge auflösen kann.
Ab 30-40 mm kann man die einzelnen LEDs nicht mehr erkennen.

Leichter hat man das natürlich mit RGB-LEDs. Das hängt jedoch von deiner 
Anwendung ab, ob die geringere Helligkeit reicht.

gruß
stefan

von MaG2k (Gast)


Lesenswert?

Hallo Leute,

das sachaut ja alles schon recht schön aus...aber eines ist mir bisher 
aufgefallen. Dieser Algortihmus ermöglicht zwar einen schönen 
Color-Sweep doch es fehlen ein paar Farben...mir selbst fehlte bei den 
Videos zum Beispiel das Weiß.
Ich habe schon einige Codes hier versucht durchzuschauen und der letzte 
den ich hatte ermöglichte nur das Dimmen 7 verschiedener Farben. Da ist 
ein solcher Farbdurchlauf schon bei weitem schöner. Wär aber wirklich 
schön wenn neben dem H-Wert auch S und V entsprechend variiert werden 
würden um mehr Farbvielfalt zu bekommen.

Ich schau mir mal den Code an...denn ich möchte mit dem RGB-LED Projekt 
auch mal einen richtigen Einstieg in den AVR-Programmierung bekommen! 
:-)

LG
MaG2k

von Christian R. (Gast)


Lesenswert?

Hallo.

Seht ihr eine Möglichkeit, aus der einen RGB LED mal so 200 oder mehr zu 
machen? Ich möchte ein RGB-LED Panel (Licht-Therapie) für eine Infrarot 
Kabine bauen.
Ich hab allerdings Angst vorm Strom: 200 Led's mit ca. 18mA x 3 (RGB) 
ist etwas viel (10,8 A!)

Könnt ihr mir weiterhelfen?

von Fly (Gast)


Lesenswert?

Was bedeutet Lichtherapie, jede Led muss 20/Sekunde die Farbe wechseln? 
Bei deinen Angaben sag ich mal NJAEIN.

Strom sollte kein Problem sein, bei richtigem Aufbau... DC-DC oder AC-DC 
Wandler heisst das Zauberwort.

von Christian R. (mrrotzi)


Lesenswert?

Naja, es gibt da so Lichtherapie-Lampen mit Steuerung. Da kann man eine 
Farbe einstellen oder gaaaanz langsame Verläufe von einer Farbe zur 
nächsten machen (lassen). so, und das ganze Ding soll eben in eine 
Infrarot-Kabine eingebaut werden (nebst ein Autoradio mit mp3 Player). 
Das alles soll zur Entspannung dienen.

Nun hab ich mir vorgestellt, ich mach eine Schaltung wo ich mit 3 
Tastern Rot, Grün und Blau Werte mische. Also somit fast jede Farbe 
erziele.
Um aber den Raum (knappe 2 m2) schön auszuleuchten, müsste man schon 
etliche LEDs verbauen.
Jetzt ist eben die Frage, wie man das geschickt angeht.
Dann hab ich deinen Beitrag hier gefunden und mir gedacht, das wär mal 
die richtige Ausgangssituation. Nur müsste ich viele viele LEDs 
verbauen.

Frage: Wieviel LEDs müsste man einbauen? Gute Frage, ich weiß. Besser 
wäre es wahrscheinlich, wenn man das teilt in so 10x10 LEDs Blöcke und 
wenn man das Ding dann in der Kabine anwirft und merkt, es ist noch 
nicht genug, dass man dann die Möglichkeit hat, noch so Blöcke dazu zu 
bauen!

Was kostet eigentlich so eine LED?

von Fly (Gast)


Lesenswert?

"Nun hab ich mir vorgestellt, ich mach eine Schaltung wo ich mit 3
Tastern Rot, Grün und Blau Werte mische. Also somit fast jede Farbe
erziele."

Ist nicht der Sinn des HSV-Farbraums. Du wählst den Farbton und die 
Helligkeit. Mit reiner RGB fumelei bringst du vielleicht den Farbton 
hin, aber nicht die Helligkeit! Dimmen ist wichtig!

"Frage: Wieviel LEDs müsste man einbauen? Gute Frage, ich weiß. Besser
wäre es wahrscheinlich, wenn man das teilt in so 10x10 LEDs Blöcke "

Vorher meintest du was von ca 200 Leds... du kannst dir den Ledabstand 
selbst ausrechnen mit vorgegebener Fläche. Ich fürchte aber mit 200 
kommst du nicht sehr weit! Mit 10x10 = 100 Leds! erweitern finde ich 
auch nicht gut. Überlege dir erst einmal welchen Led Abstand du willst. 
Dann kannst du rechnen.
Ich weiss ja schliesslich nicht wie du dir das genau vorstellst.

"Was kostet eigentlich so eine LED?"
Ich würde dir zu kleinen Leds, max 3mm Durchmesser, mit möglichst 
grossem Abstrahlwinkel raten! Ausserdem muss sie für das gesamte 
Farbspekrum geeignet und difus sein. Preis je nach Stückzahl, ich denke 
ca 50 cent / Led minimum.
Bei rgb Leds ist geiz nicht geil.

Falls nicht alle Leds gleichzeitig den selben farbton / helligkeit haben 
sollen, überlege dir wieviele Kanäle du haben villst und wie du das 
physisch aufteilst.
Hast du einigermassen eletronki und C-Programmierung Kenntnisse? Wenn 
nicht, wird das kein Wochenende Projekt.

von Christian R. (mrrotzi)


Lesenswert?

Du hast recht, dimmen ist wichtig - deswegen HSV. Du weißt aber, worauf 
ich hinaus wollte mit RGB ;o) (hab mich schlecht ausgedrückt)

Den Abstand der LEDs hätte ich mal mit 5mm angenommen. Aber bei 5mm 
LEDs.

Ich bin aber schon am Grübeln, ob die ganze Sache nicht einfacher wird, 
wenn ich "normale" 12V Halogen Lampen nehme, von jeder Farbe eine, und 
die dann vermische durch dimmen!

Aber: so ein LED Panel würde schon extrem cool aussehen, ausserdem wäre 
da eine quasi größere Fläche, wo das Licht abstrahlt. Bei einzelnen 
Spots müsste man irgendeine diffuse Glasplatte davor tun, damit das 
wirkt, glaube ich.

Bezüglich Elektronik und Programmierung sehe ich meine Schwäche im 
Moment in der Ansteuerung der vielen Leds! Das ist es, wo ich mich nicht 
auskenne!

Nur mal angenommen, man würde das hinnehmen, dass eben nicht alles LEDs 
gleich leuchten (ergibt vielleicht sogar ein ganz angenehmes Licht?!) 
Wie könnte man so eine Kaskadierung realisieren? Könntest du mir ein 
paar Tipps für die Schaltung geben?







von Fly (Gast)


Lesenswert?

"Den Abstand der LEDs hätte ich mal mit 5mm angenommen. Aber bei 5mm
LEDs."

Rechnen ist wohl nicht deine Stärke... Schon mal ausgerechnet wieviele 
tausend Leds du dann brauchst?

von Christian R. (mrrotzi)


Lesenswert?

Sehr nett von dir! 10x10 (cm) sind 100 LEDs also 1 LED / cm2
Ich hab auch immer davon gesprochen: viele LEDs anzusteuern.
2 oder 3 hundert in dem Fall. Deswegen die Aufteilung in so eine Art 
Blöcke, damit man's erweitern kann, falls es zuwenig Licht gibt.

von Fly (Gast)


Lesenswert?

Aber definitiv nicht bei 5mm Led Abstand, so wie du geschrieben hast.
Ausserdem bei 1 m^2 Fläche gibt es immer noch 100 x 100 Leds!

von Fly (Gast)


Lesenswert?

Oder möchtes du in deiner Kabine einfach nur eine, zwei, drei 10x10cm 
Matrix an einer Wand? Das würde meiner Meinung nach komisch aussehen. 
Ich würde von allen Seiten oder mindestens von der Front Seite aus 
beleuchten und die Leds regelmässig über die Gesamtfläche verteilen. 
Ledabstand ca 5-15 cm...

von Christian R. (mrrotzi)


Lesenswert?

also der Abstand war nur mal so eine Annahme weil ich gerade ein 20cm 
Lineal vor mir liegen hatte und ich mit dem Bleistift auf einem 
karierten Papier herumgekritzelt habe.

Mal angenommen, man kommt mit 200 oder 300 LEDs aus - wie würde die 
Schaltung dazu aussehen.

Bin auch nicht böse, wenn wir hier in diesem Thread nicht auf einen 
gemeinsamen Nenner kommen, was den Abstand der Leuchtdioden betrifft 
;o))

von Fly (Gast)


Lesenswert?

Okay :)
Dan musst du dir die Frage stellen nach der Anzahl von Kanälen die du 
willst.
Bei nur einem Kanal sehe ich kein Problem, wieviele möglich sind weiss 
ich nicht genau.
Ich geh mal von einem Kanal aus: Einfach, du kannst alle r, alle g und 
alle b Leitungen zusammenfassen und musst nur diese 3 Leitungen steuern. 
Ich würde dir allerdings empfehlen je nach Höhe deiner Betriebsspannung 
so viele Leds wie möglich in Reihe zu schalten (Verlustleistung und 
Anzahl der Vorwiderstände wird kleiner).

Wenn du mehrere Kanäle willst, wird es schwieriger, je nachdem was du 
dir wieder vorstellst. Am besten du suchst mal im uC + elektronik Forum 
nach Begriffen wie LED PWM MATRIX. Es hat viele Threats dazu.

von Fly (Gast)


Lesenswert?

Nachtrag: Such mal bei Google nach Led Cube. Da kannst du dir einiges 
abschauen. Übrigens wenn du eine gute Quelle für günstige und brauchbare 
leds gefunden hast --> Bitte mitteilen :)

von Christian R. (mrrotzi)


Lesenswert?

Danke!
Ich geh mal auf die Suche!

btw: ich würde sowieso nur einen Kanal machen. Denke, das muss reichen. 
Ausserdem, wenn wirklich manche LEDs aus der Reihe fallen (bezüglich 
unterschiedlicher Leuchtstärke oder so) dann schaut das vielleicht 
garnicht so schlecht aus?!

Mal sehen!

von Dirk (Gast)


Lesenswert?

>Übrigens wenn du eine gute Quelle für günstige und brauchbare leds
>gefunden hast

Die beiden Sachen passen so gut zusammen wie Katze und Hund.

von Fly (Gast)


Lesenswert?

Ich träume von einer Kabine mit folgenden Eigenschaften.

- Grösse 3 x 2 x 2 m
- Schalldicht
- Auf allen Seiten rgb Leds
- Sofa oder Sessel drin
- Soundsystem mit Ipod
- Wasserpfeife
- Abzug für den Rauch und Sauerstoff rein
- Fernbedienung um den rgb Controller zu bedienen
  - Farbton und Helligkeit wählbar
  - Verschiedene Auto rgb Programme wählbar (sanfter Farbwechsel)

Da würde ich mich eine Weile nach einem schlechten Tag verziehen...

von Christian R. (mrrotzi)


Lesenswert?

ganz recht!

Schalldicht ist wichtig um einen eventuellen Schreikrampf für mich zu 
behalten!

von Fly (Gast)


Lesenswert?

Hehe jooa, doch Schreikrämpfe hab ich nicht. Ich möchte eher Ruhe von 
meiner Umwelt :)

von Fabian B. (fabianbonner)


Lesenswert?

@edi_2k
@emil

...matt, transluzente Selbstklebefolien mit diffusiver Eigenschaft von 
Oracal und 3m können (ab 0,5m²) bei mir bezogen werden.

Ebenfalls kann ich euch Acrylglas ab 2mm Stärke anbieten, aus welchem 
beliebige Formen herausgeschnitten werden können. Auch Gravur ist 
möglich.

Einfach mal anfragen: fabianbonner@kommit.biz

Bitte auch mein derzeit aktuelles Anliegen (Auftragsarbeit) beachten:
Beitrag "Auftragsarbeit - RGB-LED-Lauflicht"

von Paul (Gast)


Lesenswert?

Hallo Forum.

Ich habe den Code von Benedikt K. versucht nach Codevision AVR zu 
portieren, leider ohne Erfolg. Mit dem Code von Fly hat es gefunzt. Aber 
jetzt leuchten die LED's eher statisch abwechselnd in den drei 
Grundfarben. Wo liegt mein Fehler? Den umgeschriebenen Code für 
CodeVision habe ich mit angehängt.

von Paul (Gast)


Lesenswert?

Ja ich weiß "Längeren Sourcecode nicht im Text einfügen, sondern als 
Dateianhang" aber irgendwie bekomme ich den hier auch nicht rein. :-(

#include <tiny45.h>
#include <io.h>
#include <stdlib.h>

#define     Ledport             PORTB    // RGB Led Port
#define     DDR_Ledport         DDRB

#define     R_PIN               2      // R Ausgang
#define     G_PIN               1      // G
#define     B_PIN               0      // B

#define      INVERT        1      // Ausgang Low aktiv ?
#define     Time                1

unsigned char Red, Green, Blue;             // PWM Register
unsigned char Flags;

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void) {
    static unsigned char PWM_cnt;

if (INVERT==1) {
  if (PWM_cnt <Red)
    Ledport &=~(1 << R_PIN);
  else
    Ledport |= (1 << R_PIN);

  if (PWM_cnt <Green)
    Ledport &=~(1 << G_PIN);
  else
    Ledport |= (1 << G_PIN);

  if (PWM_cnt <Blue)
    Ledport &=~(1 << B_PIN);
  else
    Ledport |= (1 << B_PIN);
} else {
  if (PWM_cnt <Red)
    Ledport |= (1 << R_PIN);
  else
    Ledport &=~(1 << R_PIN);

  if (PWM_cnt <Green)
    Ledport |= (1 << G_PIN);
  else
    Ledport &=~(1 << G_PIN);

  if (PWM_cnt <Blue)
    Ledport |= (1 << B_PIN);
  else
    Ledport &=~(1 << B_PIN);
}
  PWM_cnt++;
  if (PWM_cnt==0)
    Flags|=Time;
}

//HSV Function
hsv_to_rgb (unsigned char h, unsigned char s, unsigned char v) {
unsigned char r, g, b, i, f;
unsigned int p, q, t;

  if( s == 0 ) {
      r = g = 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:
        r = v; g = t; b = p; break;
      case 1:
        r = q; g = v; b = p; break;
      case 2:
        r = p; g = v; b = t; break;
      case 3:
        r = p; g = q; b = v; break;
      case 4:
        r = t; g = p; b = v; break;
      case 5:
         r = v; g = p; b = q; break;
    }
  }
  #asm("cli");                        // Kein Interrupt beim übernehmen 
der neuen Werte!
  Red=r; Green=g; Blue=b;
  #asm("sei");
}

void main(void) {
    unsigned char H,S,V;

    DDRB=0x07;

    H = 0;
    S = 255;
    V = 255;
    hsv_to_rgb(H,S,V);                  // HSV Startwerte: rot, volle 
Helligkeit

    TCCR0B=0x01;
    TIMSK = 0x02;                       // T0 Starten, Overflow 
Interrupt f/256
    #asm("sei");

while (1) {
    if (Flags&Time) {
        Flags&=~Time;
        H++;
        hsv_to_rgb(H,S,V);
    }
};
}

von Dirk (Gast)


Lesenswert?

"Ja ich weiß "Längeren Sourcecode nicht im Text einfügen, sondern als
Dateianhang" aber irgendwie bekomme ich den hier auch nicht rein. :-("


Wenn Du zu doof bist, dann lass den Scheiß.

von Paul (Gast)


Lesenswert?

Hallo und danke für deine Antwort. Das hilft mir weiter.

grüße

von Fly (Gast)


Lesenswert?

Ich habe mir den Code mal angeschaut. Auf den ersten blick erkenne ich 
keine Fehler.
Du hast INVERT als 1 definiert. Somit sind die Ausgangszustände 
invertiert. Diese Möglichkeit ist ein Feature von Benedikt. Wie sind 
deine Leds angeschlossen?
Bei meniner Hardware und dem Code sind sie highaktiv. Ich müsste das 
INVERT also als 0 definieren damit es funktioniert.

von Paul (Gast)


Lesenswert?

Hallo

Ja das ist richtig. Das ist bei meiner Hardware natürlich genau so. 
Leider bringt die Änderung keinen Erfolg. Es gibt auch keine einzelnen 
RGB-Farben. Es werden bei H=0,12,240 immer Mischfarben angezeigt.

von Fly (Gast)


Lesenswert?

Wie ist jetzt genau deine Hardware, so wie in meiner Doku beschrieben 
oder so wie Benedikts, also invertiert?
Was meinst du mit H=0,12,240 ?

von Paul (Gast)


Lesenswert?

Meine Hardware sieht wie folgt aus.
Die Ausgänge des Controllers werden über npn transistoren geschaltet. 
Demnach sollte also auch eine 0 bei invert stehen.

Mit H=0,120,240 Grad meine ich die einzelnen Grundfarben Rot, Grün und 
Blau.

Übrigens Funktioniert die selbe Hardware mit deinem Code Fly, wunderbar.

von Fabian B. (fabs)


Lesenswert?

@Fly
in deiner Anleitung zum Abgleichen der Vorwiderstände steht, dass am 
Ende bei H=0 S=1 V=1 (oder nach Benedikts Int-Umsetzung H=0 S=255 V=255 
ein möglichst gutes Weiss kommen soll... das ist doch wohl so nicht 
korrekt oder?
H=0 ist doch zwangsläufig reines rot....

Gruß
Fabian

von Fly (Gast)


Lesenswert?

Ja, natürlich mit H=0 S=1 V=1 ergibt sich rot, sry ein Fehler in der 
Doku!
Dann nimmst halt meinen Code :)
http://www.csgnetwork.com/csgcolorsel4.html
hier kannst du probieren. Weiss ergibt natürlich H=0 S=0 V=100.

von Carsten H. (carsten29)


Lesenswert?

Gibt es auch Irgendwo den Schaltplan zu dem Code ?

von Ralf (Gast)


Lesenswert?

Da hier ein paar Mal gefragt worden ist nach RGB-LED-Lieferanten, ich 
hab mal gesucht und das hier gefunden:

http://www.leds.de/index.php?language=de&cat=c26_LEDs-rainbow---RGB.html

Die unteren LEDs sind echte RGBs, die oberen wechseln die Farbe 
selbstständig.

Ich weiss nicht, ob die Teile was taugen, noch habe ich da bis jetzt 
welche gekauft. Der Preis sieht aus meiner Sicht gut aus. Dachte nur, 
dass das vielleicht für jemanden interessant sein könnte...

Ralf

von fabs (Gast)


Lesenswert?

Die Teile sind "okay". die Farbmischung ist aber nicht sooo berauschend. 
Die "Leuchtflecken" divergieren recht stark. Ich hatte mir mal LEDs aus 
Hongkong vom Hersteller besorgt (über ebay) und die waren deutlich 
besser (und deutlich günstiger).

Gruß
Fabian

von Max (Gast)


Lesenswert?

Hallo! :)

Ich hab mir jetzt mal eine Schaltung gebaut und es ausprobiert. Aber 
leider kam ich nicht auf das Ergebnis, was du hast. Wenn ich die LED's 
anmachen sieht man jede Farbe einzeln. Liegt das daran, dass es eine RGB 
LED Klar ist??

So dann habe ich glaube ich noch ein Problem mit der Frequenz. Wenn ich 
den Code auf meinem STK500 teste sieht man die onboard LED blinken. Soll 
aber nicht so sein oder!?

LG Max

von Fly (Gast)


Lesenswert?

Gut möglich, meine Leds sind diffus.
Dass die Boardleds leuchten, liegt wohl daran, dass diese noch parallel 
angehängt sind an den IO's des uC. Du kannst das Portkabel der Leds 
abziehen und sie sind aus :)

von Max (Gast)


Lesenswert?

@ Fly

ne jetzt hast du mich glaube ich falsch verstanden. Die sollen ja 
Leuchten. ;-) Aber sie blinken, und das sollen sie ja nicht oder?! Bzw. 
das Blinken soll man nicht sehen. Sonder es soll so eine Art Dimmen 
zusehen sein, nicht?

von Fabian B. (fabs)


Lesenswert?

Dann ist deine PWM Frequenz zu langsam.
bei den 256 Stufen und 8MHz internem Takt musste den Timer ohne 
Prescaler laufen lassen...

hatte ich auch...

@Fly: wo haste die diffusen RBG-Leds her?

Gruß
Fabian

von Max (Gast)


Lesenswert?

Ich hab den TCCR0=1, sprich das Ding läuft bei einer Frequenz von 8Mhz. 
Und bei 256 dann die entsprechende. Komisch... Irgendwas läuft da ganz 
krum. Aber es sollte doch kein unterschied sein, ob jetzt mega8 (ich) 
oder dem mega16?!

LG Max

von Fabian B. (fabs)


Lesenswert?

nein. bei mir läuft es auf nem tiny13 mit den internen 9,6MHz 
einwandfrei.

Poste doch mal deinen Schaltplan/Code

Gruß
Fabian

von Fly (Gast)


Lesenswert?

Die Leds habe ich einmal bei ricardo.ch bestellt

von Max (Gast)


Angehängte Dateien:

Lesenswert?

So ich hab anbei mal ein Video wie es auf meinem STK500 aussieht. So 
sollte es doch sicherlich nicht sein oder?

Ich hab einfach den Code wie er ist genommen und draufgespielt...

LG Max

von kolbaca (Gast)


Lesenswert?

Wo mit sehe ich mir das denn an ?

Kolbaca der bebutterte

von Max (Gast)


Lesenswert?

quicktime! :)

Also auf dem Video sieht man das blinken nicht sooo stark. Ist in 
wirklichkeit noch was stärker...

von Fabian B. (fabs)


Lesenswert?

Die drei Leds stellen deine Farben dar, richtig?

Wie ich oben schon schrieb:
>Dann ist deine PWM Frequenz zu langsam.
>bei den 256 Stufen und 8MHz internem Takt musste den Timer ohne
>Prescaler laufen lassen...

/Edit: Poste doch mal deinen Code bevor wir hier rumraten ;-)

Gruß
Fabian

von Max (Gast)


Lesenswert?

Ich hab einfach den Code vom Benedikt K. genommen.

http://www.mikrocontroller.net/attachment/highlight/18560

von Fabian B. (fabs)


Lesenswert?

Kann es sein, dass du die CLKOPT/CLKDIV Fuse gesetzt hast und das Teil 
in Wirklichkeit nur mit CLK/8 Läuft? Ich kenn den Mega8 jetzt nicht 
auswendig...hat der die auch? Oder probiers mal mit nem ext 16MHz Quarz. 
Wenn sich dann nichts ändert (nach FUSE umstellung) ist es nicht der 
Takt.

ansonsten mach mal Screenshots von deinen Fuse settings.

Gruß
Fabian

von Marius S. (lupin) Benutzerseite


Lesenswert?

Ich find den code mit floats irgendwie einfacher zu verwenden. Benedikts 
code funktioniert zwar auch, aber da habe ich das Problem, dass alles 8 
bit ist (man sieht deutlich die Abstufungen). Den float code kann man 
schneller auf mehr als 8 bittige PWMs anpassen und die HSV werte 
leichter extrem langsam laufen lassen.

Wäre cool wenn jemand die Funktion auf 8.8 fixed point HSV (IN) und 16 
bit RGB (OUT) abändern könnte. Die 16 bit RGB kann man sich dann ja 
immernoch nach rechts shiften falls nötig.

Ich benutze den Code mit einer "richtigen" LED (Prolight 3Watt). Ein 
Problem das ich noch habe ist, dass sobald nur R,G oder B leuchtet die 
LED viel heller erscheint - kann aber auch an meiner logarithmus-tabelle 
liegen...

von Fabs (Gast)


Lesenswert?

Solange man den Controller nur das rechnen lässt kann man natürlich auch 
mti der Float-Version machen. Aber versuch die mal in nen 1k-uC 
reinzuquetschen (z.b. Tiny13).

Stimmt schon, bei der Int Version kann man den Rundweg um den HSV-Kreis 
nicht unbegrenzt langsam machen, da man sonst die Abstufungen sieht, 
aber es geht noch gut in einer Geschwindigkeit, dass es nicht nervt.

Wegen der Helligkeit: Du kannst die Log Tabelle auch weglassen, wenn du 
die Leds über Stromquellen betreibst und die Ströme auf einander 
abstimmst: H auf 0, S auf 0, V auf 255 wars glaub ich und dann auf 
möglichst Weiss einstellen.
Klappt ganz gut.

Gruß
Fabian

von Max (Gast)


Lesenswert?

@Fabian B.

Also ich hab das jetzt mal auch mit einem mega16 ausprobiert und da ist 
das selbe Problem.

CLKOPT/CLKDIV Fuse sagt mir jetzt nichts. Ich bin ja noch am Anfang. ;-) 
Stellt man diese Sachen im makefile ein. Denn am C Code an sich habe ich 
nicht verändert.

von Max (Gast)


Lesenswert?

Jetzt geht es!

Ich verstehe aber nicht warum!? Folgendes hab ich gemacht. Ich hab im 
AVR Studio mal nach Fuses gesucht. Da war der interne auf 2 Mhz. Jetzt 
habe ich das mal auf 8 Mhz hochgestellt, war aber zu erst der falsche 
Code. Dann habe ich mit Programmers Notepad den richtigen Code 
hochgespielt und dann ging es auf einmal. Hätte ich es mit dem AVR 
hochgespielt hätte ich es vielleicht noch verstanden, aber so nicht. 
Bitte erklärt mir das mal. :-) Und wie sollte man beim aufspielen 
generell vorgehen?!

von Marius S. (lupin) Benutzerseite


Angehängte Dateien:

Lesenswert?

So, ich hab mich mal dran versucht. Im Anhang mein Code. Das ganze ist 
für nen Atmega8 weil der gerade zur Hand war.

Die h Variable ist nun ein 16 bit Integer. Statt zu teilen kann man 
super einfach mit dem Kehrwert mal nehmen. Also anstatt i = h / (256/6); 
einfach i = (h * 6) / 256;

Die s Variable ist ein 16 bit integer, aber eigentlich reichen auch 8 
bit. Da habe ich mir eine höhere Auflösung gespart damit ich keine 32 
bit Multiplikationen machen muss.

Das ganze hab ich dann halt für 16 bit gemacht und es funktioniert ganz 
gut.

Als Ergebnis kommen 16 bit Farbwerte raus, die man sich dann halt hin 
shiften kann (bei 20 MHz gehen mit Timer0 maximal 10 bit - es flackert 
dann bei 76 Hz). Vlt kann man einen Timer mit compare match einheit 
verwenden um noch höher zu gehen in der Frequenz (?).

Hab noch eine Log-Tabelle eingefügt (ist nur zu 25% nen Log...). Die ist 
aber nicht wirklich notwendig, für mich hat es keinen Unterschied 
gemacht. Mit einer Log Tabelle wie ich sie woanders gefunden hatte sah 
es aber mies aus.

An ADC0 und ADC1 werden zwei potis angeschlossen um Geschwindigkeit und 
Sättigung ein zu stellen.

Hier nochmal ein Bild von meiner Lampe ;)
http://lupin.shizzle.it/images/moodlamp.jpg

von Fabian B. (fabs)


Lesenswert?

@Max: wie man generell vorgeht ist Geschmacksache. Ich entwickle 
eigentlich immer in AVR-Studio, da ich meine Progs eh mit dem ICE2 
debuggen will.
Direkt im AVR-Studio sind, finde ich, auch die FUSES am 
übersichtlichsten.
Zum Thema CLKDIV/CLKOPT schau mal ins Datenblatt deines Controllers. 
Viele Controller laufen ja werkseitig mit dem 8MHz internen 
RC-Oszillator, der dann aber mittels CLKDIV Fuse auf 1MHz runtergeteilt 
wird. Damit läuft das Prog hier absolut nicht. Siehe auch Posting von 
Lupin: bei 20MHz sind max 10Bit Auflösung möglich und der normale 
Integer-Code hier ist für 8Bit.

@Lupin: mit nem CTC könnte man die Frequenz evtl noch erhöhen, wenn man 
nicht irgendwann in die Probleme läuft, dass der Controller seine 
Aufgaben zwischen den Interrupts nicht mehr schafft.
Ich hab schonmal so "aus der Ferne" darüber nachgedacht, ob einem da die 
PLL-Clocks z.b. vom Tiny45 helfen könnten...muss ich mal genauer drüber 
grübeln...

Gruß
Fabian

von Fox (Gast)


Lesenswert?

Hallo Zusammen

Habe die Schaltung von Marius Schmidt nachgebaut. Funktioniert soweit 
gut. Kann aber mit dem Analog ADC0 und ADC1 kein Effekt erzielen. Habe 
ein Potentiometer an GND und 5V gehängt und danach mit dem variablen Pin 
auf ADC0 und ADC1.

Ist das korrekt oder was habe ich falsch gemacht?

Gruss Fox

von Marius S. (lupin) Benutzerseite


Lesenswert?

Eine Schaltung hatte ich ja nicht wirklich dabei. Schön das es soweit 
funktioniert bei dir.

Hast du den AVCC Pin deines AVRs auch an 5 Volt? Benutzt wird die 
betriebsspannung als referenz (also Aref unbeschaltet lassen).

von Fox (Gast)


Lesenswert?

Danke für die schnelle Antwort.

AVCC habe ich nicht beschalten. und mit AREF habe ich auch nichts 
gemacht. Einfacht nur Poti 10kOhm an VCC und GND und danach den 
variablen Pin auf ADC0 und ADC1.

Habe noch den AVCC an 5V angeschlossen klappt auch noch nicht.

Gruss Fox

von Marius S. (lupin) Benutzerseite


Lesenswert?

Keine Ahnung warum das so ist... :/

Was für einen AVR benutzt du denn?

von Fox (Gast)


Lesenswert?

ATMega8

von Andre K. (andre2208)


Lesenswert?

Hallo!
Ich habe mal zum Spaß den Code von „Fly“ ausprobiert es funktioniert 
soweit gut , aber wie kriege ich hin das ich mehr als 10 Farbentöne hin 
bekomme ? Eigentlich müsste das funktionieren in dem ich statt (H+36), 
H+1 schreibe oder ?

(Controller ist der ATMega8)

Ich bedanke mich schon mal für die Hilfe!

von Fly (Gast)


Lesenswert?

Ja, das sollte problemlos gehen :)

von Andre K. (andre2208)


Lesenswert?

Hallo!
Danke schön für die schnelle Antwort funktioniert Super , bin jetzt aber 
noch am überlegen wie ich da die weiße Farbe hinbekomme?
H --  müsste undefiniert sein
S--  0 %
 V--  100%
Das müsste eigentlich so funktionieren

von Fly (Gast)


Lesenswert?

Nicht ganz, weiss:

H= 0
S= 0
V= 1

http://www.csgnetwork.com/csgcolorsel4.html

wenn ich mich recht errinnere :)

von Andre K. (andre2208)


Lesenswert?

Hallo!
Das habe ich auch schon geändert, aber dann Leuchtet die Power - LED gar 
nicht.

Jetzt versuche ich mal rauszufinden warum das so ist, er rechnet dann 
mit einer „0“

von Jens H. (Firma: FH-Köln) (holzi)


Lesenswert?

wie kann ich hier jetzt zb 3 RGBs schalten? Wie muss der Code aussehen?
1
#define     LedportB             PORTB    // RGB Led Port
2
#define     LedportC           PORTC
3
//#define     Inputport           PINC    // Noch nicht verwirklicht
4
#define     DDR_LedportB         DDRB
5
#define     DDR_LedportC         DDRC
6
//#define     DDR_Inputport       DDRC
7
#define     R1                   0      // R Ausgang PORTB
8
#define     G1                   1      // G
9
#define     B1                   2      // B
10
#define     R2                   3      // R Ausgang PORTB
11
#define     G2                   4      // G
12
#define     B2                   5      // B
13
#define     R3                   0      // R Ausgang PORTC
14
#define     G3                   1      // G
15
#define     B3                   2      // B


und der Interrupt
1
SIGNAL (SIG_OVERFLOW0)
2
{
3
    if ((PWM_cnt <=Red) && (Red!=0))
4
            { LedportB |= (1 << R1);}                             // Rot aktiv
5
            else {LedportB &= ~(1 << R1);}                        // Rot inaktiv
6
7
        if ((PWM_cnt <=Green) && (Green!=0))
8
            { LedportB |= (1 << G1);}                       
9
            else {LedportB &= ~(1 << G1);}     
10
        
11
        if ((PWM_cnt <=Blue) && (Blue!=0))
12
            { LedportB |= (1 << B1);}                        
13
            else {LedportB &= ~(1 << B1);}
14
      
15
                        
16
    if ((PWM_cnt <=Red) && (Red!=0))
17
            { LedportB |= (1 << R2);}                             // Rot aktiv
18
            else {LedportB &= ~(1 << R2);}                        // Rot inaktiv
19
20
        if ((PWM_cnt <=Green) && (Green!=0))
21
            { LedportB |= (1 << G2);}                       
22
            else {LedportB &= ~(1 << G2);}     
23
        
24
        if ((PWM_cnt <=Blue) && (Blue!=0))
25
            { LedportB |= (1 << B2);}                        
26
            else {LedportB &= ~(1 << B2);}    
27
28
29
    if ((PWM_cnt <=Red) && (Red!=0))
30
            { LedportC |= (1 << R3);}                             // Rot aktiv
31
            else {LedportC &= ~(1 << R3);}                        // Rot inaktiv
32
33
        if ((PWM_cnt <=Green) && (Green!=0))
34
            { LedportC |= (1 << G3);}                       
35
            else {LedportC &= ~(1 << G3);}     
36
        
37
        if ((PWM_cnt <=Blue) && (Blue!=0))
38
            { LedportC |= (1 << B3);}                        
39
            else {LedportC &= ~(1 << B3);}    
40
41
    /*    if (PWM_cnt==255)                    // Wenn PWM Periode vorbei 
42
            {
43
              PWM_cnt=0; timebase++;              // Neustart
44
              if (timebase == 2)                                // Geschwindigkeit des Ablaufs
45
                  {
46
           timebase=0; 
47
           V=(V-0.005);            // Helligkeit dimmen, Geschwindigkeit abhängig von timebase, Auflösung beliebig (float)
48
                   if (V<=0)                   // Wenn Helligkeit = 0
49
               {
50
             V=1;
51
             H=(H+36);              // Volle Helligkeit, Neuer Farbton, 10 Farbtöne, Auflösund beliebig veränderbar (float)
52
             if (H>=360) {H=0;}
53
             }                
54
                   Statusreg = Get_New_RGB_Value;        // Neue HSV Werte Stausbit aktiv
55
                  }                                           
56
            }
57
58
            else
59
            {PWM_cnt++;}*/
60
              
61
        TCCR0=0; TCNT0=255; TCCR0=4;                        // f:256, Timer0 starten
62
        TIMSK = _BV(TOIE0);                                     // Timer0 Overflow INT erlauben
63
64
}


muss ich die hsv_to_rgb() auch noch umschreiben??

von micha (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

Ich wollte mich erstmal für den Code bedanken!

Er lief bei mir auf dem Attiny25 fast ohne größere Änderungen.

Ich habe ihn noch um 3 Funktionen erweitert, die ich euch nicht 
vorenthalten will. Mittels eines Tasters an PB1 kann zwischen 
"RGB-Farblauf", "Farbe anhalten", und "Weiss". geschalten werden.

Villeicht hilfts dem ein oder anderen ja auch.

Micha

von uC (Gast)


Lesenswert?

Hallo zusammen,

würde das mit der hsv nach rgb Umrechnung auch mit 16Werten 
funtionieren?

Also ich hab 3x16Bit PWM und möchte damit rgb leds ansteuern.
Jetzt hab ch schon stundenlang versuch die umrechnug von HSV nach RGB mt 
16Bit Zahlen zu realisieren bekomme das aber nicht hin?

Kann mir jemand von euch vielleicht weiter helfen?

Vielen Dank im Voraus!

von Tom (Gast)


Lesenswert?

Tja, man sollte halt wissen was genau Du nicht hinbekommst...
Formeln stehen hier: http://de.wikipedia.org/wiki/HSV-Farbraum

von Jackattac (Gast)


Lesenswert?

So weit bin ich jetzt gekommen.

void hsv_to_rgb (uint16_t h, uint16_t s, uint16_t v)
{
        uint8_t i;
        uint16_t r, g, b, f, p, q, t;
        if( s == 0 )
        {       r = g = b = v;
        }
        else
        {       i=h/10922;
                f=h%10922;
                p = (v * (65535 - s))/65536;
                q = (v * ((715707735 - (s * f))/10922))/65536;
                t = (v * ((715707735 - (s * (10921 - f)))/10921))/65536;
                switch( i )
                {       case 0:
                            r = v; g = t; b = p; break;
                        case 1:
                            r = q; g = v; b = p; break;
                        case 2:
                            r = p; g = v; b = t; break;
                        case 3:
                            r = p; g = q; b = v; break;
                        case 4:
                            r = t; g = p; b = v; break;
                        case 5:
                            r = v; g = p; b = q; break;
                }
        }
        cli();          // Kein Interrupt beim übernehmen der neuen 
Werte!
        red=r, green=g, blue=b;
        sei();
}

Also von der Rechnung her sollte es passen. Doch leider funktioniert es 
nicht wenn ich es an meinem uC teste.

von H. G. (ledi)


Lesenswert?

Hallo Leute!

Ich habe den Code von Fly für meinen AT90PWM316 etwas abgeändert.
Da ich ein Stimmungslicht bauen möchte, benötige ich langsame und weiche 
Farbübergänge.

Meine Frage: WIE schaffe ich weiche Farbübergänge?
1
/*
2
Author:   Fly 
3
Datum:      06.10.06
4
Programm:  rgb.c
5
Systemtakt:  8 MHz, intern / CLKDIV8
6
7
8
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
9
Funktion:  Dimmt 10 Farbtöne automatisch
10
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
11
12
13
Hardware:   AT90PWM316
14
PB0   --> LED Rot
15
PB1   --> LED Grün
16
PB2   --> LED Blau
17
18
19
H:          der Farbton als Farbwinkel H auf dem Farbkreis (z. B. 0° = Rot, 120° = Grün, 240° = Blau) 
20
S:          die Sättigung S in Prozent (z. B. 0% = keine Farbe, 50% = ungesättigte Farbe, 100% = gesättigte, reine Farbe) 
21
V:          der Grauwert V als Prozentwert angegeben (z. B. 0% = keine Helligkeit, 100% = volle Helligkeit)
22
23
Skalierung der HSV Werte:
24
H:      0-360,  float Auflösung
25
S:      0-1,   float Auflösung, nicht verändern
26
V:      0-1,   float Auflösung  
27
*/
28
29
30
#define     Ledport             PORTB    // RGB Led Port
31
#define     DDR_Ledport         DDRB
32
#define     R                   0      // R Ausgang
33
#define     G                   1      // G
34
#define     B                   2      // B
35
#define     Get_New_RGB_Value   1      // Statusbit
36
37
#include <avr/io.h>
38
#include <avr/interrupt.h>
39
#include <stdlib.h>
40
#include <math.h>
41
42
43
// Prototypen
44
void hsv_to_rgb (void);
45
46
47
// Globale Variabeln (Timer ISR)
48
volatile int    Red, Green,    Blue;             // PWM Register
49
volatile float      H,   S,        V;                        
50
volatile uint8_t    Statusreg;
51
volatile int        PWM_cnt, timebase;              // Counter Einschaltzeit
52
53
  
54
55
//-------------------------------------------------------------------------------
56
//Hauptprogramm
57
//-------------------------------------------------------------------------------
58
int main(void)
59
{
60
 DDR_Ledport=255;   Ledport=0;              // Led aus
61
 PWM_cnt=0;    Statusreg=0;                // Variabel init.
62
63
 H=0, S=1, V=1;                      // HSV Startwerte, rot, volle Helligkeit
64
 hsv_to_rgb();                      // HSV to RGB
65
66
 TCCR0A=0; TCNT0=255; TCCR0B=5; TIMSK0 = _BV(TOIE0);    // T0 Starten, Overflow Interrupt f/256
67
 sei();                                                 // Enable Interrupts
68
69
 while(1)
70
 {
71
      if (Statusreg == Get_New_RGB_Value)             // Wenn HSV Werte geändert
72
       { hsv_to_rgb(); Statusreg=0; }          // HSV to RGB, Status zurücksetzen
73
  }
74
}
75
76
77
//-------------------------------------------------------------------------------
78
//HSV nach RGB konvertieren
79
//-------------------------------------------------------------------------------
80
81
82
void hsv_to_rgb(void)  
83
{
84
 float h=H;       // HSV Werte kopieren
85
 float s=S;
86
 float v=V;
87
88
 float r,g,b;      
89
90
 int i;
91
 float f, p, q, t;
92
93
 if( s == 0 ) 
94
   {
95
  r = g = b = v;
96
  return;
97
  }
98
99
 h /= 60;        // sector 0 to 5
100
 i = floor( h );
101
 f = h - i;      
102
 p = v * ( 1 - s );
103
 q = v * ( 1 - s * f );
104
 t = v * ( 1 - s * ( 1 - f ) );
105
106
 switch( i )
107
      {
108
    case 0:
109
      r = v; g = t; b = p; break;
110
    
111
    case 1:
112
      r = q; g = v; b = p; break;
113
      
114
    case 2:
115
      r = p; g = v; b = t; break;
116
        
117
    case 3:
118
      r = p; g = q; b = v; break;      
119
        
120
    case 4:
121
      r = t; g = p; b = v; break;
122
                
123
    default:                
124
      r = v; g = p; b = q; break;        // case 5:          
125
    }
126
127
 
128
 int rc=r*255;                    // Auf 8 Bit RGB skalieren, nacher nur noch kopieren
129
 int gc=g*255;
130
 int bc=b*255;    
131
  
132
 cli();                                              // Kein Interrupt beim übernehmen der neuen Werte!
133
 Red=rc, Green=gc, Blue=bc;      
134
 sei();
135
136
}
137
138
//-------------------------------------------------------------------------------
139
//Timer  0 Interrupt, f/256
140
//-------------------------------------------------------------------------------
141
142
ISR (TIMER0_OVF_vect)
143
{
144
if ((PWM_cnt <=Red) && (Red!=0))
145
            { Ledport |= (1 << R);}                             // Rot aktiv
146
            else {Ledport &= ~(1 << R);}                        // Rot inaktiv
147
148
        if ((PWM_cnt <=Green) && (Green!=0))
149
            { Ledport |= (1 << G);}                       
150
            else {Ledport &= ~(1 << G);}     
151
        
152
        if ((PWM_cnt <=Blue) && (Blue!=0))
153
            { Ledport |= (1 << B);}                        
154
            else {Ledport &= ~(1 << B);}                  
155
156
        if (PWM_cnt==255)                    // Wenn PWM Periode vorbei 
157
            {
158
              PWM_cnt=0; timebase++;              // Neustart
159
              if (timebase == 5)                                // Geschwindigkeit des Ablaufs
160
                  {
161
           timebase=0; V=(V-0.005);            // Helligkeit dimmen, Geschwindigkeit abhängig von timebase, Auflösung beliebig (float)
162
                   if (V<=0)                   // Wenn Helligkeit = 0
163
               {
164
             V=1; H=(H+36);              // Volle Helligkeit, Neuer Farbton, 10 Farbtöne, Auflösund beliebig veränderbar (float)
165
             if (H>=360) {H=0;}
166
             }                
167
                   Statusreg = Get_New_RGB_Value;        // Neue HSV Werte Stausbit aktiv
168
                  }                                           
169
            }
170
171
            else
172
            {PWM_cnt++;}
173
              
174
        TCCR0A=0; TCNT0=255; TCCR0B=4;                        // f:256, Timer0 starten
175
        TIMSK0 = _BV(TOIE0);                                     // Timer0 Overflow INT erlauben
176
}

von Fly (Gast)


Lesenswert?

Hallo Heimo

Habe mein Thread schon ein paar Jahre nicht mehr angeschaut und das 
Projekt auch nicht mehr angefasst :-)

Weiche Übergänge:

1.
Es rechnet schon mit float, eine höhere Auflösung ist wohl nicht mehr 
möglich.. und imo auch nicht nötig.

2.
Weiche Übergänge schaffst du mit 1. und LANGSAMEN Übergängen. Oder hast 
du das Problem das bei langsamen Übergängen trotzdem noch "springt"?
Wie die Geschwindigkeit eingestellt wird hast du herausgefunden?

Grüsse, fly

von Schnitzel (Gast)


Lesenswert?

Moin,

was spricht hier eigentlich gegen Festkommaarythmetik?
http://www.mikrocontroller.net/articles/Festkommaarithmetik

Sitze auch gerade daran hsv in rgb und zurück zu wandeln und werde mich 
dessen jetzt mal annehmen.

Gruß Schnitzel

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.