Hallo an Alle!
Ich habe ein kleines Problem und brauche eine Idee oder einen
Denkanstoß.
Meine 10W-LED betreibe ich an einem LED-Treiber (LM3404), den ich per
Tiny dimmen kann.
Der Sollwert wird durch ein Poti eingestellt (10bit-ADC) und meine
10bit-PWM läuft mit 122Hz. Um die LED für unser Auge linear zu dimmen
nutze ich ein Array mit 64 Werten so wie es im Artikel "LED-Fading" hier
im Forum beschrieben ist.
Das Problem ist, dass es bei manchen Potieinstellungen die LED flackert.
Dies kommt daher, da die PWM zwischen zwei Werten des Arrays springt.
Wie kann ich das verhindern?
Grüße und Danke, Nico
An Deiner Stelle würde ich kleinere Änderungen am Poti (ADC) ignorieren,
d.h. erst mit einer PWM-Änderung reagieren, wenn der gemessene
Unterschied zur letzten Spannung am ADC einen Schwellwert überschreitet.
Nico ... schrieb:> ies kommt daher, da die PWM zwischen zwei Werten des Arrays springt.
Eventuell reicht es wenn du zwischen Poti Ausgang und Masse einen
kleinen Kondensator machst (220nF - 1µF)
Ausserdem nur die oberen 8 oder gar nur 6 Bit des Wandlers auswerten,
mehr brauchst du bei 64 PWM Stufen eh nicht.
Wenn das nicht reicht musst du softwareseitig einen Schmitt-Trigger
einbauen. Sprich du merkst dir den letzten Potiwert bei dem du die PWM
verändert hast und machst die nächste Änderung der PWM erst wenn sich
der aktuelle Potimesswert um 1/256 oder 1/128 des Gesamtbereichs
verändert hat.
Hallo!
@urschmidt
Daas "Glätten" mit Kondensator oder die Beschneidung auf weniger Bits
hilft nicht. Es gibt immer einen Punkt wo sich - auch wenn nur das LSB
des AD-Wandlers springt - auch z.B. das 6-te Bit "springt". Da ist es
egal ob du die untersten 5 ausblendest.
Die einzige Lösung ist die (Software-)Hysterese.
Route 66 schrieb:> Es gibt immer einen Punkt wo sich - auch wenn nur das LSB> des AD-Wandlers springt - auch z.B. das 6-te Bit "springt". Da ist es> egal ob du die untersten 5 ausblendest.
Prinzipiell richtig, aber je nachdem wie stark die Messwerte 'zappeln'
wird der Effekt durch den Tiefpass so gering daß er nicht mehr stört.
Hallo route_66, wie Du schon erklärt hast bringen der Kondensator oder
das Abschneiden der Bits nichts.
Aber wie implementiere ich eine Software-Hysterese?
Selbst dann gibt es immer noch die Möglichkeit, dass der Messwert genau
am Schaltpunkt hin und her kippelt.
Eine Hysterese in Software ist doch kein Hexenwerk. Man braucht dazu
keine externe Beschaltung und auch sonst nichts ausser ein wenig
Programmieren.
Nico ... schrieb:> Hallo route_66, wie Du schon erklärt hast bringen der Kondensator oder> das Abschneiden der Bits nichts.>> Aber wie implementiere ich eine Software-Hysterese?
Wie sieht denn dein Programm jetzt aus?
(Hättest du am Anfang schon zeigen sollen)
Eine Hysterese ist ganz einfach:
'Hochgeschaltet' wird bei einem etwas größerem Wert als der
Schaltschwelle. 'Runtergeschaltet' bei einem etwas kleineren.
Sinn der Sache ist es, dass bei einem Wert der gleich (bzw. ungefähr
gleich) der Schaltschwelle ist, immer die Stufe bevorzugt wird, die
vorher schon vorhanden war.
Wie man das konkret macht, hängt von der jeweiligen Implementierung bzw.
den Details der Aufgabenstellung ab.
Nico ... schrieb:> Dies kommt daher, da die PWM zwischen zwei Werten des Arrays springt.> Wie kann ich das verhindern?
Wenn das zwei benachbarte Werte des Arrays sind, hilft nur, die Tabelle
feiner zu machen bzw. zwischen den Tabellenwerten zu interpolieren.
Mittelwertbildung/Tiefpassfilterung würde da nicht helfen, weil damit
allenfalls die Häufigkeit der Sprünge verringert wird, nicht aber die
Sprunghöhe unsichtbar wird.
Nico ... schrieb:
In dem Fall würde ich es so machen
> wert = 0;> for(unsigned char i=0; i<16; i++)> {> ADCSRA |= (1<<ADSC);> while(ADCSRA & (1<<ADSC));> wert = wert + (ADCH / 4);> }
1
wert2=wert/16;
2
reminder=wert%16;
3
4
if(reminder>1&&reminder<14)
5
wert=wert2;
Sinn der Sache ist es hier
+-------+-------+-------+-------+-------+-------+ -> ADC Wert
jweils kleine Bereiche einzubauen
+-------+-------+-------+-------+-------+-------+ -> ADC Wert
xxx xxx xxx xxx xxx xxx
In denen sich die PWM-Stufe nicht ändert. Bewegt sich der ADC Messwert
in diesem Bereich, dann wird einfach immer der letzte Zustand
beibehalten. Erst wenn der Messwert eindeutig von diesem Umschaltpunkten
entfernt ist, dann wird er für die Bestimmung der PWM Stufe
herangezogen.
De facto werden daher nur diese ADC-Messwerte
+-------+-------+-------+-------+-------+-------+ -> ADC Wert
##### ##### ##### ##### ##### #####
zur Bestimmung der PWM-Stufe herangezogen. In den Bereichen dazwischen
gilt immer die Stufennummer, die vorher eingestellt war, und ändert sich
nicht. Wird dieser Totbereich 'von oben' betreten, dann gilt die obere
Stufennummer. Wird er 'von unten' betreten, dann gilt die untere
weiterhin.
Nachteilig bleibt bei jeder Art von Software-Hysterese, die mangelhafte
Haptik - das "Spiel" bei der Einstellung (d.h. das sich beim Hoch- bzw.
herunterdrehen die Zuordnung Drehwinkel zu Spannung ändert), kann
bemerkbar und störend sein.
Überlegt man, welche Funktionalität man sich eigentlich wünscht:
- stetige, spielfreie und feinfühlige Umwandlung von Drehwinkel in
Spannung, solange man am Poti dreht
- Nachdem die Hand das Poti verlassen hat: Ein Festhalten des letzten
vom Poti gelieferten und gespeicherten (also nicht mehr fortlaufend neu
digitalisierten) Spannungswertes.
...sollte man vielleicht für den Controller erkennbar machen, ob sich
gerade eine Hand am Potiknopf zu schaffen macht oder eben nicht, und
dazu eine "Knopf-Touch"-Erkennung vorsehen. Bspw. mit Metallknopf und
kapazitiv...
Nico ... schrieb:> Der Sollwert wird durch ein Poti eingestellt (10bit-ADC) und meine> 10bit-PWM läuft mit 122Hz.
meine Meinung:
Entweder man macht das ganz digital:
Falk Brunner schrieb:> gleich einen Drehgeber mit RICHTIGER> Auswertung
oder man bleibt analog:
> Statt dem Tiny einen schnöden NE555 verbauen.> Damit geht die PWM Stufenlos mit dem Poti zu regeln, und mehr als 122 Hz> sind auch drinnen.> (Wegen der "pwmtable": Potis gibts mit passender Kennlinie fertig zu kaufen)
Ich würde den 10bit Wert nehmen und anhand dessen entscheiden, welche
beiden Felder der LUT relevant sind und dazwischen linear interpolieren.
1
lutInd=adcVal/16;// 10bit -> 6bit
2
remainder=adcVal%16;// nachkommaanteil <-- remainder mit a
3
4
val1=pwmtable[lutInd];
5
val2=pwmtable[lutInd+1];// hier aufpassen wegen +1
6
7
pwmval=val1+((val2-val1)*remainder)/16;// hier wegen überläufen aufpassen
Dann braucht man keine Hysterese mehr, weil das Kippeln von ein paar
bits nicht stören sollte.
eventuell kann man noch einen Mittelwert- oder Medianfilter davorsetzen,
der sollte aber nicht zu lang sein, weil es sonst auch zu Verzögerungen
kommt.
Noch was:
ich würde die PWM-Frequenz wenigstens nochmal verdoppeln.
120Hz ist ziemlich nervig.
Hallo Karl Heinz und danke für die Idee. Leider scheint es nicht zu
funktionieren. Die LED blitz so nur bei Potiveränderung auf und ist
sonst aus. Woher das kommt, verstehe ich noch nicht.
Hallo Ernst, der Tiny hat den Sinn noch andere Aufgaben zu
erledigen...deswegen ein µC. Die 122Hz haben den Sinn, dass der Treiber
inkl. Beschaltung keine hörbaren Töne von sich gibt!
Fahr doch einfach an den nächsten Tabellenwert heran, statt dort hin zu
springen. Dann sind die Flackereien "smooth". der Hannes macht das bei
den Modellbaureglern so. Die Vorgabe erreicht den Motor nicht direkt,
sondern es wird an die Vorgabe innerhalb einer bestimmten Zeit
herangefahren.
ich hatte seinerzeit mal die Ansteuerung eines Gokart-Elektromotors
gepostet. da habe ich das auch so gelöst. Dort gab es eine
Beschleunigungstabelle und abhängig von der "Gas" Stellung wurde die
Leistung des Motors nicht sofort aus der Tabelle genommen, sondern
erstmal mit dem eingegebenen Wert verglichen und alle 10mSek an den
Tabelleneintrag angeglichen.
Wenn Du willst, suche ich das mal raus.
Axelr.
Εrnst B✶ schrieb:> oder man bleibt analog:>>> Statt dem Tiny einen schnöden NE555 verbauen.>> Damit geht die PWM Stufenlos mit dem Poti zu regeln, und mehr als 122 Hz>> sind auch drinnen.>> (Wegen der "pwmtable": Potis gibts mit passender Kennlinie fertig zu kaufen)
dann hat man aber keine Logarithmierung der Kennlinie.
Hallo Axelr., eine kleine Regelung sozusagen!?
Hätte nicht gedacht, dass dies so kompliziert wird. Nach der
Beschneidung des ADC-Wertes auf 6Bit ist das Umspringen schon stark
zurück gegangen. Ich denke das reicht mir erstmal so!
Danke erstmal an Alle!
axelr schrieb:> Fahr doch einfach an den nächsten Tabellenwert heran,
das könnte man wunderbar mit meinem Vorschlag kombinieren in dem man am
ende jedes (oder einem vielfachen davon) PWM-Zyklus den PWM wert auf den
nach obigen Ansatz berechneten heranführt
Hat den Nachteil, dass wenn der Benutzer schnell an dem Poti dreht, die
Änderung unangenehm nachläuft.
Nico ... schrieb:> Ich denke das reicht mir erstmal so!
wenn der adcwert aber zwischen
9876543210
0010000000
und
0001111111
tocgelt, bist du wieder da.
Die Symptome werden nicht abgeschwächt nur die Häufigkeit auf 1/16tel
reduziert.
Nico ... schrieb:> Hallo Karl Heinz und danke für die Idee. Leider scheint es nicht zu> funktionieren. Die LED blitz so nur bei Potiveränderung auf und ist> sonst aus. Woher das kommt, verstehe ich noch nicht.
Dein Code?
Wenn du Hilfe mit deinem Code brauchst, dann zeige immer deinen Code.
Auch wenn dir jemand ein Codestückchen gibt: zeige es her! Es besteht
immer noch die Chance, dass du das Stückchen nicht so eingebaut hast,
wie sich das der Autor vorgestellt hat.
:-)
Oder er hat einen Fehler gemacht.
Du darfst natürlich das OCR Register auch nur dann beschreiben, wenn du
einen neuen Wert hast. Du hast ja vorher die Variable 'wert' mit dem ADC
überschrieben. Daher taugt der nicht mehr als Array-Index.
@Vlad Tepesch (vlad_tepesch)
>wenn der adcwert aber zwischen>9876543210>0010000000>und>0001111111>tocgelt, bist du wieder da.
Kauf einen Poti mit Rastung ;-)
>>> Damit geht die PWM Stufenlos mit dem Poti zu regeln, und mehr als 122 Hz>>> sind auch drinnen.>>> (Wegen der "pwmtable": Potis gibts mit passender Kennlinie fertig zu>>> kaufen)>dann hat man aber keine Logarithmierung der Kennlinie.
Doch, deswegen ja "Potis gibts mit passender Kennlinie", aka
logarithmische Kennlinie.
Naja, man kriegt das schon hin mit dem Poti. Und es wird sicher nicht
EINE Massnahme allein wirken, sondern erst mehrere zusammen.
1.) Filter, damit das Zappeln auf ein Minimum reduziert wird.
2.) Bitbreite der ADC-Messung sinnvoll wählen, 10 Bit sind schon sehr
ambitioniert, wenn gleich möglich.
2.) Dithering. Man merkt sich immer den vorhergehenden, verschiedenen
Wert. Zwischem dem und dem aktuellen springt man immer hin und her, mit
hier 122Hz. Damit hat man das Flackern ausgetrickst, weil es sowieso
immer "flackert". Ggf. muss man etwas höher in der Frequenz gehen, so
200-300 Hz, damit effektiv 100-150 Hz rauskommen. Muss man mal
probieren.
Nico ... schrieb:> Die 122Hz haben den Sinn, dass der Treiber> inkl. Beschaltung keine hörbaren Töne von sich gibt!
O_o
Wenn das passiert ist irgendwas falsch und nein, nicht die Frequenz
Das funktioniert im übrigen allerdings nur, wenn du mit der Hand drehst,
weil dein µC schneller ist, als du drehen kannst und es daher nicht
passieren kann, dass eine Stufe übersprungen wird.
Sorry, falls ich etwas übersehen habe. Aber warum machst Du die
Lookup-Tabelle nicht einfach größer, also z.B. 256 Einträge? Wenn das
RAM nicht reicht, kannst Du sie ja per PROGMEM in den Flash legen. Oder
Du interpolierst zwischen zwei Werten.