Hallo!
Ich versuche einen 4-Kanal PWM Dimmer für 12V Halogenlampen zu bauen,
der einen automatischen Lichtablauf steuern soll.
Es soll periodisch "sanft" zwischen 2 verschiedenen Lampen umgeschaltet
werden (eine faded-out, die nächste faded-ein) mit einer kleinen Pause
dazwischen.
Folgende Parameter möchte ich dabei mit Potis einstellen: Maximale
Helligkeit, Geschwindigkeit des Faden/Dimmen, Pause dazwischen.
Beschreibung des Problems:
-> Während des Dimmens blitzt die jeweilige Led kurz hell auf - das
passiert in unregelmäßigen Zeitabständen
-> Im Anhang befindet sich ein Video davon, damit alle wissen, wovon ich
spreche.
Beschreibung der Hardware (Auswahl der Bauteile aufgrund von dem was ich
gerade zu Hause hatte):
-> AtMega8 (4,7µF direkt an den Versorgungspins)
-> 4x BUZ11 MosFETs
-> 2x TC4424 als Treiber für die MosFETs
-> 3x Trimpoti (10k)
-> 7805 zur Versorgung des Atmegas (100µF zur Stabilisierung auf
Eingangsseite, 47µF auf Ausgangsseite)
-> Aufgebaut ist das ganze auf Lochrasterplatine mit 0,5mm² Kupferdraht
auf der Rückseite
-> Zum Testen verwende ich als Leuchtmittel rote LEDs mit passendem
Vorwiderstand, da mir die Halogenlampen auf dauer zu hell sind beim
programmieren.
Beschreibung der Software:
-> Programmiert in C mit AtmelStudio
-> Die 3 Potis werden periodisch nacheinander eingelesen (conversion für
den nächsten kanal wird im ADC-Interrupt gestartet)
-> Gedimmt wird mittels Zählvariable die im Timer-Overflow-Interrupt
erhöht wird
-> Gedimmt wird durch Vergleich der Vorgabewerte für die Helligkeit mit
der Zählvariable und entsprechendem Schalten der Ausgänge in der ISR.
-> Maximalhelligkeit wird über den Maximalwert der Zählvariable
bestimmt.
Um das Problem zu beheben habe ich bisher folgendes erfolgslos
ausprobiert, bzw ist noch folgendes zu sagen:
-> ADC deaktivieren und die Werte fix vorgeben (Vermutung war, dass der
ADC Interrupt irgendwie den Timer-Interrupt verhindert und so ab und zu
das Schalten eines Ausganges verhindert wird)
-> Verschiedene Spannungsquellen (Stabilisiertes Netzgerät, Eigenbau
Netzgerät, Labornetzgerät), aber immer das selbe Problem
-> Der Atmega resettet nicht, das merke ich daran, da ich beim
Einschalten eine spezielle Blinksequenz habe um das zu erkennen.
-> Es liegt nicht daran, dass der MosFET bzw dessen Treiber manchmal
einfach nicht schaltet. Das habe ich überprüft indem ich eine Led am
Ausgangspin des Atmegas gehängt habe - diese blitzt auch manchmal auf.
Ich hoffe, dass ihr mir Hinweise geben könnt, wo ich das Problem noch
suchen kann!!!
Danke und liebe Grüße aus Österreich!
P.S.: Weiters finden sich am Board folgende Bauteile:
-> ein 75176er, weil ich den Dimmer später auch per DMX ansteuern will
-> zwei Jumper: zum Laufrichtung umschalten und zum einschalten vom
DMX-Mode
-> eine LED die den Zustand des ersten Kanals anzeigt.
P.P.S.: letztens sind mir meine TC4424 plötzlich kaputt gegangen. Nach
dem Austausch funktioniert wieder alles. Kann mir vielleicht auch wer
verraten, ob ich im Leistungsteil noch zusätzliche Bauteile benötige
(Leider bin ich bei Leistungselektronik nicht so gut drauf)?
Hallo!
Ich habe nun eine Lösung gefunden, aber das Problem noch nicht wikrlich
identifiziert!?
Meine Lösung ist, dass ich im Timer-Overflow-Interrupt die
Zählervariable nicht auf Gleichheit mit dem gewünschten Helligkeitswert
prüfe, sondern auf "Größer Gleich"...
Also nicht:
1
if(timer_counter==output_pwm_analog_value_1){
2
output_pwm_set_digital_1(0);
3
}
sondern
1
if(timer_counter>=output_pwm_analog_value_1){
2
output_pwm_set_digital_1(0);
3
}
.
Leider wird dadurch die Durchschnittliche Laufzeit von der ISR stark
erhöht, was zu einer stark verringerten Maximalgeschwindigkeit des
Dimm-Vorganges führt. Aber auch dafür konnte ich eine Lösung finden:
Nämlich, dass ich zuerst prüfe, ob der Ausgang überhaupt noch ON ist...
Das sieht dann so aus:
Das führt zwar jetzt zu einem annehmbaren Fade, aber mir ist noch nicht
klar, warum das überhaupt notwendig ist!?
Kann mir noch irgendwer erklären, warum anscheinend die Gleichheit der
beiden Variablen nicht in jedem Durchlauf eintritt, und es daher zu
einem Flackern kommt?
Danke!
P.S.: Wenn ich für dieses Projekt schon einen Thread eröffnet habe, wärs
auch ganz nett, wenn mir wer sagen könnte, ob ich am Leistungsteil
(TC4424 und BUZ11) noch irgendwelche weiteren Bauteile benötige???
Markus schrieb:> Warum ist das hochzählen in einem Else...
Weil sonst der "erste" Durchlauf mit dem Wert 1 anstatt 0 geschieht.
1. Alternative: im if-Zweig den Zählerwert auf -1 setzen.
2. Alternative: das if mit ">" (anstatt ">=") am Beginn der ISR.
Hmmm - wenn ich drüber nachdenke, gefällt mir die 2. Alternative
eigentlich am Besten - damit spare ich gegenüber meiner jetztigen
Variante auch einen Sprungbefehl im übersetzten Code... Oder?
Danke für den Hinweis, ich werde die Änderung umsetzen - aber das hat
leider nichts mit meinen Fragen zu tun...
mfg
Bastler143 schrieb:> -> AtMega8 (4,7µF direkt an den Versorgungspins)
Wenn das ein 0815-C ist, wird der kaum dafür geeignet sein.
100nF o.ä. wären eher geeignet, um kurzzeitige Lastspitzen aufzufangen.
> -> 7805 zur Versorgung des Atmegas (100µF zur Stabilisierung auf> Eingangsseite, 47µF auf Ausgangsseite)
Der 7805 ist ein Regler und als solcher i.A. nicht besonders glücklich
über große kapazitive Lasten. Was sagt das Datenblatt des Herstellers?
Dein 12V-Gnd sind mit µC-Gnd verbunden?
Dein Code geht so nicht mal durch den Compiler. Wie soll man da etwas
testen, ohne groß mit Basteln anzufangen.
Bastler143 schrieb:> Ich habe nun eine Lösung gefunden, aber das Problem noch nicht wikrlich> identifiziert!?
Das Problem ist einfach, daß die Analogwerte nicht konstant sind,
sondern immer geringfügig "wackeln", insbesondere ein Wackeln im letzten
Digit ist praktisch unvermeidbar. Dadurch kann es zu folgendem
(beispielhaften) Ablauf kommen:
ADC-ISR:
Analogwert=50
Timer-ISR:
Zähler+=1 (neuer Zählerstand=47)
Prüfung auf Abschaltbedingung negativ->LED bleibt an
Timer-ISR:
Zähler+=1 (neuer Zählerstand=48)
Prüfung auf Abschaltbedingung negativ->LED bleibt an
Timer-ISR:
Zähler+=1 (neuer Zählerstand=49)
Prüfung auf Abschaltbedingung negativ->LED bleibt an
ADC-ISR:
Analogwert=49 (wackeln im letzten Digit)
Timer-ISR:
Zähler+=1 (neuer Zählerstand=50)
Prüfung auf Abschaltbedingung negativ->LED bleibt an
Und nun bleibt die LED bis zum Ende des Zyklus an, weil nie mehr die
Abschaltbedingung eintritt. ->Lampe blitzt hell auf.
> Leider wird dadurch die Durchschnittliche Laufzeit von der ISR stark> erhöht
Deklariere mal die output_pwm_set_digital_x-Routinen als
Inline-Funktionen, dann sollte sich dieses Problem deutlich entschärfen.
...
Die schönere Lösung wäre allerdings, die Ursache zu bekämpfen. Und das
erreicht man dadurch, daß man dafür sorgt, daß sich während eines
PWM-Zyklus die zum Vergleich benutzten ADC-Werte nicht mehr ändern
können. Dazu benutzt man das gute alte double buffering.
Man erzeugt also einen zweiten Satz Variablen. Die ADC-ISR schreibt
ausschließlich in den ersten Variablensatz. Die Timer-ISR holt die
Vergleichswerte für die PWM hingegen ausschließlich aus dem zweiten
Variablensatz. Alles, was nun noch fehlt, ist ein Umkopieren der Werte
aus dem ersten in den zweiten Variablensatz im richtigen Moment, nämlich
beim Start des PWM-Zyklus, also genau dort, wo du alle Ausgänge
einschaltest.
->Problem an der Wurzel gelöst.
Hallo!
Michael schrieb:> Wenn das ein 0815-C ist, wird der kaum dafür geeignet sein.
OK - Werde ich ändern - mach ich immer so und hatte noch nie Probleme!
Michael schrieb:>Der 7805 ist ein Regler und als solcher i.A. nicht besonders glücklich>über große kapazitive Lasten. Was sagt das Datenblatt des Herstellers?
Datenblatt sagt, dass man beim Eingang und beim Ausgang einen C
hinhängen soll - jedoch werden dort kleinere Werte vorgeschlagen...
Werde bei der nächsten Platine Bauteilwerte im Bereich der Vorschläge im
Datenblatt wählen.
Michael schrieb:> Dein 12V-Gnd sind mit µC-Gnd verbunden?
Ja.
c-hater schrieb:
>Das Problem ist einfach, daß die Analogwerte nicht konstant sind,>sondern immer geringfügig "wackeln", insbesondere ein Wackeln im letzten>Digit ist praktisch unvermeidbar.
Danke für den Hinweis und deine Ausführliche Erklärung, aber wenn du dir
den Code etwas genauer ansiehst, merkst du eventuell (code is ja nicht
vollständig), dass ich 2 der 3 eingelesenen Analogwerte nicht als
PWM-Tastwerte (Helligkeitswerte) benutze, sondern als delay um die
Ablaufgeschwindigkeit zu steuern. Der dritte Analogwert dienst zwar als
max. Zählerwert, bei dem der Zähler wieder zurückgesetzt wird, dort ist
aber genau das, was du als "double buffering" Bezeichnest, umgesetzt.
Also ich lese den ADC-Wert nur am Beginn eines PWM-Zyklus (beim
Zählerstand=0) in eine zweite Variable ein, die ich als Vergleichswert
in der timer ISR benutze. Also ist meines Verständnisses nach das
Flackern nicht aufgrund vom Rauschen des ADC.
Mein Problem ist also noch immer nicht gefunden....
Es darf weiter spekuliert werden!
Danke an alle die sich die Mühe gemacht haben und meine Uploads zum
Thread betrachtet haben!
mfg
Das sieht mir nach dem typischen Fade-out Flackern bei einer einfachen
PWM aus.
Problem (8-Bit PWM, Match bei 10):
1. Zyklus beginnt -> LED ein
2. Zähler erreicht 10 -> LED aus
3. Zähler läuft über -> neuer Zyklus beginnt
So, wenn jetzt aber der Zähler z.B. 8 erreicht hat und nun
der Match Wert per SW auf z.B. 5 verringert wird, leuchtet die
LED während des gesamten Zyklus da mit "==" kein Match auftritt. Mit dem
">=" umgehst du das Problem.
Einige HW PWM lösen das indem sie einen neuen Match Wert erst zu Beginn
eines neuen Zyklus übernehmen. Während des aktuellen Zyklus wird der
alte Wert verwendet.
Bastler143 schrieb:> Danke für den Hinweis und deine Ausführliche Erklärung, aber wenn du dir> den Code etwas genauer ansiehst, merkst du eventuell (code is ja nicht> vollständig)
Woran man mal wieder sehen kann, wie wichtig es ist, daß der
vollständige Code gepostet wird.
> Mein Problem ist also noch immer nicht gefunden....> Es darf weiter spekuliert werden!
Hättest du den vollständigen Code gepostet, bräuchte man nicht zu
spekulieren.
Hallo!
Stefan schrieb:> Das sieht mir nach dem typischen Fade-out Flackern bei einer einfachen> PWM aus.
Danke - es scheint als wäre damit die Ursache geklärt.
Als Lösung werde ich das Dubble Buffering anwenden, wie es c-hater
beschrieben hat.
mfg
P.S.: Es war alles, was man zur Auffindung des Problems benötigte im
Codeauszug vorhanden.
P.P.S.: Leistungselektronik: passt das so? Oder brauche ich noch Diode,
Widerstand oder C irgendwo dazu um meinen Treiber vor einem erneutem
Tode zu schützen?