Forum: Mikrocontroller und Digitale Elektronik PWM Steuerung einer RGB-LED


von Daniel J. (n0i5ebreak3r)


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
}

von Herr Biber (Gast)


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

von Daniel J. (n0i5ebreak3r)


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.

von Wolfgang (Gast)


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.

von Daniel J. (n0i5ebreak3r)


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

von Karl H. (kbuchegg)


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.

von Daniel J. (n0i5ebreak3r)


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

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.