PWM Steuerung einer RGB-LED

OP #2502659
Lesenswert?

Guten Abend Foren-Gemeinde,

Ich habe folgende Frage, und zwar ich habe an einem ATmega32 am PORTA 
PB0-PB2 ein RGB-LED mit Vorwiderständen angeschlossen. Der ATmega32 
läuft mit internem RC-Oszi bei 8MHz. Das Fading zwischen den Farben ist 
schön langsam und ruhig. Nur eins stört mich wenn die einzelnen 
Grundfarben auf 0% gesteuert werden, bzw von 0% auf 100%. Dann sieht man 
die einzelnen Stufen wie die LED immer dunkler wird bzw wieder heller 
wird aber nur die ersten 10 Abstufungen. Darüber ist alles Perfekt. 
Liegt das nun aus Elektrischer Sicht her an der LED etc. oder am 
Programm selber? Vielen Dank erstmal.
1
C-Code
2
#include <avr/interrupt.h>
3
#include <avr/io.h>
4
#include <avr/iom32.h>
5

6
#define F_CPU 8000000UL
7
#define TIMER0_OVF0_vect TIMER0_OVF_vect
8
#define TCCR0A TCCR0
9

10
volatile char pwm_counter,pwm_r,pwm_g,pwm_b;
11

12
ISR (TIMER0_OVF0_vect)
13
{
14
  if (pwm_counter++ > 63)
15
  {
16
    PORTA = 0x00;
17
    pwm_counter = 0;
18
  }
19

20
  if (pwm_counter > pwm_r ) PORTA |= (1<<0);
21
  if (pwm_counter > pwm_g ) PORTA |= (1<<1);
22
  if (pwm_counter > pwm_b ) PORTA |= (1<<2);  
23
}
24

25
int main (void)
26
{
27
  DDRA = (1<<0)|(1<<1)|(1<<2);         //Port für LED auf output
28
  TIMSK |= (1 << TOIE0);            //Interrupt for the Clock enable
29
  TCCR0A |= (1<<CS00)|(0<<CS01)|(0<<CS02);  //Rescaler 
30

31
  sei();
32

33
  pwm_r = 0;
34
  pwm_g = 64;
35
  pwm_b = 64;
36

37
  while(1)
38
  {
39
    for (char a = 0; a<65; a++)
40
    {
41
      pwm_r = a;
42
      pwm_b = 64 - a;
43
      for (long b = 0;b<1000000;b++){asm("nop");};
44
    }
45

46
    for (char a = 0; a<65; a++)
47
    {
48
      pwm_b = a;
49
      pwm_g = 64 - a;
50
      for (long b = 0;b<1000000;b++){asm("nop");};
51
    }
52

53
    for (char a = 0; a<65; a++)
54
    {
55
      pwm_g = a;
56
      pwm_r = 64 - a;
57
      for (long b = 0;b<1000000;b++){asm("nop");};
58
    }
59
  }
60
}
Gast #2502686
Lesenswert?

Dein Problem sind deine Augen! bzw. die jedes Menschen.

Die Wahrnehmung von Licht verläuft Logarithmisch. D.h. wenns dunkel ist 
fällt dir ein bisschen Licht mehr schon auf, wenns aber eh schon Hell 
ist brauchst du wesentlich mehr Helligkeit um einen Unterschied 
festzustellen.

Steht aber alles im Wiki zum Thema LED Fading
OP #2502700
Lesenswert?

Das wird es sein :) Meine Augen daran habe ich auch schon überlegt nach 
dem ich das ganze Programm einfach schneller Ablaufen lassen habe. Wie 
sieht es denn aus kann ich die Auflösung des PWM noch erhöhen, bzw die 
Abstufungen verfeinern oder bin ich schon an der oberen Grenze 
angekommen. Habe mir die PWM Geschichte im Detail noch genau angeschaut, 
ich habe es mal auf gut Glück probiert, und war froh das es lief nach 
einer ganzen Nacht. Aber Danke schon mal.
Gast #2502796
Lesenswert?

Herr Biber schrieb:
> Dein Problem sind deine Augen!

Das Problem sind nicht die Augen, sondern das Programm.
Die Helligkeit sollte von Stufe zu Stufe um einen bestimmten Faktor 
steigen. Wegen der endlichen Auflösung der PWM muß man da natürlich 
Kompromisse machen, aber 0, 1, 2, 4, 8, .... würde die Sache schon 
besser machen.
OP #2503961
Lesenswert?

Ok Danke euch beiden erstmal ich werde mal schauen was sich da so machen 
lässt. Hab aber noch eine andere Frage, und zwar wie kann ich 
realisieren das ich die PWM anhalten kann? Sprich wenn z.B. die Farbe 
orange leuchtet, das ich per Tastendruck die Farbe halte, und nicht 
weiter läuft in die nächste Farbe. Und wenn ich dann erneut auf den 
Taster drücke oder auch ein anderer Taster. Das es dann ganz normal 
weiter läuft.

Gruß, Daniel Joachims
#2503970
Lesenswert?

Daniel Joachims schrieb:
> Ok Danke euch beiden erstmal ich werde mal schauen was sich da so machen
> lässt. Hab aber noch eine andere Frage, und zwar wie kann ich
> realisieren das ich die PWM anhalten kann?

Indem du diesen ganzen Ansatz
1
  while(1)
2
  {
3
    for (char a = 0; a<65; a++)
4
    {
5
      pwm_r = a;
6
      pwm_b = 64 - a;
7
      for (long b = 0;b<1000000;b++){asm("nop");};
8
    }
9

10
    for (char a = 0; a<65; a++)
11
    {
12
      pwm_b = a;
13
      pwm_g = 64 - a;
14
      for (long b = 0;b<1000000;b++){asm("nop");};
15
    }
16

17
    for (char a = 0; a<65; a++)
18
    {
19
      pwm_g = a;
20
      pwm_r = 64 - a;
21
      for (long b = 0;b<1000000;b++){asm("nop");};
22
    }

überdenkst.
Solche 'Ablaufsteuerungen' mittels for-Schleife und einem Delay 
dahinter, sind zwar einfach programmiert aber auch genauso unflexibel, 
wenn man auch nur ein bischen mehr will.


Was du brauchst:
Einen Mechanismus, der die 'Farbeinstellung' abhängig davon, auf welcher 
Einstellung sie gerade ist, beim nächsten Aufruf des Mechanismus auf den 
nächsten Wert setzt.

Eine Statemachine mit 3 Zuständen und einem laufenden Dimm-Index 
(dein jetziges a) wäre dafür zb genau das Richtige.
Die Farbe wechselt nur, solange die State Machine auch aufgerufen wird. 
Keine Aufrufe - kein Farbwechsel. Und dieser Aufruf lässt sich ja mit 2 
Tasten leicht ein und ausschalten.
OP #2503993
Lesenswert?

Hallo Karl-Heinz,

Danke für deine Antwort, aber leider versteht ich Bahnhof welches wohl 
daran liegt das ich noch zu wenig Erfahrungen damit habe. Da werde ich 
mir wohl noch etwas Lektüre aneignen. Ich habe schon gehofft das es nur 
eine Kleinigkeit ist, da wurde ich dann gerade von zurück auf den Boden 
der Tatsachen geholt. Es sind ja noch keine Meister vom Himmel gefallen 
:)

Gruß, Daniel Joachims

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren