www.mikrocontroller.net

Forum: Mikrocontroller und Elektronik LED über Photowiderstand dimmen


Autor: Philipp (Gast)
Datum:

Hallo Leute.

Ich bin momentan dabei mir eine Schreibtischlampe aus LEDs zu bauen und
wollte dazu das Licht autoatmisch je nach Umgebungslicht dimmen.

Die PWM hat 10bit und der ADC auch.

Leider funktioniert der Code (?) irgendwie nicht und ich finde den
Fehler nicht. Die LED dimmt nur runter wenn ich ne Lampe draufhalte;
wenn ich se wieder wegnehme wird sie aber nicht mehr heller. Und mit
weniger Licht heller werden funktioniert gar nicht.

[c]

while(1) {

       ADC_INIT();
       ADC_Wert_lesen_und_uebergeben(); // x ist der gemessene Wert

// Dimmen:

       if (x<378 && OCR1B>=1023) {      // 378 entspricht rund 1000lx
       OCR1B++;
       }
       if (x>378 && OCR1B>=1) {
       OCR1B--;
       }
       ...
}

Wäre nett, wenn wir einer mal nen Tip geben könnte.

Danke,

Philipp
Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Das hier

       if (x<378 && OCR1B>=1023) {      // 378 entspricht rund 1000lx
       OCR1B++;
       }

ist nicht logisch.

OCR1B wird nur dann erhöht, wenn es schon GRÖSSER als 1023 ist?
Ich denke das sollte kleiner heissen

