Forum: Mikrocontroller und Digitale Elektronik LED als Sensor


von Chris (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen. Ich bin in der Abschlussklasse einer Schule für 
Elektroltechnick und bräuchte hilfe bei unserem Jahresprojekt.

Wir wollen soetwas bauen, wie im folgenden Video gezeigt wird.
http://www.youtube.com/watch?v=6WkqYltIJJU

Da der Lehrer will, dass wir verschiedene Methoden ausprobieren, müssen 
wir halt ein bischen experimentieren.

Meine Aufgabe ist es, eine LED als Helligkeitssensor zu verwenden. 
Gleichzeitig soll diese LED auch Leuchten, wenn man darüber fährt und es 
so dunkler wird.

Ich verwende einen Atmega16 Baustein dafür. Bis jetzt kann ich erkennen, 
ob es eine veränderung in der Helligkeit gibt. Dazu habe ich die LED in 
Sperrichtung an zwei I/O Ports angehängt, "lade" die LED auf und miss 
dann, bis sie wieder entladen ist. Je dunkler es wird, desto länger 
dauert es, bis es wieder entladen ist.

1
      // Portpin PD7 auf Ausgang stellen und LED aufladen
2
      DDRD = DDRD | 0b10000000; 
3
      PORTD = PORTD | 0b10000000; 
4
      _delay_ms(8);
5
  
6
      // Portpin PD7 auf Eingang stellen
7
      DDRD = DDRD & 0b01111111;
8
      PORTD = PORTD & 0b01111111;
9
  
10
      // Zeit (in 5ms Schritten) messen bis Signalpegel am Portpin auf LOW fällt
11
12
      while(PIND & (1<<PIND7) && a < 40000)
13
      {
14
          a++;
15
          _delay_us(5);
16
      }

Je größer jetzt also die Variabel a ist, desto dunkler ist es.

Um die LED jetzt aber auch als Leuchte verwenden zu können, habe ich mir 
überlegt, dass 10ms lang die Helligkeit gemessen wird und danach die LED 
entweder leuchtet oder nicht. Leider geht mein Code (Anhang) nicht.
Weiß jemand eine Lösung für das Problem?
Und ich befürchte auch, dass das "Entladen" der LED zu lange dauern 
könnte und somit die LED Blinkt, anstelle zu leuchten wenn es dunkel 
wird.

Ich wäre wirklich frah über eine Antwort.

PS: Das Projekt machen wir dann mit RGB. Kennt einer eine Seite, bei der 
man solche billig herbekommt?

: Verschoben durch User
von Easylife aka Technick (Gast)


Lesenswert?

a solltest du vor dem Aufladen der LED immer mit 0 initialisieren.

Was heisst "Leider geht mein Code nicht" genau?
Ich denke mal, du siehst nach der while-schleife immer 0 oder 1 für dein 
a.
Es würde mich wundern, wenn die Entladung der LED mehrere Millisekunden 
dauert.
Ich würde eher Microsekunden vermuten.

von Martin S. (led_martin)


Lesenswert?

Hallo,

solche Spielereien mit LEDs gehören zu meinen bevorzugten Bastel-Themen, 
die Zeiten, in denen eine LED sich 'entläd' kommen, bei geringer 
Helligkeit, durchaus in den Bereich von mehreren 100 ms. wenn es also 
nicht 'blinken' soll, sollte die, zu messende, Helligkeit nicht zu 
gering sein. Es macht auch Sinn, mit verschiedenen LED Typen zu 
experimentieren. LEDs die langwelliges Licht abstrahlen, also Rote, 
Orangene, oder Gelbe eignen sich am besten für die Helligkeitsmessung. 
Bei RGB-LEDs also den rotleuchtenden Chip verwenden. Bei der Messung 
wäre noch eine Möglichkeit, den A/D-Wandler zu verwenden, also: LED in 
Sperrrichtung laden, eine Seite freischalten (Diese Seite ist auch ein 
ADC-Eingang), eine definierte, kurze Zeit warten, Spannung messen. 
Vorteil, die Zeit kann recht kurz sein, und ist konstant.

Mit freundlichem Gruß - Martin

von Georg G. (df2au)


Lesenswert?

Alternativ kann du einfach die LED an einen der ADC Ports hängen und die 
Spannung messen. Das geht für eine Hell-Dunkel Erkennung recht gut. Und 
zum Leuchten schaltest du einfach den ADC ab, den Port auf Ausgang und 
los geht es (Vorwiderstand nicht vergessen, der stört bei der 
Spannungsmessung nicht).

von Chris (Gast)


Lesenswert?

Das mit dem ADC kling vielversprechend. So wäre die Zeit kein Problem 
mehr.
Kann mir einer vielleicht bitte erklären, wie man bei dem Atmega16 die 
ADC-Ports verwendet? Liegen tun sie ja auf PortA.

Gruß
Chris

von Georg G. (df2au)


Angehängte Dateien:

Lesenswert?

Beispiel als Anhang, quick and dirty.
Abwechselnd blinkt die LED und die Helligkeit wird gemessen. Um die 
Empfindlichkeit zu erhöhen, könnte man noch die Referenz auf "intern" 
umschalten.

von Jürgen S. (jurs)


Lesenswert?

Chris schrieb:
> Und ich befürchte auch, dass das "Entladen" der LED zu lange dauern
> könnte und somit die LED Blinkt, anstelle zu leuchten wenn es dunkel
> wird.

Erste Abhilfe wäre, die Aufladezeit zu verringern:
_delay_ms(8);
Ich glaube nicht, dass die LED 8 ms zum Aufladen benötigt, auch nicht 
mit einem Vorwiderstand an der LED. Probier's mal mit 100 Mikrosekunden 
oder noch weniger Aufladezeit!

Das zweite wäre die stärkere Begrenzung der Messzeit:
>       while(PIND & (1<<PIND7) && a < 40000)
>       {
>           a++;
>           _delay_us(5);
>       }

Damit mißt Du bei Dunkelheit bis zu 5µs x 40000 = 200000µs = 200 ms. Das 
ergibt ein Blinken mit 5 Hertz oder weniger.

Versuche, die Messzeit unter 20 ms zu halten, also ggf.
>       while(PIND & (1<<PIND7) && a < 20000)
>       {
>           a++;
>           _delay_us(1);
>       }

Und nicht vergessen, vor Messbeginn a auf 0 zu setzen, also
>       a=0;
>       while(PIND & (1<<PIND7) && a < 20000)
>       {
>           a++;
>           _delay_us(1);
>       }

Das sollte die Wahrnehmung von Blinken vermeiden, da die Messphase dann 
nur noch kurz ist. Allerdings kannst Du nur bis herunter zu einer 
gewissen Resthelligkeit messen (ist ggf. abhängig von der verwendeten 
LED).

von Chris (Gast)


Angehängte Dateien:

Lesenswert?

Kann mir einer den Fehler bei diesem Programm sagen?

Auf PORTC befinden sich übrigens LEDs mit denen ich anzeigen will, dass 
sich überhaupt etwas ändert, wenn sich die Helligkeit bei der "mess LED" 
verändert.

von Georg G. (df2au)


Lesenswert?

Du machst die passende LED an, machst sie aber nie wieder aus.

von Chris (Gast)


Lesenswert?

Daran liegt es nicht. Wenn die ich Sensor-LED weg tue, leuchten die 
ersten drei LEDs. Wenn ich es anschließe, immer noch die ersten 3. Es 
macht überhaupt keinen Unterschied ob die die Sensor-LED anschließe oder 
nicht.

von Chris (Gast)


Lesenswert?

Es steht immer genau der gleiche Wert in ADC, ob ich die LED anhänge 
oder nicht.
Kann mir da bitte einer weiter helfen?

von Jürgen S. (jurs)


Lesenswert?

Chris schrieb:
> Es steht immer genau der gleiche Wert in ADC, ob ich die LED anhänge
> oder nicht.
> Kann mir da bitte einer weiter helfen?

Soweit mir bekannt ist, darfst Du keine ADC-Werte messen.

Bei der ADC-Messung kommt eine "Sample-and-Hold" Schaltung zum Einsatz:
http://de.wikipedia.org/wiki/Sample-and-Hold-Schaltung

Zentrales Element dieser Schaltung ist ein Kondensator, der bei jedem 
ADC-Sampling aufgeladen werden muss. Da ist die Ladung von Deiner LED 
ruckzuck flöten.

Du MUSST zur Lichtmessung die LED in Sperrrichtung aufladen und 
anschließend auf Eingang schalten und so lange in einer engen Schleife 
den Eingangspegel ermitteln, bis die LED "entladen" ist.

ADC-Messungen kannst Du dabei komplett vergessen.
Das ist eine Sackgasse.
Schöne Grüße an denjenigen, der Dich in diese ADC-Sackgasse geführt hat!
Du hattest zu Anfang schon richtig angefangen, bevor Du dann den Irrweg 
mit ADC-Messungen beschritten hast.

von Jürgen S. (jurs)


Lesenswert?

Als Nachtrag hier mal ein Code, den ich als Arduino-Programmierer 
gemacht habe, unter Verzicht auf hoffentlich alle Arduino-spezifischen 
Library Befehle, so dass es allgemein mit AVR 8-Bit Controllern unter 
GCC laufen sollte.

Getestet habe ich mit einer grünen 20mA LED auf einem Atmega2560 Board 
mit 16 MHz Taktrate.

Du müßtest eigentlich nur die Definitionen von LED_K und LED_A anpassen 
an Pin und Port, wo Du die LED angeschlossen hast.

Mit den am Anfang definierten Makros habe ich mir versucht, einige 
Arduino-Befehle nachzubauen, so dass ich das Programm quasi im 
Arduino-Stil programmieren konnte, ohne entsprechende Library-Funktionen 
zu verwenden. Ich hoffe, es wird durch die Kommentare klar, was der Code 
macht.
1
#include <avr/delay.h>
2
3
/* Macro function to declare an output pin */
4
#define out(x)      _out(x)
5
#define _out(bit,port)  DDR##port |= (1 << bit)
6
7
/* Macro function to declare an input pin */
8
#define in(x)      _in(x)
9
#define _in(bit,port)  DDR##port &= ~(1 << bit)
10
11
/* Macro function to set an output pin high */
12
#define on(x)      _on(x)
13
#define _on(bit,port)  PORT##port |= (1 << bit)
14
15
/* Macro function to set an output pin low */
16
#define off(x)      _off(x)
17
#define _off(bit,port)  PORT##port &= ~(1 << bit)
18
19
/* Macro function to get state of input pin */
20
#define get(x)      _get(x)
21
#define _get(bit,port)  (PIN##port & (1 << bit))
22
23
// Definieren von Pin und Register der beiden LED Anschlüsse
24
#define LED_K PH4,H
25
#define LED_A PH3,H
26
27
28
unsigned int Lichtmessung()
29
{
30
  unsigned int counter;
31
  // LED Anode auf OUTPUT/LOW
32
  out(LED_A);
33
  off(LED_A);
34
  // LED Kathode auf OUTPUT/HIGH
35
  out(LED_K);
36
  on(LED_K);
37
  _delay_us(4);
38
  // Kathode wieder auf INPUT
39
  in(LED_K);
40
  off(LED_K);
41
  // In einer Schleife zählen, bis Kathode auf LOW geht
42
  for ( counter = 0; counter < 65000; counter++) {
43
    if (get(LED_K)==0) break;
44
     _delay_us(5);
45
  }
46
  return counter;
47
}
48
49
50
int main()
51
{
52
  while(1)
53
  {
54
    unsigned int messwert=Lichtmessung();
55
    out(LED_K);
56
    out(LED_A);
57
    on(LED_A);  // LED Anode HIGH
58
    _delay_us(5000); // für 5 ms blinken
59
    off(LED_A);
60
  }
61
}

Dieselbe LED wird sowohl zum Messen der Lichtstärke als auch zum 
Anzeigen des Ergebnisses verwendet. Wenn alles funktioniert, sollte die 
LED bei Dunkelheit blinken, bei zunehmender Helligkeit schneller 
blinken, und bei ausreichender Helligkeit "Dauerlicht" geben.

Die sichtbaren Aus-Phasen entstehen dadurch, dass die Messung und damit 
die Aus-Phase um so länger dauert, je dunkler es ist.

Ach ja: Die Schaltung ist auf einem Breadboard aufgebaut extrem 
berührungsempfindlich. Der Aufbau entspricht quasi fast einem 
kapazitiven Nährungssensor und sie verhält sich auch so.

Also: Die Pfoten und alle Körperteile weg vom Breadboard!
Bei Annäherung Deiner Hand ans Breadboard bekommst Du sonst denselben 
Effekt wie bei "Helligkeit".

von Dirk K. (dekoepi)


Lesenswert?

Danke für diese Inspiration! War mir gänzlich unbekannt, dass man die 
Umgebungslichtstärke mit einer LED messen kann.

Da heute wieder der komische Quatsch für die holde Weiblichkeit in der 
Glotze lief, einfach mal probiert: LED umgekehrt ansteuern, ein paar ns 
"aufladen", anschließend auf ADC umstellen und messen. Ich bekomme 
deutlich unterschiedliche Ergebnisse bei unterschiedlichen Helligkeiten. 
Mit starker LED-Taschenlampe angeleuchtet 1/10 der ADC-Bandbreite 
weniger als im gemütlichen Dämmerlicht. So ganz Sackgasse kann das mit 
dem ADC also nicht sein. (Absolutwerte vom ADC: Angestrahlt ~500, 
Dämmerlicht ~850).

Jetzt auch mal nach Hintergrundinformationen suchen. Finde ich spannend 
:)

von Georg G. (df2au)


Lesenswert?

Jürgen S. schrieb:
> Soweit mir bekannt ist, darfst Du keine ADC-Werte messen.

Kennst du Nuhr?

Der Fotostrom der LED reicht allemal aus, die wenigen pF Sample 
Kapazität zu laden. Das Verfahren arbeitet hier seit Anno Knips 
einwandfrei.

von Bussard (Gast)


Lesenswert?

In etlichen Hard- und Softwarevarianten kannst Du Dich auch hier mal 
rein-/querlesen:

http://reaktivlicht.de/atmel.html

Im "Kochbuch" mit Schaltungsvarianten ...

von PopCorn (Gast)


Lesenswert?

Hallo,

in diesem Link ist zwar ein Programm in Assembler geschrieben, aber als 
Beispiel gut zu gebrauchen.
Du kannst es in C  umschreiben.

http://www.loetstelle.net/diesunddas/ledlichtsensor/ledlichtsensor.php

LG

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.