Arduino Helligkeit und Dunkelheit erkennen lassen

Hallo,

ich soll für die Schule ein Projekt mit Arduino machen. Dafür soll bei Nacht eine Pumpe laufen und bei Tag soll ein Elektromotor einen Verschluss öffnen. Die Schaltung und Programmierung dafür, denke ich, kriege ich hin, aber wie kann ein Arduino kennen, das Tag und das Nacht ist?

Eine Idee wäre, einen Stromkreis über einen LDR laufen zu basteln und den Arduino messen lassen, wie groß die Spannung ist, die ankommt. (Je heller, desto geringer der Widerstand --> große Spannung). Die Frage ist daher, ist so etwas möglich, und wie progammiert man so etwas?

Danke für eure Antworten

Mit dem LDR einen Spannungsteiler basteln und die Spannung über analogRead() messen.

Vernünftiger wäre hier aber eine Real Time Clock und damit den Sonnenaufgang und Untergang berechnen (das geht auf ein paar Minuten genau). Das hatten wir letztens hier: http://forum.arduino.cc/index.php?topic=218280.0

Mit dem LDR musst du aufpassen, dass er nicht auch auf Bewölkung und ähnliches reagiert.

Ich würde einen Phototransistor benutzen. Die Idee mit dem LDR ist auch gut :D.

Addi2438: Ich würde einen Phototransistor benutzen.

LDRs sind zwar sehr langsam, aber bei dieser Anwendung reicht das vollkommen.

Wenn die Aufgabe heisst : "Wenn es dunkel ist, ... " nimm nen LDR und Widerstand als Spannungsteiler Wenn die Aufgabe heisst: "Nachts ... " nimm eine Uhr ( RTC , z.B. DS1307 ), die du aber auch stellen können musst.

Zum einfachen Testen ist LDR besser, da muss man nicht Stundenlang warten, sondern kann den Sensor abdecken, im "echten Leben" wäre eine Uhr besser, die ist nicht so leicht durch einen abgedeckten Sensor zu stören.

LDRs sind zwar sehr langsam, aber bei dieser Anwendung reicht das vollkommen.

LDR sind viel zu schnell: je nach dem wie geduldig du beim Testen bist, sollte es einige Minuten hell bzw. dunkel sein, damit du daraus Tag/Nacht ableitest.

Schon klar. Das muss man in der Software erledigen. Mir ging es halt darum, dass man Fototransistoren sonst eher wegen der höheren Geschwindigkeit verwendet, was hier nichts bringt. Gegenüber LDRs haben die bei dieser Anwendung keine Vorteile.

iceman95:
ich soll für die Schule ein Projekt mit Arduino machen. Dafür soll bei Nacht eine Pumpe laufen und bei Tag soll ein Elektromotor einen Verschluss öffnen. Die Schaltung und Programmierung dafür, denke ich, kriege ich hin, aber wie kann ein Arduino kennen, das Tag und das Nacht ist?

Eine Idee wäre, einen Stromkreis über einen LDR laufen zu basteln und den Arduino messen lassen, wie groß die Spannung ist, die ankommt. (Je heller, desto geringer der Widerstand → große Spannung). Die Frage ist daher, ist so etwas möglich, und wie progammiert man so etwas?

Bei Deinem Anwendungsfall kommt es nicht darauf an, dass die Messung schnell sein muss, daher reicht im Prinzip eine einzelne trickreich angesteuerte LED, um die Helligkeit zu messen. Siehe Playground:
http://playground.arduino.cc/Learning/LEDSensor

Ich habe das mal etwas umgeschrieben, so dass die Helligkeitsmessung als Funktion verfügbar wird:

