Hallo liebes Forum,
ich sitze gerade an einem selbst gebauten PWM-Dimmer und verzweifel am
korrekten Filtern des AD-Wertes für die Indizierung der Look-up-table.
Meine Idee war mehrere Samples zu nehmen, daraus dann den Mittelwert zu
bilden und das diesen Mittelwert in eine LUT zu geben.
Komischerweiße flackern die LED's dann deutlich, so wie sie es ohne die
Mittelwertberechnung nicht machen.
Daher vermute ich, dass ich irgendwo einen Überlauf habe, leider weiß
ich aber nicht wo.
Ich wäre dankbar, wenn mal jemand über meinen Quellcode schaut und mir
nen Tip gibt wo der Fehler liegen könnte..ich sehe es einfach nicht.
Vielen Dank und Gruß
•
>Daher vermute ich, dass ich irgendwo einen Überlauf habe, leider weiß>ich aber nicht wo.
filter = (filter+ (dutycalc-filter));
Was ist wenn dutycalc kleiner filter ist? Bummm;)
Jan schrieb:> ich sitze gerade an einem selbst gebauten PWM-Dimmer und verzweifel am> korrekten Filtern des AD-Wertes für die Indizierung der Look-up-table.
Kannst du mal verraten, was der ADC mit dem Dimmer zu tun hat und was
für einen Filtertyp dir vorschwebt?
Was du da machst, sieht sehr nach Sub-Sampling aus. Was du brauchst ist
ein gleitender Mittelwert oder ein Tiefpass.
holger schrieb:> Was ist wenn dutycalc kleiner filter ist? Bummm;)
Hm aber ich addiere danach doch dann wieder dutycalc drauf...also selbst
wenn ich einen Überlauf ins Negative bekomme, so läuft der Wert
anschließend wieder ins Positive über?
Der Dimmer besteht aus einem Atmega13, der über den ADC ein Poti
einließt und den eingelesenen Wert als Index für eine Look-up-table
nutzt, in der dann der Wert für den Duty-Cycle steht
Gruß
Jan schrieb:> filter = (filter+ (dutycalc-filter));
Was soll damit überhaupt erreicht werden?
Wenn meine Rechenkenntnisse mich nicht ganz verlassen haben, steht da
eine ausgeschmückte Version von
>holger schrieb:>> Was ist wenn dutycalc kleiner filter ist? Bummm;)>>Hm aber ich addiere danach doch dann wieder dutycalc drauf...also selbst>wenn ich einen Überlauf ins Negative bekomme, so läuft der Wert>anschließend wieder ins Positive über?
Na dann erklär mir mal wie unsigned Variablen negativ werden.
Ja Wolfgang du hast Recht! Es soll eigentlich
filter += (filter+ (dutycalc-filter));
heißen, das Plus ist mir irgendwie verlustig gegangen.
Ich habe bisher noch nichts mit digitalen Filtern zu tun gehabt, wollte
es auch nicht unnötig kompliziert aufblähen...daher dieser Ansatz
Jan schrieb:> Ja Wolfgang du hast Recht! Es soll eigentlich>> filter += (filter+ (dutycalc-filter));
Das ergibt aber dann erst recht keinen Sinn.
Wie soll das irgendwas filtern?
Das Aufsummieren für die Mittelwertsberechnung kommt doch erst danach.
Schmeiss die ganze Variable 'filter' und alles was mit ihr zusammenhängt
raus. Das verwirrt doch mehr als es nützt. Die Mittelwertbildung über 16
Samples sollte mehr als ausreichend sein.
Ja du hast Recht...mei ich glaube ich lass es für heute und geh ins
Bett, da kommt eh nichts mehr sinnvolles bei raus, bin total durch den
Wind.
Wenn ich versuche nur den Mittelwert zu bilden, dann hab ich ein totales
Flackern auf den LED's
Und je mehr Werte ich zur Mittelwertbestimmung mitnehm, desto schlimmer
wird es...Daher meine "Idee" mit dem filtern.
Uwe S. schrieb:> Und keine geht auf den Datentype:>>> uint16_t average;>> ein.>> Frage: wie oft passt da die Zahl 1024, also eine ADC Wert, hinein ?
er limitiert das zu summierende auf maximal 45.
Wenn auch etwas seltsam
if(dutycalc >= 46)
{
dutycalc = 44;
}
Jan schrieb:> Ja du hast Recht...mei ich glaube ich lass es für heute und geh ins> Bett, da kommt eh nichts mehr sinnvolles bei raus, bin total durch den> Wind.>> Wenn ich versuche nur den Mittelwert zu bilden, dann hab ich ein totales> Flackern auf den LED's> Und je mehr Werte ich zur Mittelwertbestimmung mitnehm, desto schlimmer> wird es...Daher meine "Idee" mit dem filtern.
?
Da würde ich mal in Richtung Timer-Einstellung gehen.
Timer wird nur einmal initialisiert und das wars dann.
Klar, kann den Rest vom Programm gern zeigen, sind aber mehrere Files,
daher als Zip.
Eine Messung mit dem Logik-Analysator hat ergeben, dass das Flackern von
unterschiedlichen Duty-Cyclen+s kommt...obwohl das Poti an ein und der
selben Stelle verbleibt
welcher Prozessor ist das eigentlich?
(Da hast du dir ja jede Menge Arbeit gemacht, die Einzelteile möglichst
auf so viele Files zu verstreuen, dass man nur ja dauernd Files wechseln
muss :-)
Es handelt sich um einen Attiny13A
Ja ich habe versucht die Software in Blöcke zu packen, um nur die
Hardware-Encapsulation austauschen zu müssen, wenn ich mal auf ein
anderes Zielsystem portiere.
Das macht es nicht gerade übersichtlicher, ist richtig :-S
Jan schrieb:> Es handelt sich um einen Attiny13A>> Ja ich habe versucht die Software in Blöcke zu packen, um nur die> Hardware-Encapsulation austauschen zu müssen, wenn ich mal auf ein> anderes Zielsystem portiere.> Das macht es nicht gerade übersichtlicher, ist richtig :-S
Ja.
Vor allen Dingen wenn man bedenkt, dass dein ganzes Programm auf knapp
eine einzige Bildschirmseite passen würde.
Aber egal. Beim Drüberscrollen durch die Files ist mir nichts großartig
aufgefallen.
Mich macht das immer noch stutzig, dass dein Flackern mit der Anzahl der
Messungen zu tun hat. Gib doch hier mal eine Konstante aus
Magic Numbers sind der Tod jedes Programmes.
Der Compiler kennt die Grösse deines Arrays.
Versuchs mal so:
if(dutycalc >= sizeof(DutyCycleLUT))
{
dutycalc = sizeof(DutyCycleLUT) - 1;
}
Ich will mich da jetzt ehrlich gesagt noch nochmal durch deinen Code
durchquälen.
Kann es sein, dass dein µC laufend abschmiert? Zb. wegen einem
freigegebenem Interrupt für den es keine ISR gibt?
Genau das versteh ich auch nicht. Wenn ich z.b nur 2 Messwerte nehme,
dann erkenne ich mit dem bloßen Auge kein Flackern.
Stell ich den Wert aber auf 16, so kann man es nicht nur messen, sondern
auch deutlich sehen.
Ich habe nun mal den Wert 23 hart auf average geschrieben und damit
bleibt der Duty-Cycle stabil. Kein Flackern mehr und auch die Messung
zeigt ein gleich bleibendes Tastverhältnis.
Kann es vielleicht sein, dass durch das Sammeln der Werte die Zeitspanne
zwischen den aktualisierungen des Duty-Cycles zu groß ist und man dann
einen springenden Wert leichter erkennt, als wenn der Duty-Cycle in
jedem Interrupt-Durchlauf aktualisiert wird?
Das Auge ist ja träge und wenn diese "Peaks" genau so schnell
verschwinden wie sie kommen, dann macht ein Wertesammeln das ganze ja
eigentlich schlimmer
holger schrieb:> Magic Numbers sind der Tod jedes Programmes.> Der Compiler kennt die Grösse deines Arrays.
Ach, wenns nur das wäre.
Aber was soll man mit
1
/*Mode of operation = "Fast PWM", TOP = "0xFF", Update of OCRx at "TOP", TOV Flag set on "MAX" */
2
case3:
3
SBITTIM(TCCR0B,3)=0;
4
SBITTIM(TCCR0A,1)=1;
5
SBITTIM(TCCR0A,0)=1;
6
break;
anfangen. Das kann stimmen (ich glaub sogar ungschaut, dass es stimmt),
nichts desto trotz muss es kontrolliert werden. Die Schreibweise ist
noch 'suboptimler' als eine binäre Zuweisung. Und dazu hab ich heute
ehrlich gesagt keine Lust mehr, mir da die Einzelteile alle
zusammenzutragen.
Jan schrieb:> Ich habe nun mal den Wert 23 hart auf average geschrieben und damit> bleibt der Duty-Cycle stabil. Kein Flackern mehr und auch die Messung> zeigt ein gleich bleibendes Tastverhältnis.
Hmm.
Das würde ich so deuten, dass tatsächlich vom ADC schwankende Werte
kommen. Was allerdings komisch ist, denn eigentlich sollte sich das
durch den Mittelwert ausgleichen.
> Kann es vielleicht sein, dass durch das Sammeln der Werte die Zeitspanne> zwischen den aktualisierungen des Duty-Cycles zu groß ist und man dann> einen springenden Wert leichter erkennt, als wenn der Duty-Cycle in> jedem Interrupt-Durchlauf aktualisiert wird?
Das sowieso.
Wenn du jeweils 16 Werte sammelst, dann dauert das 16 mal so lange, wie
wenn du noch jedem Wert die PWM updatest.
Karl Heinz Buchegger schrieb:> Das sowieso.>> Wenn du jeweils 16 Werte sammelst, dann dauert das 16 mal so lange, wie>> wenn du noch jedem Wert die PWM updatest.
Ich glaube das ist tatsächlich des Rätsels Lösung!
Ich habe nun die Samplerate des ADCs von 62kHz auf 125kHz erhöht und
siehe da, das Flackern wurde deutlich besser!
Nun noch die Mittelwertbildung über 8 Messwerte statt 16 und das
Flackern ist weg! Ich brech zusammen....
Jan schrieb:> Ich habe nun die Samplerate des ADCs von 62kHz auf 125kHz erhöht und> siehe da, das Flackern wurde deutlich besser!>> Nun noch die Mittelwertbildung über 8 Messwerte statt 16 und das> Flackern ist weg! Ich brech zusammen....
Da ist was anderes faul.
Der ADC darf so gut wie überhaupt nicht schwanken. Und der gemittelte
Wert über 16 Samples erst recht nicht.
Nun ja ich dachte, dass eventuell die kleine Schrittweite des ADC in
Verbindung mit einem hohen Rauschen dieses unruhiges Verhalten
hervorruft.
Das "Schwanken" des Dutycycles ist auch vorhanden, wenn man nur wenige
Werte zur Mittelwertbestimmung nimmt, nur ist es dann nicht als
Flackern, sondern als eine Art "gleitendes" heller- und dunkler werden
zu vernehmen.
Daher tippe ich auf das Eingangssignal an sich als Übeltäter
Ich habe noch nicht ganz verstanden, wozu du etwas Messen willst? Ein
Dimmer hat einen Zündwinkel, dieser geht von etwas über 0Grad bis knapp
unter 180Grad pro Halbwelle. Also du misst eigentlich nur die Frequenz
bzw. Synchronisierst dich mit dem Nulldurchgang und lässt dann je nach
gewünschtem Zündwinkel einen Zähler laufen, mit 100us Auflösung und
zündest dann nach Ablauf der Zeit. Vorsicht bei SSRs, die schalten oft
nur im Nulldurchgang => nicht dimmbar!
Michael schrieb:> Was du da machst, sieht sehr nach Sub-Sampling aus
Stunden später:
Jan schrieb:>> Wenn du jeweils 16 Werte sammelst, dann dauert das 16 mal so lange, wie>> wenn du noch jedem Wert die PWM updatest.> Ich glaube das ist tatsächlich des Rätsels Lösung!
Sag ich doch ...
Ok ich formuliere mein Problem noch einmal etwas ausführlicher:
Es sollen eine Reihe von Leuchtdioden per PWM gedimmt werden. Übernehmen
soll diese Aufgabe ein Atmel ATTiny13A mit einer Hardware-PWM.
Bis zu diesem Punkt funktioniert auch alles, PWM läuft und hat die
gewünschte Frequenz.
Nun geht es an die Einstellung des Duty-Cycles. Die einfachste
Möglichkeit wäre, ein 10kOhm Drehpoti an den Eingang des ADC zu setzen.
So hätte man einen großen Rausch-Nutzsignal Abstand.
Der Knackpunkt an der Sache ist aber, dass ich dieses 10kOhm Poti nicht
verwenden kann/will, sondern auf eine Art Schieberegler zurück greife.
Dieser hat einen veränderbaren Widerstand von 0,3 - 22,3 Ohm.
Zur Auswertung habe ich einen Spannungsteiler bestehend aus dem
Schieberegler und einem 560Ohm Widerstand aufgebaut. Und genau hier
komme ich nun in einen Zielkonflikt:
Auf der einen Seite sollte der zweite Widerstand nicht zu groß sein, um
die Änderung des Schiebereglers noch messen zu können und zum anderen
darf der zweite Widerstand aber auch nicht zu klein sein, da sonst ein
unnötig hoher Strom fließt.
Daher habe ich mich für die 560Ohm Variante entschieden und betreibe den
AD-Wandler mit der vollen 10Bit Auflösung. Den Spannungsteiler speiße
ich mit Vcc, was ebenfalls die Referenz für den ADC ist.
Je länger ich darüber nachdenke, desto wahrscheinlicher wird für mich,
dass mein Rauschen einfach so groß ist, dass der gewandelte Wert
permanent springt. Am Eingang des ADC's habe ich noch einen 10uF
Kondensator gegen Masse gelegt, aber das scheint auch nichts zu bringen
Jan schrieb:> Dieser hat einen veränderbaren Widerstand von 0,3 - 22,3 Ohm.>> Zur Auswertung habe ich einen Spannungsteiler bestehend aus dem> Schieberegler und einem 560Ohm Widerstand aufgebaut.>> und betreibe den AD-Wandler mit der vollen 10Bit Auflösung.
Mit dem Aufbau nutzt du die unteren 40 Stufen deines AD-Wandlers, d.h.
wenn der ordentlich läuft, muss der meistens fest aus einer Stufe
kleben. Bei wenigen Einstellungen des Potis darf er zwischen
benachbarten Werten hin- und herspringen. Häng mal einen Kondensator an
den ADC-Eingang.
Selbst bei nur 40 Stufen ergibt im oberen Bereich ein Sprung zwischen
benachbarten Werten nur relativ schwache Helligkeitsänderungen. Anders
sieht es natürlich aus, wenn das digitalisierte Signal zwischen 0 und 1
springt, da das Auge die Helligkeit näherungsweise logarithmisch
bewertet ;-)
Wenn man über Mittelung die Auflösung verbessern möchte, kann man dem
Signal vom Spannungsteiler ein Störsignal überlagern, so das statistisch
auch benachbarte Digitalwerte auftreten. Die Mittelung erledigt den
Rest. Das funktioniert aber nur vernünftig, wenn der Stufenabstand des
ADC deutlich besser als seine Auflösung ist.
Hi
>Daher habe ich mich für die 560Ohm Variante entschieden und betreibe den>AD-Wandler mit der vollen 10Bit Auflösung. Den Spannungsteiler speiße>ich mit Vcc, was ebenfalls die Referenz für den ADC ist.
Dann nimm doch einfach mal die 1,1V Referenz vom AD-Wandler. Dürfte mehr
bringen als deine jetzige pseudoratiometrische Messung.
MfG Spess
Ohne jetzt alles gelesen, oder der Code angeschaut zu haben:
ein Flackern der LEDs kann auch dadurch entstehen, das der
PWM-Vergleichswert mitten im Zyklus umgesetzt wird.
In einigen Modi wird der neue Wert sofort übernommen.
Das heißt:
Ist der neue Wert kleiner als der erste und ist der Timer schon an dem
neuen vorbeigelaufendem, dann läuft er erst einmal über und beachtet den
neuen Wert erst dann.
Vermeiden lässt sich das, indem ein Modus genommen wird, der den neuen
Wert zu einem definiertem Zeitpunkt übernimmt.
oder man selbst im CompareMatch-Isr den neuen wert setzt und nicht
sobald der ADC fertig ist.
PS:
die statischen lokalen variablen als volatile zu definieren ist
überflüssig.
Michael schrieb:> Bei wenigen Einstellungen des Potis darf er zwischen>> benachbarten Werten hin- und herspringen. Häng mal einen Kondensator an>> den ADC-Eingang.
Habe ich bereits gemacht, 10uF.
spess53 schrieb:> Dann nimm doch einfach mal die 1,1V Referenz vom AD-Wandler. Dürfte mehr>> bringen als deine jetzige pseudoratiometrische Messung.
Ja das sollte gehen. Dadurch wird die Auflösung feiner. Dass die Messung
dann nicht mehr ratiometrisch ist, spielt ja bei diesem Anwendungsfall
keine Rolle. Danke für den Hinweis
Vlad Tepesch schrieb:> Ohne jetzt alles gelesen, oder der Code angeschaut zu haben:>> ein Flackern der LEDs kann auch dadurch entstehen, das der>> PWM-Vergleichswert mitten im Zyklus umgesetzt wird.>> In einigen Modi wird der neue Wert sofort übernommen.
Auch ein sehr guter Einwand. Ich werde das mal überprüfen, nutze aber
bisher den Fast-PWM Mode und meine gelesen zu haben, dass hier der
Registerzugriff für den PWM-Wert double-buffered erfolgt; Also immer zu
einem definierten Zeitpunkt der neue Wert geladen wird (denke wenn der
Counter TOP, also 255, erreicht)
Vielen Dank für die Antworten!
Gruß
Hi
>Vermeiden lässt sich das, indem ein Modus genommen wird, der den neuen>Wert zu einem definiertem Zeitpunkt übernimmt.
Bei den PWM-Modi des ATTiny13 erfolgt das Update der OC-Register
generell beim Overflow des Timers.
MfG Spess
spess53 schrieb:> Dann nimm doch einfach mal die 1,1V Referenz vom AD-Wandler. Dürfte mehr> bringen als deine jetzige pseudoratiometrische Messung.
Was ist daran "pseudoratiometrische", wenn sowohl Spannungsteiler als
auch ADC-Referenz von der selben Spannung abgeleitet sind, solange die
anständig abgeblockt ist?
Der Auflösung würde eine kleinere Referenzspannung schon zu gute kommen.
Den gleichen Effekt hätte es, wenn man den Vorwiderstand verkleinert und
sowohl für Spannungteiler als für die Referenz die gleiche, aber
entsprechend niedrigere Spannung verwendet.
Die Probleme liegen im Moment aber wohl woanders.
Die 1,1V Refernz für den Spannungsteiler verwenden geht leider nicht, da
der Atmel diese Spannung nur intern hat und nicht nach außen führt.
Ich kann heute Abend mal Schaltplan und Layout posten, denn im Code kann
ich (trotz nochmaligen Durchgehens) keinen Fehler finden.
Ich denke schon, dass es am schwankenden ADC-Wert liegen kann, da ja in
der LUT teilweiße recht große Schritte gemacht werden, sobald sich der
gewandelte Wert um nur eine Stufe (also ca 5mV ändert). Kabelwiderstand
und Übergangswiderstände an den Steckern gehen ja auch mit ein
Jan schrieb:> Die 1,1V Refernz für den Spannungsteiler verwenden geht leider nicht, da> der Atmel diese Spannung nur intern hat und nicht nach außen führt.
Da hat der ATtiny13 leider etwas wenig Pins :-(
Bei den großen Brüdern wäre sie am ARef-Pin zugänglich.
Wenn man mal auf die ratiometrische Messung verzichtet, hätte man mit
der internen Referenz zumindest eine fast 5x so hohe Auflösung des ADC.
Ja ich denke, das wird in diesem Fall auch der sinnvollste Weg sein. Es
soll ja keine absolute, genaue Messung werden.
Die interne Refernz ist ja soweit ich weiß recht temperaturstabil,
lediglich der exakte Spannugnswert schwankt von Controller zu
Controller...aber das kann man ja durch Anpassen der LUT auskalibrieren.
Hi
>Die 1,1V Refernz für den Spannungsteiler verwenden geht leider nicht, da>der Atmel diese Spannung nur intern hat und nicht nach außen führt.
Sollst du doch gar nicht. Einfach als Referenz für den ADC.
MfG Spess
Also kurzes Feedback:
Ich habe nun die 1,1V Refernz als Bezugspotential für die Wandlung
ausgewähl und damit funktioniert das ganze so wie es soll!
Es lag scheinbar tatsächlich an der zu groben Auflösung, bedingt durch
Vcc als Referenz.
Nun kann ich 16 Messwerte sammeln und mitteln, ohne das irgendwas
flackert. Nun ist selbst bei einer extrem hohen Anzahl an Messwerten
kein Flackern mehr zu sehen :)
Vielen Dank an alle Beteiligten!
Jan schrieb:> Eine Messung mit dem Logik-Analysator hat ergeben, dass das Flackern von> unterschiedlichen Duty-Cyclen+s kommt...obwohl das Poti an ein und der> selben Stelle verbleibt
Vielleicht einfach nur Regelschwingungen? Sowas soll vorkommen.
Insbesondere wenn man de facto einen Regelkreis aufbaut, aber sich
keinerlei Gedanken über die Gesetzmäßigkeiten einer solchen Rückkopplung
macht...
Nur mal als Möglichkeit: Mittelwertkalkulationen dauern eine gewisse
Zeit, insbesondere, wenn man sie nicht sinnvollerweise als "gleitendes"
Mittel implementiert. Sowas nennt man dann eine Totzeit. Garnicht gut
für einen Regler, Regelschwingungen entstehen auf diese Art sogar mit
recht hoher Wahrscheinlichkeit, es sei denn, die Regelstrecke hat eine
hinreichend große eigene Zeitkonstante, um die Schwingung wieder
wegzudämpfen, was aber in der konkreten Anwendung eher nicht der Fall
sein dürfte.
Sprich: du hast dir da eine Initiativstrafe "Studium der Grundlagen der
Regeltechnik" aufgehalst.
Hi
>Vielleicht einfach nur Regelschwingungen? Sowas soll vorkommen.>Insbesondere wenn man de facto einen Regelkreis aufbaut, aber sich>keinerlei Gedanken über die Gesetzmäßigkeiten einer solchen Rückkopplung>macht...
ADC->LUT->OCR. Wo ist da ein Regelkreis?
MfG Spess
Hi
>du hast den Photosensor davor und die LED dahinter vergessen ;)
Ich ergänze:
Poti-> ADC->LUT->OCR->LED;
Es ist wahrscheinlich schon zu spät um einen Regelkreis zu erkennen.
MfG Spess
c-hater schrieb:> Sprich: du hast dir da eine Initiativstrafe "Studium der Grundlagen der>> Regeltechnik" aufgehalst
Es ist zwar mittlerweile scho einige Zeit her, dass ich tatsächlich
diese Vorlesung besucht habe, aber ich bin mir ziemlich sicher, dass ich
(auf Grund des fehlenden Rückkoppelpfades) keine Regelung, sondern eine
Steuerung gebaut habe ;-)
Würde ich die Helligkeit mit Hilfe eines Sensors auf einen konstanten
Wert regeln, oder temperaturstabilisieren wollen, würde ich den Einwand
verstehen...aber in diesem Fall sehe ich lediglich ein P-Glied (Umsetung
ADC-Wert -> DutyCycle) als Steller.