Forum: Mikrocontroller und Digitale Elektronik Led Fading mit Soft PWM "ruckelt"


von RGB und AVR-Anfänger (Gast)


Lesenswert?

Guten Abend!

Ich beschäftige mich seit kurzer Zeit mit AVRs. Ich möchte auf lange 
Sicht gerne eine Farbmischung mittels einer RGB Led programmieren.

Nun habe ich erstmal angefangen einen Chip(also eine Farbe der LED) mit 
SoftPWM  heller und dunkler zu faden.
Leider flackert und ruckelt die Farbmischung sehr stark(vorallem in 
"dunkleren" Bereichen).

Hardware(hier sollte alles richtig sein):
Als Hardware habe ich einfach den entsprechenden Pin der LED mit 
Vorwiederstand an den Portpin des AVR angeschlossen.

Software/Pseudocode(ist hier ein Denkfehler?):

Taktfrequenz vom Atmega ist 1MHz
Ich betreibe den Timer im normalen Modus mit Prescaler 1.
Der Timer löst einen Overflow Interrupt aus.

In der Interruptroutine wird eine Variable(z.B. "heller") hochgezählt 
solange sie kleiner als z.b. 255 ist.

Im Hauptprogramm wird nichts gemacht außer die Led anzuschalten wenn 
TCNT0(der aktuelle Timerwert) kleiner als "heller" und sie auszuschalten 
wenn TCNT0 größer als "heller" ist


Es wäre super, wenn mir jemand weiterhelfen kann.
P.S.: Mein Problem ist nicht, dass die LED sehr schnell hell wird und 
dann hell bleibt, was ja an der Kennlinie des menschlichen Auges liegt!

Nochmal genau wie sich die LED verhält:
- erst blitzt die LED immer nur kurz auf, flackert also langsam
- ab einer gewissen Helligkeit ist das Flackern weg und die LEd leuchtet 
relativ homogen, aber die Helligkeitssprünge sind abrupt/ sprunghaft und 
nicht flüssig

Vielen Dank für eure Hilfe

von Ralf (Gast)


Lesenswert?

Tja, mal wieder keinen echten Code gepostet... Gibt ne 5 und ausserdem 
nur Vermutungen.

Ohne den AVR genau zu kennen und auch nicht zu wissen, ob der Timer 8- 
oder 16-Bit breit ist, würde ich mal vermuten, dass dein Ruckeln durch 
die zu langsame Taktfrequenz kommt...

Gehe ich von einem MHz Takt aus, braucht der Timer bei 16-Bit etwa 65ms, 
was wiederum 15Hz entspricht, und das würde ich als flackernde 
PWM-Frequenz ansehen.

Also, entweder Taktrate erhöhen, oder Timer bei 16-Bit nicht voll 
durchlaufen lassen oder für einen schnellen Test auf 8-Bit setzen.

Ralf

von Karl H. (kbuchegg)


Lesenswert?

RGB und AVR-Anfänger schrieb im Beitrag #1750283:

> Im Hauptprogramm wird nichts gemacht außer die Led anzuschalten wenn
> TCNT0(der aktuelle Timerwert) kleiner als "heller" und sie auszuschalten
> wenn TCNT0 größer als "heller" ist

Das ist unbrauchbar. Damit kriegst du keine stabile PWM mit immer 
konstanten Pulsbreiten hin. TCNT0 verändert sich viel schneller als das 
dein Programm das mitkriegen würde.

Zeig dein Programm und beschreibe es nicht.

von Karl H. (kbuchegg)


Lesenswert?

Und dreh als erstes die Taktfrequenz deines Mega hoch, wenn das möglich 
ist.

von thisamplifierisloud (Gast)


Lesenswert?


von RGB und AVR-Anfänger (Gast)


Lesenswert?

Danke euch allen schonmal für die Hilfe.
Ihr habt Recht, mein Beitrag hätte wohl besser sein können.

Ich hab sehr viele Versuche gemacht - mit verschiedenem code.

Ein Beispiel in dem die Farbsprünge am Anfang gut zu sehen sind ist 
dieser code:

(Das verhalten der LED: dunkel...etwas heller --> Sprung: nen gutes 
Stück heller...etwas heller --> Sprung: nen gutes Stück heller - sobald 
die Led noch heller wird sind keine Sprünge mehr zu sehen)
1
#ifndef F_CPU
2
#define F_CPU 1000000UL 
3
#endif
4
5
#include <avr/io.h>
6
#include <util/delay.h>
7
#include <avr/interrupt.h>
8
9
#define rot_an    PORTA |= (1 << PA2)
10
#define rot_aus    PORTA &= ~(1 << PA2)
11
12
// Variablen definieren
13
volatile uint8_t rot;
14
15
// ***** Timer2-Overflow-Interrupt ******
16
ISR (TIMER2_OVF_vect){ 
17
// zähle die Variable rot von 0-254
18
rot++;
19
if (rot > 254) {timer = 0;}
20
}
21
22
// ***** Hauptprogramm *****
23
int main(void){
24
// Variablen setzen
25
rot = 0;
26
27
// PortA zu Ausgängen
28
DDRA= 0xff; 
29
PORTA= 0b00000000; 
30
31
// PB0 als Eingang, Pull-Up aktivieren
32
DDRB  &= ~(1<<PB2);  
33
PORTB |= (1<<PB2);     
34
                
35
// Timer 0 konfigurieren: Prescaler 1
36
TCCR0 = (1<<CS00);
37
38
// Timer 2 konfigurieren: Prescaler 1024
39
TCCR2 = (1<<CS20)|(1<<CS22);
40
// Overflow Interrupt Timer 2 aktivieren
41
TIMSK |= (1<<TOIE2);
42
43
// Global Interrupts aktivieren
44
sei();
45
46
// ***** Endlosschleife *****
47
while(1){
48
49
if (TCNT0 < rot) {rot_an;}
50
else {rot_aus;}
51
52
53
} //eof while
54
55
} //eof main