und unterstreicht eigentlich das, was ich meistens predige: Mit ein paar
Leerzeichen da und dort sieht man Fehler viel besser.

       if( x < 378 &&
           OCR1B >= 1023 ) {      // 378 entspricht rund 1000lx

Seit Kindesbeinen an hast du dein Gehirn darauf trainiert, dass zwischen
Wörtern eine optische Lücke besteht. Dein Gehirn nimmt OCR1B >= 1023 als
3 getrennte Wörter war, die es einzeln absucht, während es OCR1B>=1023
zunächst erst mal nur als 1 Wort ansieht. Erst wenn du dich darauf
konzentrierst, beginnt es dieses Wort in seine Bestandteile zu zerlegen.
In diesem Sinne musst du bei der 'kürzeren' Lösung aktiv darüber
nachdenken, aus welchen Teilen sie zusammengesetzt ist und welches die
Bedeutung ist, während du bei der 'längeren' Lösung einfach nur so lesen
musst, wie du es seit vielen Jahren gewohnt bist und dein Gehirn ordnet
die Bestandteile ganz automatisch richtig ein.

Ob das jetzt so aussieht
       if( x < 378 &&
           OCR1B >= 1023 ) {      // 378 entspricht rund 1000lx
oder so
       if( (x < 378) && (OCR1B >= 1023) ) {      // 378 entspricht rund 1000lx
oder so
       if(     x <   378 &&
           OCR1B >= 1023 ) {      // 378 entspricht rund 1000lx
oder so
       if(   x < 378
          && OCR1B >= 1023 ) {      // 378 entspricht rund 1000lx
oder ...
muss jeder für sich selbst entscheiden. Aber nutze das, was du deinem
Hirn seit jungen Jahren als Automatismus eingetrichtert hast.
Autor: Philipp (Gast)
Datum:

Super! Werd ich dann ab jetzt so machen. Genau daran lag es.

Komisch ist aber, dass ich keine "Dimmung" sehe. Entweder is die LED aus
oder an. Sie schaltet zwar weich (fadet), aber nen Wert zwischen An und
Aus stellt sich nicht ein; auch wenn ich noch so vorsichtig extrem dünne
Materialien als Schatten nehme. Hab ich da irgendwo einen Denkfehler?
Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Philipp schrieb:
> Super! Werd ich dann ab jetzt so machen. Genau daran lag es.
>
> Komisch ist aber, dass ich keine "Dimmung" sehe. Entweder is die LED aus
> oder an. Sie schaltet zwar weich (fadet), aber nen Wert zwischen An und
> Aus stellt sich nicht ein; auch wenn ich noch so vorsichtig extrem dünne
> Materialien als Schatten nehme. Hab ich da irgendwo einen Denkfehler?

Das Problem wird darin zu suchen sein, dass das faden viel zu schnell
geht.
Autor: Christian T. (shuzz)
Datum:

Philipp schrieb:
> Komisch ist aber, dass ich keine "Dimmung" sehe. Entweder is die LED aus
> oder an. Sie schaltet zwar weich (fadet), aber nen Wert zwischen An und
> Aus stellt sich nicht ein; auch wenn ich noch so vorsichtig extrem dünne
> Materialien als Schatten nehme. Hab ich da irgendwo einen Denkfehler?

Ja, hast Du.

Du fragst in Deinem Programm den ADC ab.
Wenn der Wert größer 378 ist fadest Du die LED auf null runter.
Ist der Wert kleiner fadest Du auf's Maximum hoch.
Damit hat das Programm im Prinzip nur zwei stabile Zustände:

LED an  bei X < 378
LED aus bei X > 378

Was Du aber eigentlich willst ist eine Art Lookup-Tabelle die jedem
ADC-Wert einen bestimmten PWM-Wert zuordnet.
Dabei wird dann auch die Kennlinie des menschlichen Auges eine Rolle
spielen. (LED-Fading)
Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Christian T. schrieb:
> Philipp schrieb:
>> Komisch ist aber, dass ich keine "Dimmung" sehe. Entweder is die LED aus
>> oder an. Sie schaltet zwar weich (fadet), aber nen Wert zwischen An und
>> Aus stellt sich nicht ein; auch wenn ich noch so vorsichtig extrem dünne
>> Materialien als Schatten nehme. Hab ich da irgendwo einen Denkfehler?
>
> Ja, hast Du.
>
> Du fragst in Deinem Programm den ADC ab.
> Wenn der Wert größer 378 ist fadest Du die LED auf null runter.
> Ist der Wert kleiner fadest Du auf's Maximum hoch.
> Damit hat das Programm im Prinzip nur zwei stabile Zustände:
>
> LED an  bei X < 378
> LED aus bei X > 378
>

Kopf klatsch.
Ja klar du hast recht, da hab ich die Frage misverstanden.


> Was Du aber eigentlich willst ist eine Art Lookup-Tabelle die jedem
> ADC-Wert einen bestimmten PWM-Wert zuordnet.
> Dabei wird dann auch die Kennlinie des menschlichen Auges eine Rolle
> spielen. (LED-Fading)

Da hast du recht.
Aber erst mal soll er einen 'nauchlaufenden' Wert realisieren

  ADC_INIT();    // initialisiert wird nur EINMAL

  PWMZiel = 0;

  while(1) {

     ADC_Wert_lesen_und_uebergeben(); // x ist der gemessene Wert

     PWMZiel = 1024 - x;

     if( OCR1B > PWMZiel )
       OCR1B--;

     else if( OCR1B < PWMZiel )
       OCR1B++;

     ...
  }
}

PWMZiel gibt den Wert vor auf den die PWM eingestellt werden soll. Der
OCR Wert wird aber immer nur in kleinen Schritten (+/- 1) diesem Ziel
nachgeführt, sollte er abweichen. Auf die Art 'fadet' sich der
eigentlich die Helligkeit bestimmende OCR Wert an das PWMZiel heran.

Für die Berechnung des Zielwertes aus der ADC kann man dann natürlich
noch jede Menge Aufwand treiben. Ich hab jetzt einfach mal 1024-x
genommen: Je höher der ADC Wert, desto geringer der PWM Wert.
Autor: Philipp (Gast)
Datum:

Philipp schrieb:
> if (x<378 && OCR1B>=1023) {      // 378 entspricht rund 1000lx
>
>        OCR1B++;
>
>        }
>
>        if (x>378 && OCR1B>=1) {
>
>        OCR1B--;
>
>        }
>
>        ...

Also ich verstehe meinen Code wiefolgt:
In einer Endlosschleife geht es wie folgt. Meine Referenz ist 378 @
1000lx.
Umgebungshelligkeit messen.

Die Erste If Anweisung guckt. Ist deine gemessene Umgebungshelligkeit
kleiner als "378" und ist Die Helligkeit der LED kleiner als 1024, dann
mache die LED um 1(!) heller.

Die Zweite If Anweisung fragt, ob der gemessene Wert nicht vielleicht
größer als "378" ist und gleichzeigi die LED heller als 0 ist, dann
mache die LED um 1(!) dunkler.

Dann das ganze wieder von vorne.

Was ist an dem Code anders als an deinem?

Meine Idee ist ja nicht, dass die LED "fadet" sondern, dass sie IMMER
die 1000lx versucht (innerhalb der Grenzen) zu realisieren... Dafür
brauche ich doch kein Lookuptable?! Ich habe bei 1000lx 1,663V gemessen
was rund 378 bei 10 bit entspricht.
Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Philipp schrieb:
> Philipp schrieb:
>> if (x<378 && OCR1B>=1023) {      // 378 entspricht rund 1000lx
>>
>>        OCR1B++;
>>
>>        }
>>
>>        if (x>378 && OCR1B>=1) {
>>
>>        OCR1B--;
>>
>>        }
>>
>>        ...
>

> Was ist an dem Code anders als an deinem?


Das hier

> Die Erste If Anweisung guckt. Ist deine gemessene Umgebungshelligkeit
> kleiner als "378" und ist Die Helligkeit der LED kleiner als 1024, dann
> mache die LED um 1(!) heller.

steht zwar in deiner Beschriebung aber nicht in deinem Code :-)

> Was ist an dem Code anders als an deinem?
Auf welchen Code beziehst du dich?
Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Philipp schrieb:

> Meine Idee ist ja nicht, dass die LED "fadet" sondern, dass sie IMMER
> die 1000lx versucht (innerhalb der Grenzen) zu realisieren... Dafür
> brauche ich doch kein Lookuptable?! Ich habe bei 1000lx 1,663V gemessen
> was rund 378 bei 10 bit entspricht.

Das hättest du aber auch im Eröffnungsposting schon erzählen können:

Du willst einen Code schreiben, bei dem eine PWM eine LED soweit
nachführt, dass am ADC immer ein Wert von 378 raus kommt. De Facto baust
du damit eine Reglschleife. Das kann ja keiner wissen, wenn du es nicht
erzählst.

Hast du schon probiert, was dein ADC Wert macht, wenn es beim
Lichtsensor dunkler wird? Wird der größer oder kleiner?
Autor: Philipp (Gast)
Datum:

Karl heinz Buchegger schrieb:
> Du willst einen Code schreiben, bei dem eine PWM eine LED soweit
>
> nachführt, dass am ADC immer ein Wert von 378 raus kommt. De Facto baust
>
> du damit eine Reglschleife. Das kann ja keiner wissen, wenn du es nicht
>
> erzählst.

genau! Hab ich doch auch dachte ich?! Um 1 wird doch mit "++"
Inkrementiert und bei Dekrementierung mit "--" entsprechend.

> Hast du schon probiert, was dein ADC Wert macht, wenn es beim
>
> Lichtsensor dunkler wird?

Dann wird die LED heller. So wie es sein soll. Nur ebn viel zu schnell.
Und ich steh grad aufm schlauch, ob vielleicht die Emfpindlichkeit zu
hoch ist oder die nichtlineare Kennline meiner ,zugegebenermaßen schon
etwas entzündeten Augen, eine Rolle spielt.

> steht zwar in deiner Beschriebung aber nicht in deinem Code :-)

Ich hoffe damit meinst du den Vorzeichenfehler!
Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Philipp schrieb:

> Dann wird die LED heller. So wie es sein soll. Nur ebn viel zu schnell.

Dann musst du dir etwas überlegen, wie du den 'OCR' Wert nicht um +/- 1
in jedem Schleifendurchlauf nachziehst, sondern um zb 0.5 :-)

(wenn du zb den OCR Wert nicht direkt um 1 erhöhst/erniedrigst sondern
stattdessen eine Hilfsvariable und von der immer nur die Hälfte ins OCR
Register schreibst, dann inkrementierst du OCR de fact immer nur um 1/2
pro Schleifendurchlauf)

> steht zwar in deiner Beschriebung aber nicht in deinem Code :-)
>
> Ich hoffe damit meinst du den Vorzeichenfehler!

