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
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
1 | if( x < 378 && |
2 | OCR1B >= 1023 ) { // 378 entspricht rund 1000lx |
oder so
1 | if( (x < 378) && (OCR1B >= 1023) ) { // 378 entspricht rund 1000lx |
oder so
1 | if( x < 378 && |
2 | OCR1B >= 1023 ) { // 378 entspricht rund 1000lx |
oder so
1 | if( x < 378 |
2 | && 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.
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?
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.
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)
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
1 | ADC_INIT(); // initialisiert wird nur EINMAL |
2 | |
3 | PWMZiel = 0; |
4 | |
5 | while(1) { |
6 | |
7 | ADC_Wert_lesen_und_uebergeben(); // x ist der gemessene Wert |
8 | |
9 | PWMZiel = 1024 - x; |
10 | |
11 | if( OCR1B > PWMZiel ) |
12 | OCR1B--; |
13 | |
14 | else if( OCR1B < PWMZiel ) |
15 | OCR1B++; |
16 | |
17 | ...
|
18 | }
|
19 | }
|
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.
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.
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?
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?
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!
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 :-)
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
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
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
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
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
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
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
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
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.