Forum: Mikrocontroller und Digitale Elektronik Led als Lichtsensor - Zeitmessung fehlerhaft?


von Julian V. (torten_juli)


Angehängte Dateien:

Lesenswert?

Ich experementiere gerade mit Leds als Lichtsensoren. Ich habe mich an 
dem Artikel aus dem Wiki gehalten.
Mein Aufbau:
-Arduino Nano auf dem Steckbrett mit USB und Atmega328P
-Led mit Vorwiderstand hängt zwischen PB0 und PB1, wobei die Anode an 
PB0 hängt
-CPU-Takt 16MHZ

Nun habe ich ein kleines Testprogramm geschrieben, um mal zu schauen wie 
die Leds, dich ich hier so rumliegen habe, als Lichtsensor 
funktionieren. Habe rote, blaue, gelbe und grüne probiert, bekomme aber 
immer den selben Wert bei meiner Zeitmessung. Egal ob dunkel oder hell. 
Selbst wenn ich die Led vom Steckbrett entferne, kommt der selbe 
Messerwert raus. Ich lasse mir diesen per UART an den PC senden. Sind 
immer 0.1ms.

Das Programm läuft interruptgestuert ab. Zuerst soll die Led in 
Sperrichtung 10ms geladen werden. Danach stell ich den PIN PB1 auf 
Eingang um, damit der Strom abfließen kann und messe die Zeit. Hier 
komme ich immer auf 0.1ms.
das kommt mir doch arg wenig vor.

Vielleicht habe ich einen Fehler im Code oder sonst einen Denkfehler.

Ich würde mich freuen, wenn mir jemand auf die Sprünge helfen könnte.

Juli

von Karl H. (kbuchegg)


Lesenswert?

Du solltest hier
1
...
2
    if (flag_led_load_fin)
3
    {
4
      flag_led_load_fin = 0;
5
      
6
      milisekunde = 0;
7
      zehntelmilisekunde = 0;
8
      
9
      //Portpin PB1 auf Eingang stellen
10
      DDRB &= ~(1<<PINB1);
11
      PORTB &= ~(1<<PINB1);
12
      
13
      measure = 1;
14
      TCCR0B |= (1<<CS00) | (1<<CS01); // Timer starten
15
    }
16
....

ehe du den Timer erneut startest, den Timer auf 0 zurück setzen und 
eventuell in der Zwischenzeit aufgelaufene Overflow Compare Interrupts 
löschen.
1
....
2
      measure = 1;
3
      TCNT0 = 0;                // Timer auf 0
4
      GTCCR |= (1<<PSRSYNC);    // Prescaler resetten
5
      TIFR0 = (1<<OCF0A);       // aufgelaufene Compares löschen
6
      TCCR0B |= (1<<CS00) | (1<<CS01); // Timer starten
7
....


Allerdings: einen Wert von minimum 0.1 wirst du immer haben. Denn so wie 
du misst, musst du mindestens einmal in die Compare-Interrupt Routine 
rein. Selbst wenn da die Messung gleich als beendet erklärt wird, weil 
der Pin schon abgefallen ist. Teil der ISR ist aber das Hochzählen 
deiner Zehntelmillisekunden. Bei einem Startwert von 0 ergibt das dann 
natürlich 1.

von Erich (Gast)


Lesenswert?

>Leds als Lichtsensoren

Ja, gute LEDs können als Sensor arbeiten.
Es entsteht eine Spannung bei Beleuchtung, an hochohmigem Widerstand.
Man kann das auf einen A/D Eingang geben.

Aber man braucht nichts "aufladen" und umschalten dabei.

Gruss

von Julian V. (torten_juli)


Lesenswert?

Karl Heinz schrieb:
> Du solltest hier

> ehe du den Timer erneut startest, den Timer auf 0 zurück setzen und
> eventuell in der Zwischenzeit aufgelaufene Overflow Compare Interrupts
> löschen.
>

Danke für den Hinweis. Das hatte ich nicht bedacht. Leider hat dies 
keine Änderung bewirkt.

