Hallo,
ich habe eine Projekt am laufen, in dem ich zwei Lichtschranken habe die schauen sollen ob jemand durch die Tür geht. Da ich nur wissen will ob jemand in das Zimmer reingeht möchte ich gerne, dass das programm nur dann ausgeführt wird, wenn zuerst die rechte Lichtschranke unterbrochen wird und danach die zweite. Falls zuerst die linke unterbrochen wird und dann die rechte soll nichts passieren.
Mein versuch war zunächst mal einfach zwei if statements:
if(photoWertR < 700){
if(photoWertL < 500){
Pushover po = Pushover("XXXX","XXXXX", UNSAFE);
po.setDevice("XXXX");
po.setMessage("Jemand ist im Zimmer");
po.setSound("Alien alarm");
Serial.println(po.send());
//Die angeschlossene LED soll angeschaltet werden
digitalWrite(LEDPin, HIGH);
while(analogRead(fresPinR) < 700){
Serial.println("Jemand steht in der Tür");
}
}
}else{
digitalWrite(LEDPin, LOW);
}
}
Hat natürlich nicht geklappt, da er nicht unterscheiden kann welche der beiden zuerst abgedeckt ist. (Die Photoresistoren sind so nah einander, dass sie beim durchgehen beide gleichzeitig abgedeckt sind. Der eine nur früher als der andere und das möchte ich feststellen welcher zuerst und dann daraufhin ein Programm ausführen oder eben nicht.)
Kann mir jemand helfen mit was für einem befehl oder trick ich das machen kann? ^^ Danke schonmal im voraus!
Du könntest beim Durchschreiten der Lichtschranken jeweils die aktuelle Zeit abspeichern und dann überprüfen, welches die kleinere von beiden ist. Das sollte dann das Erkennen der Richtung möglich machen.
Daran hatte ich auch schon gedacht, aber mir ist nicht klar, wie ich das abfrage. Also wie weise ich die eine Zeit dem ersten resistor zu und wie die andere zeit dem anderen?
Ein Resistor ist ein Widerstand, dem kannst Du keinen Wert zuweisen.
Fremdworte bitte nur nutzen, wenn Du weißt, was sie bedeuten.
Du meinst eher eine Variable.
Nein, das ist kontraproduktiv.
Ich würde das als Statemachine bauen mit Abbruchbedingung.
Keinerlei Zeiten - nur switches.
Ok. Vielleicht eine Zeit als TimeOut.
Switch case? hab da auch drüber nachgedacht, aber ebenfalls nicht gewusst, wie ich da zu einer lösung kommen kann. Wie kann ich da denn sagen, er soll den case als erstes ausführen bevor er den anderen ausführt?
Ich denke dass alle Informationen vorliegen - Du musst es nur noch zusammensetzen
uint32_t zeitL;
uint32_t zeitR;
if(photoWertR < 700)
zeitR = millis();
if(photoWertL < 500)
zeitL = millis();
if (zeitR < zeitL) {
// Programm ausführen
}
else {
// nix tun (oder was anderes - z.B. LED wieder ausschalten
}
Natürlich das Ganze jetzt noch ordentlich verriegeln - beim nächsten Durchlauf von loop() willst Du ja nicht sofort wieder Zeiten nehmen... und damit wären wir dann bei der Zustandsmaschine: Schreib Dir in einfachen Worten auf, was nacheinander passieren muss, damit Deine Aktion "Alarm" ausgelöst werden soll. Vielleicht so:
Warten
links ausgelöst --> zurück auf Warten
rechts ausgelöst -> warten mit Timeout auf links ausgelöst
warten auf links
Timeout läuft und links ausgelöst --> Aktion
Timeout abgelaufen --> Warten
Aktion --> Warten
Wenn Du das vollständig und widerspruchsfrei aufgeschrieben hast, tippt sich der Code dazu fast von allein.
Habe ich auch mal gemacht.
Ich komme gänzlich ohne Zeiten aus.
Da beide Schranken abgedeckt sind, ist das sogar recht einfach.
Im Code ist ein delay() auskommentiert.
Wenn Du das auf dem Steckbrett machst, mach es rein, dann merkst Du das prellen der Schalter bzw. das stecken der Kontakte nicht so sehr.
Kurze Erklärung:
Ich frage die Pins ab, und merke mir den Zustand. Dann rufe ich die Funktion zur Feststellung der Richtung auf.
Nur wenn sich der Zustand ändert, wird wieder der Zustand gewerkt und das geht wieder von vorn.
Ich hoffe nichts vergessen zu haben.
// Forensketch - Laufrichtung feststellen
// https://forum.arduino.cc/t/zwei-lichtschranken-weiterschaltbedingung-moglich/925089
bool rechtsPin = false;
bool linksPin = false;
const byte photoRechts = 2;
const byte photoLinks = 3;
void setup()
{
Serial.begin(115200);
Serial.println(F("Start..."));
pinMode(photoRechts, INPUT_PULLUP);
pinMode(photoLinks, INPUT_PULLUP);
}
void loop()
{
// delay(100);
if (!digitalRead(photoRechts))
{
if (!rechtsPin)
{
rechtsPin = true;
bewegung();
}
}
else
{
if (rechtsPin)
{
rechtsPin = false;
bewegung();
}
}
if (!digitalRead(photoLinks))
{
if (!linksPin)
{
linksPin = true;
bewegung();
}
}
else
{
if (linksPin)
{
linksPin = false;
bewegung();
}
}
}
void bewegung()
{
enum {warten, rechts, links, ausgang, falsch};
static byte vorwaerts = warten;
switch (vorwaerts)
{
case warten:
if (rechtsPin) {vorwaerts = rechts; Serial.println(F("komme von rechts"));} // Eintritt von rechts nach links
if (linksPin) {vorwaerts = falsch; Serial.println(F("komme von links"));} // Eintritt von links nach rechts
break;
case rechts:
if (!rechtsPin) {vorwaerts = warten; Serial.println(F("gehe nach warten"));} // geht wieder zurück
if (linksPin) {vorwaerts = links; Serial.println(F("gehe nach links"));} // geht nach links
break;
case links:
if (!rechtsPin) {vorwaerts = ausgang; Serial.println(F("gehe zum ausgang"));} // geht nach links
if (!linksPin) {vorwaerts = rechts; Serial.println(F("gehe nach rechts"));} // geht wieder nach rechts
break;
case ausgang:
if (rechtsPin) {vorwaerts = links; Serial.println(F("gehe zurück nach links"));}
if (!linksPin) // bin am Ende
{
vorwaerts = warten;
// Hier kann eine Aktion rein
Serial.println(F("bin durch"));
}
break;
case falsch:
if (!rechtsPin && !linksPin) {vorwaerts = warten; Serial.println(F("falsche Richtung beendet"));} // geht wieder nach warten
break;
}
}
Ah okay, also kann ich auch das mit HIGH einfach schreiben richtig?
und eine weitere Frage, wofür ist das "enum" bzw ich vermute mal dass man damit die Variablen irgendwie definiert, aber was wäre das wenn man es als "normale" variable aufschreibt?
Also wenn man int oder float etc. verwenden würde?