/* Arduino-Lichtmessung mit LED von 'jurs' für das Deutsche Arduino Forum
   Benötigte Hardware: Eine LED beliebiger Farbe (vorzugsweise weiß)
   Die LED wird bei diesem Versuch NICHT leuchten, sondern in Sperrrichtung betrieben.
   Sie wird wie ein "Kondensator" aufgeladen, der sich je nach Lichtstärke schneller
   oder langsamer entlädt. 
*/
#define LED_ANODE 6    // Anode = LED lAnger Draht
#define LED_KATHODE 7  // Kathode = LED Kurzer Draht
#define MAXCOUNTER 100000 // je größer diese Zahl, desto "dunklere" Messwerte sind möglich

void setup()
{
  Serial.begin(9600);
}

long helligkeit()
{
  // Funktion zur Helligkeitsmessung mit LED
  // große Zahlen = kleine Helligkeit
  // kleine Zahlen = große Helligkeit
  // die tatsächlichen Zahlen sind von der verwendeten LED (und der Helligkeit) abhängig
  long counter;
  // LED in Sperrrichtung "aufladen"
  pinMode(LED_ANODE,OUTPUT);
  digitalWrite(LED_ANODE,LOW); // Die LED Anode LOW setzen
  pinMode(LED_KATHODE,OUTPUT);
  digitalWrite(LED_KATHODE,HIGH); // Die LED Kathode ganz kurz auf HIGH setzen zum "Aufladen"
  pinMode(LED_KATHODE,INPUT); // Kathode hochohmig von der Stromversorgung abtrennen
  digitalWrite(LED_KATHODE,LOW);  // den internen PullUp-Widerstand abschalten
  // nun in einer Zählschleife "entladen", bis an der Kathode ein LOW gemessen wird
  for ( counter=0; counter<100000L; counter++) {
    if ( digitalRead(LED_KATHODE)==LOW) break; // Bei erfüllter break-Bedingung ist die LED entladen
  }
  return counter;
}

void loop()
{
  long messwert=helligkeit();
  Serial.print("Helligkeit: ");
  Serial.println(messwert);
  delay(500);
}

Beim Erstellen Deiner Hell/Dunkel-Anwendung mußt Du aufpassen, dass Du nicht einfach nur eine Schaltschwelle bei einem festen Wert vorsiehst, das ist eine FALSCHE Schaltlogik:

 if (licht>grenzwert)
  schaltedies();
else
  schaltejenes();

Das Problem dabei ist, dass reale Messwerte immer etwas streuen, und genau beim Grenzwert würdest du ein ständiges Hin- und Herschalten bekommen, wenn der Messwert mal über und mal unter dem Grenzwert liegt. D.h. bei Anbruch des Tages bzw. der Nacht könnte es passieren, dass dabei hunderte Male ganz schnell hin und her geschaltet wird.

Deshalb mußt Du eine Schaltlogik mit einer “Hysterese” machen. Das bedeutet, es gibt einen kleinen Bereich Messwerte, bei dem immer der letzte Schaltzustand beibehalten und nicht geschaltet wird. Richtige Schaltlogik:

 if (licht>grenzwert+hysterese)
  schaltedies();
else if (licht<grenzwert-hysterese)
  schaltejenes();

In dem Fall würde immer dann, wenn der Messwert zwischen (grenzwert+hysterese) und (grenzwert-hysterese) schwankt, NICHT geschaltet werden, sondern es bleibt innerhalb dieses Bereiches der letzte Schaltzustand weiter bestehen. Erst bei Über- oder Unterschreiten der Grenzen erfolgt tatsächlich ein Umschalten. Wie groß die Hysterese sinnvollerweise gewählt werden sollte, richtet sich danach, wie stark die Messwerte streuen und wie reaktionsfreudig die Schaltung sein soll.

Natürlich kannst Du auch “richtige” Lichtsensoren zur Lichtmessung verwenden. Aber LEDs hat man ja meistens in der Bastelkiste, so dass man gar nichts extra kaufen muß, um Helligkeit/Dunkelheit zu messen. Außer der Langsamkeit dieser Messungen gibt es ggf. einen weiteren Nachteil, den der Richtungsabhängigkeit: Genau so wie eine LED Licht hauptsächlich “nach oben” abstrahlt, wird bei der Messung per LED hauptsächlich “Licht von oben” gemessen. Aber das ist bei Deinem Anwendungsfall ja vielleicht auch gar nicht so verkehrt.

