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
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
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.
Und dreh als erstes die Taktfrequenz deines Mega hoch, wenn das möglich ist.
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 |
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.
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.
@ 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
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.
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!
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.