Nein. Ich meine größer versus kleiner :-)
Autor: Andreas Ferber (aferber)
Datum:

Philipp schrieb:
> Dann wird die LED heller. So wie es sein soll. Nur ebn viel zu schnell.
> Und ich steh grad aufm schlauch, ob vielleicht die Emfpindlichkeit zu
> hoch ist oder die nichtlineare Kennline meiner ,zugegebenermaßen schon
> etwas entzündeten Augen, eine Rolle spielt.

Ich vermute mal, dass dir da die PWM einen Strich durch die Rechnung
macht.

Solange der Duty Cycle noch niedrig ist, werden deine ADC-Messungen
meistens zu einem Zeitpunkt stattfinden, an dem die LEDs gerade aus
sind, damit misst du dann nur die Umgebungshelligkeit, und dein PWM-Wert
geht immer weiter hoch. Erst wenn die PWM bei ca. 50% liegt gleicht sich
das aus, dann ist die wahrgenommene Helligkeit aufgrund der
Nichtlinearität der Wahrnehmung aber schon nicht mehr weit vom
Maximalwert entfernt, die LEDs wirken also schon ziemlich hell.

Vielleicht hilft ein Tiefpass vor dem ADC-Eingang, oder du musst eine
ausreichende Zahl von ADC-Messwerten mitteln (gleitendes Mittel bilden).