Viel Spaß beim Lichtmessen und Schalten!

Edit/Nachtrag: Das mit dem Realtime Clock Modul (DS1307 oder für seltenes Nachstellen DS3231) ist natürlich auch eine interessante Option. Man könnte sich z.B. dann je nach Datum die Sonnenaufgangs- und -untergangszeiten (oder Dämmerungszeiten) ausrechnen und Tag und Nacht anhand des Sonnenstands ermitteln. Viele Möglichkeiten.

Hallo, was soll es den werden? Bei Tag und Nacht, oder Hell und Dunkel?

Bei Nacht ( die Zeit zwischen Sonnenuntergang und Sonnenaufgang = Nacht) bei Tag ( die Zeit zwischen Sonnenaufgang und Sonnenuntergang = Tag) Da wäre die "Sonnen Auf- Untergang Geschichte", die Serenifly erwähne, eine sehr gute Sache für.

Der LDR hat einen nicht zu unterschätzenden Nachteil. Wenn Du damit "Nacht" dedektierst, dann wird es "Tag" wenn jemand mit der Lampe kommt. Bei "Tag" deckst Du ihn ab- und es ist "Nacht".

Wenn Du aber zwischen Sonnenuntergang und Sonnenaufgang nur die dedektierte "Dunkeheit" scharf machst, und zwischen Sonnenaufgang und Sonnenuntergang nur die "Helligkeit"- dann ist das ganze auch gegen "LichtManipulationen" gesichert. Gruß und Spaß dabei Andreas

Ich meinte Hell/Dunkel, soll vorgeführt werden und da wäre Tag/Nacht nicht wirklich günstig...

Danke für die vielen Antworten

Wie heißt der Befehl konkret, mit dem das verglichen wird. Und zweitens, wie kriege ich das hin, dass der Elektromotor nur einmal nachdem Wechsel seinen Befehl ausführt, da es nicht gut wäre, wenn er sich die ganze Zeit dreht, wenn es Hell ist.

iceman95: Wie heißt der Befehl konkret, mit dem das verglichen wird.

Das hat jurs oben mit der Hystere schon erklärt

Und zweitens, wie kriege ich das hin, dass der Elektromotor nur einmal nachdem Wechsel seinen Befehl ausführt, da es nicht gut wäre, wenn er sich die ganze Zeit dreht, wenn es Hell ist.

Merke dir den aktuellen Status ob es hell oder dunkel ist (z.B. mit einem boolean oder enum). Dann steuere den Motor nur an wenn der Status auf "dunkel" steht, aber der Sensor "hell" anzeigt. Bei Status == "hell" und Sensor == "hell" passiert dann nichts. Bei Status == "hell" und Sensor == "dunkel" kannst du dann wieder was anderes machen.

Falls Serenilfy dich auch verwirrt hat: Mit "Status" meint er, ob der Motor schon gelaufen ist seit Beginn der Helligkeit. Status wird also verändert : a) Wenn der Motor gelaufen ist, und b) Wenn es wieder dunkel ist

Wie lang soll der Motor denn laufen, ist die erste Frage. Da gibt es grundsätzlich verschiedene Möglichkeiten. Entweder: Motor einschalten, Warten ( delay ) , Motor ausschalten Oder: Motor einschalten und Einschalt-Zeit merken. Wenn (aktuelleZeit -EinschaltZeit) > WunschDauer Ausschalten

Die Auswahl hängt davon ab, wie die komplizierteren Fragen gelöst werden wollen: Was soll passieren, wenn es schon wieder dunkel wird, aber der Motor noch läuft ? ( Im delay Fall hast du gar keine Wahl, weil da der Sensor gar nicht erfasst wird während der Motor läuft. )

Vielleicht fallen dir noch mehr Sonderfälle ein, viel Spass.