von Karl H. (kbuchegg)


Lesenswert?

RGB und AVR-Anfänger schrieb im Beitrag #1750377:

Wie schon gesagt, ist das

> // ***** Endlosschleife *****
> while(1){
>
> if (TCNT0 < rot) {rot_an;}
> else {rot_aus;}


zwar nett gedacht, aber unbrauchbar.
Du erwischt mit dem Code nicht oder nur zufällig den Zeitpunkt an dem 
TCNT0 genau die Schwelle des Grenzwertes überschreitet. Wenn dann noch 
mehr Code dazu kommt, wirds noch zufälliger.

Du brauchst definierte Zeitpunkte.
Mit dem Overflow Interrupt des Timers 0 wirst du mehr Glück haben. Den 
PWM Zähler musst du dir selber aufbauen.
Mit lediglich 1Mhz Taktfrequenz wirds aber eng mit einer 8Bit PWM. Daher 
muss die Taktfrequenz rauf. Kann dein µC interne 8MHz?


Allerdings wirst du auch dann, bei den kleinen Helligkeitsstufen Sprünge 
sehen. Unsere Augen sind da einfach zu empfindlich.

von RGB und AVR-Anfänger (Gast)


Lesenswert?

Danke, nun bin ich schon etwas schlauer.

Ich werde also den Overflow-Interrupt vom Timer nutzen um eine Variable 
hochzuzählen und zurückzusetzten (von z.b. 0-254) um dann diese mit 
meiner Variable "rot" zu vergleichen?
     - ist das so richtig ?

Beim CPU möchte ich später einmal einen Attiny25 nutzen(daher auch 
Software PWM).
Die Taktfrequenz hatte ich auf 1Mhz gelassen da ich gerechnet hatte 1Mhz 
/ 256 /1(Prescaler aus) = 3906,25Hz. Daraus geschlossen hatte ich 
geschlossen, dass die Frequenz locker ausreicht

Wie kann ich denn die Helligkeitssprünge weitestgehend vermeiden ?

Vielen Dank für eure Mühe.

von Falk B. (falk)


Lesenswert?

@  RGB und AVR-Anfänger (Gast)

>Wie kann ich denn die Helligkeitssprünge weitestgehend vermeiden ?

Durch Lesen und Anwenden des Artikels LED-Fading.

MFG
Falk

von Karl H. (kbuchegg)


Lesenswert?

RGB und AVR-Anfänger schrieb im Beitrag #1750415:
> Danke, nun bin ich schon etwas schlauer.
>
> Ich werde also den Overflow-Interrupt vom Timer nutzen um eine Variable
> hochzuzählen und zurückzusetzten (von z.b. 0-254) um dann diese mit
> meiner Variable "rot" zu vergleichen?
>      - ist das so richtig ?

genau.
Wenn du sie von 0-255 laufen lassen willst, dann mach sie als uint8_t 
Variable, dann brauchst du sie auch nicht zurücksetzen.

> geschlossen, dass die Frequenz locker ausreicht

jetzt dann nicht mehr
1
  1000000 / 256 / 256 = 15.irgendwas
das Flackern sieht man dann.

> Wie kann ich denn die Helligkeitssprünge weitestgehend vermeiden ?

Gar nicht. Dazu muss die Bitanzahl der PWM rauf. die hast du aber nicht.
Von einer PWMstufe von 0 auf 1 hast du nun mal einen Sprung. Von 1 auf 2 
hast du wieder einen Sprung.
genauso wie du von 234 auf 235 einen Sprung hast.
Nur sind unsere Augen bei kleinen Helligkeiten empfindlicher. Dort 
merken sie den Sprung, während bei den großen Helligkeiten der Sprung 
nicht weiter auffällt.
Tun kannst du dagegen nichts, ausser die PWM Bitanzahl hochzudrehen. 
Aber dann kommst du mit der Taktfrequenz nicht mehr hin, so dass nichts 
flackert.
Die sichtbaren Sprünge sind physikalisch bedingt. Und Physik lässt sich 
nun mal nicht überlisten.

von RGB und AVR-Anfänger (Gast)


Lesenswert?

Vieln Dank an Alle und vorallem an dich Karl heinz Buchegger!

Nun habe ich die Problematik verstanden!

P.S. die Artikel Led-Fading(und einige andere) kannte ich schon, jedoch 
ist es manchmal schwer nur vom Lesen allein alles zu verstehen.

Schönen Abend noch!

von Karl H. (kbuchegg)


Lesenswert?

RGB und AVR-Anfänger schrieb im Beitrag #1750435:
> P.S. die Artikel Led-Fading(und einige andere) kannte ich schon, jedoch
> ist es manchmal schwer nur vom Lesen allein alles zu verstehen.

Der Artikel LED-Fading ist dann nützlich wenn es darum geht mit einer 16 
Bit PWM einen konstanten Helligkeitsanstieg in einer bestimmten Zeit zu 
erreichen. Am grundsätzlichen Problem, dass bei kleinen PWM Bitzahlen in 
den kleinen Werten sichtbare Sprünge existieren, kabnn auch er nichts 
ändern.

von Sepp (Gast)


Lesenswert?

Der ATTINY24 hat bereits einen richtigen 8Bit PWM eingebaut!

Grüße,
Sepp

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.