Andreas
Autor: Andreas Ferber (aferber)
Datum:

Ergänzend noch: wenn die PWM über 50% liegt kehrt sich das ganze um, die
meisten Messungen finden bei eingeschalteten LEDs statt, und dein
PWM-Wert wird überwiegend runtergezählt, auch hier wieder bis ca. 50%
erreicht sind.

Damit hast du im Ergebnis nur entweder 0% (Umgebungshelligkeit über dem
Schwellwert) oder 50% (Umgebung unter dem Schwellwert).

Andreas
Autor: Christian T. (shuzz)
Datum:

Philipp schrieb:
>> Hast du schon probiert, was dein ADC Wert macht, wenn es beim
>>
>> Lichtsensor dunkler wird?
>
> Dann wird die LED heller. So wie es sein soll. Nur ebn viel zu schnell.
> Und ich steh grad aufm schlauch, ob vielleicht die Emfpindlichkeit zu
> hoch ist oder die nichtlineare Kennline meiner ,zugegebenermaßen schon
> etwas entzündeten Augen, eine Rolle spielt.

Ich interpretiere mal den Satz "Nur eben viel zu schnell."
Ich gehe davon aus, dass Du meinst "Die LED ist dunkel wenn's hell ist.
Dann setzt die Dämmerung ein und es passiert erstmal net viel. Dann geht
die LED innerhalb kurzer Zeit (=geringer Helligkeitsunterschied im
Aussenlicht) auf Hell und dann passiert wieder nix bis es komplett
dunkel draussen ist."

Falls Du das so meintest liegt das Problem vermutlich in der Kennlinie
Deines Auges. Schau nochmal in LED-Fading rein.


Grüße,

Christian
Autor: Andreas Ferber (aferber)
Datum:

Christian T. schrieb:
> Falls Du das so meintest liegt das Problem vermutlich in der Kennlinie
> Deines Auges. Schau nochmal in LED-Fading rein.

Genau diese Problem kommt in diesem Fall nicht in Frage. Er versucht die
Beleuchtungsstärke an seinem LDR zu regeln, und nicht mit einem
bestimmten PWM-Wert eine bestimmte Helligkeit einzustellen.

