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?
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.
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
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).
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
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.
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).
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.
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.
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.
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
unsignedintLichtmessung()
29
{
30
unsignedintcounter;
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
returncounter;
47
}
48
49
50
intmain()
51
{
52
while(1)
53
{
54
unsignedintmesswert=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".
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
:)
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.
In etlichen Hard- und Softwarevarianten kannst Du Dich auch hier mal
rein-/querlesen:
http://reaktivlicht.de/atmel.html
Im "Kochbuch" mit Schaltungsvarianten ...