Also ich hab da mal einen Versuch gestartet, das zu schreiben, aber mit LDR. Die meisten Vorschläge hab ich leider nicht so komplett verstanden, weswegen diese fehlen. Es erscheinen (vorerst) zwei Fehler:

14: error: expected ‘,’ or ‘;’ before ‘int’
30: error: function definition does not declare parameters

Programm ist wie folgt:

int MotorRechts = 1
int MotorLinks = 2
int LDR1 = 3
int LDR2 = 4
int Pumpe = 5
int Helligkeit

void setup
{
Serial.begin(9600);
pinMode(MotorLinks,OUTPUT);
pinMode(MotorRechts,OUTPUT);
pinMode(LDR1, OUTPUT);
pinMode(LDR2, INPUT);
pinMode(Pumpe, OUTPUT);
}

void loop
{
digitalWrite(LDR1, HIGH);
Helligkeit=analogRead(LDR2);

if(Helligkeit<2)
digitalWrite(MotorRechts, HIGH);
digitalWrite(MotorLinks, LOW);
digitalWrite(Pumpe, LOW);
delay(100);

if(Helligkeit>2)
digitalWrite(MotorRechts, LOW);
digitalWrite(MotorLinks, HIGH);
digitalWrite(Pumpe, HIGH);
delay(100);

}

Bitte erstens darum, mir zu sagen wo der Fehler liegt, weil den finde ich überhaupt nicht…
und zweitens um Verbesserungsvorschläge (wie ich zum Beispiel den Status einbaue…) V
Vielen Dank :smiley:

Da ist so vieles falsch :frowning:

Bei den globalen Variablen am Anfangen fehlen die abschließenden Strichpunkte.

Das macht wahrscheinlich nicht was du willst:

if(Helligkeit<2)
  digitalWrite(MotorRechts, HIGH);
  digitalWrite(MotorLinks, LOW);
  digitalWrite(Pumpe, LOW);
  delay(100);

Das führt die zweiten Zeile bedingt aus, aber alle anderen Zeilen werden immer ausgeführt. Du musst Code-Blöcke in geschweifte Klammern setzen:
http://manderc.manderby.com/structures/blocks/index.php

Dann musst du einen der Analog-Eingänge für analogRead() verwenden! Also z.B. A0 oder A1. 3 oder 4 sind die Digital Pins auf der anderen Seite.

Außerdem ist die Abfrage auf 2 etwas unsinnig. Eine Stelle entspricht 4,88mV. ca. 10mV sind gar nichts. Lass die Motoransteuerung erst mal weg (kann man auskommentieren) und schaue, dass du vernünftige Werte auf dem Serial Monitor hast. Mit Serial.println(Helligkeit) siehst du wasfür eine Spannung du misst. Wenn das passt, kannst du weiter machen.

Und wozu hast du einen Ausgang beim LDR?

pinMode(LDR1, OUTPUT);

Der Spannungsteiler sollte fest an 5V und Masse sein und du hast nur eine Verbindung zum Mittelpunkt:
http://www.doctronics.co.uk/images/sens01.gif

Da passt ein bischen was nicht so ganz. Schau Dir das Beispiel zum Thema AnalogRead ( http://arduino.cc/en/Reference/AnalogRead ) an, und versuche es zu verstehen. Taste Dich langsam vorwärts, versuche Deinen LDR auszulesen, und je nach Helligkeit eine LED ansteuern. Wenn das geht weiter machen mit LED nur einmal kurz ansteueren, etc.... Dabei versteht man plötzlich sehr viel wie es geht und zusammenhängt. Auch die Beispiele die in der Arduino IDE dabei sind sind sehr hilfreich. EDIT: Hier habe ich noch etwas gefunden, wo das schön mit einem Fotowiederstand erklärt wird. Musst nur ein wenig nach unten scrollen. http://www.arduino-tutorial.de/2010/06/analog-in/ Grüße,

Sven