Wenn diese Regelung so funktionieren würde wie sie soll, würde jede
Änderung in der Aussenbeleuchtung jeweils eine vom Betrag her gleiche
Änderung bei der LED-Beleuchtung hervorrufen, nur mit entgegengesetztem
Vorzeichen. Irgendwelche Augenkennlinien spielen da keine Rolle, da
Aussen- und LED-Licht genau gegenläufig und vom Betrag her gleich wären.

Von der Grundidee her ist die Regelung also garnicht so verkehrt, nur
die PWM bereitet eben wie von mir beschrieben noch Probleme.

Andreas
Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Andreas Ferber schrieb:

> Von der Grundidee her ist die Regelung also garnicht so verkehrt, nur
> die PWM bereitet eben wie von mir beschrieben noch Probleme.

Und ich denke du hast auch recht damit.
Aber das einzige was mir da zur Lösung einfällt wäre:
* Einen trägen Sensor nehmen
  Ob wohl ein LDR eine kHz PWM noch als PWM wahrnimmt?
* Tiefpass am ADC Eingang
* Den PWM Ausgang mit einem Siebglied in eine echte
  Gleich-Spannung umwandeln
Autor: Andreas Ferber (aferber)
Datum:

Karl heinz Buchegger schrieb:
> Aber das einzige was mir da zur Lösung einfällt wäre:

Als allererstes würde ich es erstmal mit einem gleitenden Mittel über
den ADC-Messwerten als Tiefpass versuchen, ganz einfach weil man dafür
nichts an der Hardware ändern muss.

Dabei könnte es dann eventuell noch Probleme mit Überlagerungen zwischen
der PWM- und der ADC-Frequenz geben, also ggf. darauf achten, dass die
nicht in einem einfachen Verhältnis zueinander stehen, und auch nicht zu
dicht beeinander liegen (wegen möglicher Schwebung).

> * Einen trägen Sensor nehmen
>   Ob wohl ein LDR eine kHz PWM noch als PWM wahrnimmt?

Ein LDR ist zwar träge, deutlich im ms-Bereich liegt das aber meines
Wissens nur bis von 0 aus der Vollausschlag oder umgekehrt erreicht wird
(oder zumindest nahe dran). Um das Problem im vorliegenden Fall
auszulösen reicht es aber wenn der LDR es von knapp über dem Schwellwert
auf knapp unter dem Schwellwert (und umgekehrt) schneller als die PWM
schafft, und das dürfte auch im (unteren) kHz-Bereich noch der Fall
sein.

> * Tiefpass am ADC Eingang
> * Den PWM Ausgang mit einem Siebglied in eine echte
>   Gleich-Spannung umwandeln

Irgendwo muss halt ein Tiefpass hin, ich würde es wie gesagt erstmal
mittels Firmware versuchen.

Andreas
Autor: Andreas Ferber (aferber)
Datum:

Andreas Ferber schrieb:
> Dabei könnte es dann eventuell noch Probleme mit Überlagerungen zwischen
> der PWM- und der ADC-Frequenz geben, also ggf. darauf achten, dass die
> nicht in einem einfachen Verhältnis zueinander stehen,

Ich habe nochmal ein bisschen drüber nachgedacht, vielleicht wäre es
doch garnicht so schlecht, eine feste Kopplung zwischen PWM und
ADC-Abtastung zu haben, z.B. PWM 100Hz und ADC-Samplerate 10kHz. Im
Beispiel müsste man dann immer über 100 Messwerte mitteln. Die Messungen
würden dann immer an festen Punkten innerhalb des PWM-Intervalls
stattfinden, damit sollte sich eigentlich ganz gut ein Mittelwert
berechnen lassen.

Andreas
Autor: Philipp (Gast)
Datum:

Also ich möchte mich nochmal zu Wort melden und sagen. ES GEHT! :-) Das
mit dem zu schnell lag an der nicht Rückführbarkeit wegen der zu großen
Helligkeit. Wie bei nem OPV. Man kann mit +-10V nicht 30V ausregeln. jap
jap

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel




Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder GIF-Format hochladen.
Siehe Bildformate
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net