>
> Allerdings: einen Wert von minimum 0.1 wirst du immer haben. Denn so wie
> du misst, musst du mindestens einmal in die Compare-Interrupt Routine
> rein. Selbst wenn da die Messung gleich als beendet erklärt wird, weil
> der Pin schon abgefallen ist. Teil der ISR ist aber das Hochzählen
> deiner Zehntelmillisekunden. Bei einem Startwert von 0 ergibt das dann
> natürlich 1.

Genau. 0.1ms habe ich immer als Ausgabe, wenn die Messung kleiner ist. 
Demzufolge müsste ich noch feiner messen, oder? Scheinbar entläd sich 
die Led schneller. Kann das sein? Im Wiki wird alle 5ms gemessen, sodass 
ich davon ausging, dass die Entladung schon länger benötigen wird.

von Karl H. (kbuchegg)


Lesenswert?

Das hier
1
ISR (TIMER0_COMPA_vect)
2
{
3
...
4
  if (PINB & (1<<PINB1) && measure)
5
...
kommt mir aus dem Bauch raus seltsam vor.

Willst du nicht eigentlich die Messung beenden, wenn der Pin von 1 auf 0 
wechselt?
D.h. die Messung ist beendet, wenn der Pin auf 0 gegangen ist. Du 
beendest die Messung aber, wenn der Pin auf 1 ist.

von Julian V. (torten_juli)


Lesenswert?

Karl Heinz schrieb im Beitrag #4006543:
> Das hier
>
1
> ISR (TIMER0_COMPA_vect)
2
> {
3
> ...
4
>   if (PINB & (1<<PINB1) && measure)
5
> ...
6
>
> kommt mir aus dem Bauch raus seltsam vor.
>
> Willst du nicht eigentlich die Messung beenden, wenn der Pin von 1 auf 0
> wechselt?

Genau das möchte ich messen. Ich muss ehrlich zugeben, dass ich dies aus 
dem Bsp.-Code aus dem Wiki angepasst habe

von Karl H. (kbuchegg)


Lesenswert?

Juli V. schrieb:
> Karl Heinz schrieb im Beitrag #4006543:
>> Das hier
>>
1
>> ISR (TIMER0_COMPA_vect)
2
>> {
3
>> ...
4
>>   if (PINB & (1<<PINB1) && measure)
5
>> ...
6
>>
>> kommt mir aus dem Bauch raus seltsam vor.
>>
>> Willst du nicht eigentlich die Messung beenden, wenn der Pin von 1 auf 0
>> wechselt?
>
> Genau das möchte ich messen. Ich muss ehrlich zugeben, dass ich dies aus
> dem Bsp.-Code aus dem Wiki angepasst habe

Dann musst du das aber auch so machen: Die Messung wird als beendet 
erklärt, wenn der Pin auf 0 gewechselt hat. Solange er 1 ist, 
interessiert das nicht weiter.
1
   if ( !(PINB & (1<<PINB1)) && measure)

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Juli V. schrieb:

> Ich muss ehrlich zugeben, dass ich dies aus
> dem Bsp.-Code aus dem Wiki angepasst habe

Im Wiki steht
1
 while(PINB & (1<<PIN3) && (entladezeit != 0xff)){
2
   ++entladezeit;
3
   _delay_ms(5);
4
 }
d.h. hier läuft die Zeit solange, solange der Pin auf 1 ist.

Du hast aber bei dir die Logik umgedreht. Dich interessiert nicht, wie 
lange du noch weiter messen musst, sondern in deinem Programm kommt es 
darauf an, wann die Messung zu beenden ist. Daher dreht sich dann die 
Port-Pin Bedingung logischerweise bei dir um.

von Julian V. (torten_juli)


Lesenswert?

Juli V. schrieb:
> Karl Heinz schrieb im Beitrag #4006543:
>> Das hier
>>
1
>> ISR (TIMER0_COMPA_vect)
2
>> {
3
>> ...
4
>>   if (PINB & (1<<PINB1) && measure)
5
>> ...
6
>>
>> kommt mir aus dem Bauch raus seltsam vor.
>>
>> Willst du nicht eigentlich die Messung beenden, wenn der Pin von 1 auf 0
>> wechselt?
>
> Genau das möchte ich messen. Ich muss ehrlich zugeben, dass ich dies aus
> dem Bsp.-Code aus dem Wiki angepasst habe

Ups. Da fehlt wo ein !
1
...
2
   if (!(PINB & (1<<PINB1)) && measure)
3
...

Hab es mal geändert. Jetzt läuft es ganz schön lange XD. Selbst nach 10s 
ist die Messung noch nicht fertig. Komisch

von Julian V. (torten_juli)


Lesenswert?

Karl Heinz schrieb:
> Juli V. schrieb:
>
>> Ich muss ehrlich zugeben, dass ich dies aus
>> dem Bsp.-Code aus dem Wiki angepasst habe
>
> Im Wiki steht
>
1
>  while(PINB & (1<<PIN3) && (entladezeit != 0xff)){
2
>    ++entladezeit;
3
>    _delay_ms(5);
4
>  }
5
>
> d.h. hier läuft die Zeit solange, solange der Pin auf 1 ist.
>
> Du hast aber bei dir die Logik umgedreht. Dich interessiert nicht, wie
> lange du noch weiter messen musst, sondern in deinem Programm kommt es
> darauf an, wann die Messung zu beenden ist. Daher dreht sich dann die
> Port-Pin Bedingung logischerweise bei dir um.

Stimmt genau. Man sollte immer genau schauen, was man sich kopiert O:-)
Danke für den Hinweis. Das ist nun behoben.

von Julian V. (torten_juli)


Lesenswert?

Tada. Danke für deine Hilfe.

Ich habe jetzt meine Messung gemacht. Die längste dauet knapp 12s. Ich 
poste später nochmal das komplette Programm, falls jemand ebenfalls dies 
ausprobieren möchte.

von Julian V. (torten_juli)


Lesenswert?

Erich schrieb:
>>Leds als Lichtsensoren
>
> Ja, gute LEDs können als Sensor arbeiten.
> Es entsteht eine Spannung bei Beleuchtung, an hochohmigem Widerstand.
> Man kann das auf einen A/D Eingang geben.
>
> Aber man braucht nichts "aufladen" und umschalten dabei.
>
> Gruss

Bitte informiere dich nochmal genauer. Hier im Wiki 
http://www.mikrocontroller.net/articles/Lichtsensor_/_Helligkeitssensor 
findest du unter LED informationen dazu, wie man eine LED ganz einfach 
mit normalen Vorwiderstand als Lichtsensor missbrauchen kann.

von Erich (Gast)


Lesenswert?

>Bitte informiere dich nochmal genauer.

Ob dein Zauber geht, kann ich nicht sagen.
Was geht ist das hier:
http://www.eeweb.com/blog/extreme_circuits/using-led-as-a-light-sensor

Es hat den Nachteil, daß es sofort arbeitet.
Ohne 12 Sekunden warten zu müssen.
In Bruchteilen von uS oder ns, eben wie schnell du den Ausgang mit 
Comparator oder uC/AD in der Lage bist auszuwerten.

Die Lichtgeschwindigkeit ist hoch.

Gruss

von Karl H. (kbuchegg)


Lesenswert?

Erich schrieb:
>>Bitte informiere dich nochmal genauer.
>
> Ob dein Zauber geht, kann ich nicht sagen.

Doch. Der funktioniert.

Allerdings: die 12 Sekunden sind unegwöhnlich. Das sollte wesentlich 
schneller gehen. Da stimmt was in der Hardware nicht, würde ich mal 
sagen.

von Marek L. (mareklew)


Lesenswert?

Erich schrieb:
> Ob dein Zauber geht, kann ich nicht sagen.
> Was geht ist das hier:
> http://www.eeweb.com/blog/extreme_circuits/using-led-as-a-light-sensor
>
> Es hat den Nachteil, daß es sofort arbeitet.

Außerdem auch die Nachteile, dass es:
- einen OpAmp braucht
- ggf. eine separate Versorgung
- ein Häufchen Bauteile
- und ist stark nichtlinear, wobei es sich der Vorteil einer 
exponentiellen Kennlinie einer Diode zum logarithmieren nicht nutzen 
lässt...

Wenn man z.B. nur wissen will, ob man die Hintergrundbeleuchtung der 
LCD-Anzeige einschalten soll ist das ein Overkill... ;-)

Gruß!
Marek

von John D. (Gast)


Lesenswert?

Erich schrieb:
>>Bitte informiere dich nochmal genauer.
> Was geht ist das hier:
> http://www.eeweb.com/blog/extreme_circuits/using-l...
>
> Es hat den Nachteil, daß es sofort arbeitet.
> Ohne 12 Sekunden warten zu müssen.
> In Bruchteilen von uS oder ns, eben wie schnell du den Ausgang mit
> Comparator oder uC/AD in der Lage bist auszuwerten.

Bist wirklich so oder willst du nur trollen? Diese Schaltung hat bei den 
typ. 50pF LED-Kapazität eine Zeitkonstante von 1,5ms!

von Julian V. (torten_juli)


Lesenswert?

Karl Heinz schrieb:
> Erich schrieb:
>>>Bitte informiere dich nochmal genauer.
>>
>> Ob dein Zauber geht, kann ich nicht sagen.
>
> Doch. Der funktioniert.
>
> Allerdings: die 12 Sekunden sind unegwöhnlich. Das sollte wesentlich
> schneller gehen. Da stimmt was in der Hardware nicht, würde ich mal
> sagen.

Das lag scheinbar an der Led(rote). Hab mal Messungen mit anderen Leds 
gemacht.

Meine Messung:

rote Led - dunkel 2.8s
rote Led - Tageslicht(stark bewölkt) 2.286s
rote Led - Schreibtischlampe an 1.726s

grüne Led - dunkel 1.649s
grüne Led - Tageslicht(stark bewölkt) 0.171s
grüne Led - Schreibtischlampe an 0.17s

blaue Led - dunkel 6.72s
blaue Led - Tageslicht(stark bewölkt) 1.878s
blaue Led - Schreibtischlampe an 0.022s

gelbe Led - dunkel 1.7s
gelbe Led - Tageslicht(stark bewölkt) 0.07s
gelbe Led - Schreibtischlampe an 0.01s

Auffälig war, je dunkler es war, desto größer die Messunterschiede. 
Wobei die rote ein sehr diffuse Verhalten gezeigt hat->also nicht 
geeignet wäre

von Erich (Gast)


Lesenswert?

>ein Häufchen Bauteile
Man kann die LED auch direkt an den uC Eingang anschliessen.
Falls dessen Eingangswiderstand definiert ist und nach Gnd geht.
Oder eben einen 2M2 dort anschliessen.
Natürlich ist dann der Hub (die max. Spannung) geringer.
Oder 'nen Buffer Type "HCU" (74hcu04) verwenden, dann kann's hochohmig 
bleiben.

>eine Zeitkonstante von 1,5ms
Der 30 MOhm ist der Arbeitswiderstand.
Siehe Hinweis oberhalb.
Ausserdem wird sich die Helligkeit nicht in jedem Meßschritt von ganz 
dunkel auf ganz hell ändern.
Die "Zeitkonstante" ist bei Verwendung eines uC sowieso Kappes.


@ Juli V.
>dunkel
>Schreibtischlampe

http://de.wikipedia.org/wiki/Lichtst%C3%A4rke_%28Photometrie%29


Gruss

von Martin S. (led_martin)


Lesenswert?

Juli V. schrieb:
> Das lag scheinbar an der Led(rote). Hab mal Messungen mit anderen Leds
> gemacht.
>
> Meine Messung:

Da ich gerade auch an etwas Ähnlichem rumtüftle, ich versuche aus den 
Messungen an den drei Chips von RGB-LEDs Farbinformationen zu gewinnen, 
wundere ich mich sehr über Deine rote LED. Generell werden ja rote LEDs 
sogar für solche Anwendungen empfohlen, und bei mir sind die Zeiten, bei 
der roten LED deutlich kürzer, als bei den Grünen und Blauen. Bei 
Tageslicht habe ich, an der Roten, ca. 0,01 Sekunden, bei Dunkelheit 
sind die Zeiten deutlich höher, und liegen teilweise im Sekundenbereich. 
Da ich bei mir 8 RGB-LEDs am Controller habe, also 24 LED-Chips, fällt 
auf, daß die Exemplarstreuungen riesig sind. Bei mir sind allerdings die 
Roten LED-Chips die besten, was die Stabilität der Messungen anbelangt. 
Bei Grün und Blau variieren die Ergebnisse stark, selbst bei konstanten 
(Licht-)Verhältnissen. Daß das bei längeren Zeiten instabiler wird, ist 
prinzipbedingt. Erstens ändert sich die Spannung langsamer, die mit der, 
eher unsicheren, Schaltschwelle des Portpins verglichen wird, zweitens 
haben störende Einflüsse, wie z.B. Leckströme, mehr Einfluß.

Bei einem anderen Projekt, was aber auch mit solchen Messungen arbeitet, 
konnte ich die Qualtät der Messungen, durch eine Abwandlung des 
Verfahrens, deutlich verbessern. Dort lade ich die LEDs auch in 
Sperrrichtung, schalte dann den einen Pin auf Eingang, warte eine feste, 
definierte Zeit, und messe dann die Spannung an diesem Pin per internem 
A/D-Wandler. Die Messzeit ist dabei recht kurz.

Mit freundlichen Grüßen - Martin

von Julian V. (torten_juli)


Angehängte Dateien:

Lesenswert?

Die Leds mit denen ich die Messung gemacht habe sind alles 
Low-Current-Leds. Habe jetzt fünf verschiedene rote Leds probiert und 
bei allen ist keine sinnvolle Messung durchzuführen. Warum auch immer. 
Die anderen Farben scheinen sich in diesem Fall besser zu eignen. Habe 
aber gerade nur diese zur Hand, sodass ich nicht noch mehr Messungen 
machen kann.

Ich werde bei der nächsten Elektronikbestellung neue Leds für dieses 
Experiment ordern. Vielleicht sind die Ergebnisse dann besser.

Im Anhang noch der komplette Code. Vielleicht kann das jemand 
gebrauchen.

von Martin S. (led_martin)


Lesenswert?

Nimm keine 'Low Current', da ist der Chip oft kleiner -> Weniger 
sensitive Fläche, nimm was 'Superhelles'.

Mit freundlichen Grüßen - Martin

von Julian V. (torten_juli)


Lesenswert?

Martin Schlüter schrieb:
> Nimm keine 'Low Current', da ist der Chip oft kleiner -> Weniger
> sensitive Fläche, nimm was 'Superhelles'.
>
> Mit freundlichen Grüßen - Martin

Ok. Wenn ich welche habe(muss erst welche kaufen), dann werde ich 
nochmal meine Ergebnisse posten. Habe mir das schon gedacht.

Danke auch für deinen informativen Beitrag. Die Messung ohne ADC ist bei 
mir vollkomen ausreichend, aber vielleicht benötige ich mal genauere 
Werte, dann habe ich die Idee schonmal im Hinterkopf. Ich möchte nur 
wissen, ob Tag, Dämmerung oder Nacht ist, um die Helligkeit meiner 
Anzeige anzupassen.

von Martin S. (led_martin)


Lesenswert?

Für diese Anwendung sollte das locker reichen, man hat ja auch Zeit, 
könnte also den Mittelwert vieler Messungen verwenden. Vielleicht sogar 
einen Tiefpass nachbilden, dann fährt die Anzeige 'weich' auf die 
passende Helligkeit. Sprunghafte Änderungen können da durchaus nerven.

Bei Anzeige käme mir die Idee, nicht leuchtende Segmente, oder 
unbenutzte Dezimalpunkte zur Messung zu 'missbrauchen'.

Mit freundlichen Grüßen - Martin

von chris_ (Gast)


Lesenswert?

Hallo Juli,

für einen Roboter habe ich als Liniensensor mal zwei LEDs benutzt:

http://www.hobby-roboter.de/forum/viewtopic.php?f=4&t=133&;

Ich kann Deine Beobachtung bestätigen, es ist tatsächlich so, dass bei 
sehr schwacher Beleuchtung die Integrationszeit in den Sekundenbereich 
geht.

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
Noch kein Account? Hier anmelden.