Bahnübergang mit LDR und zwei Servos

Guten Tag zusammen,

wir haben für ein Schulprojekt vor, einen Bahnübergang mit zwei Servos und LDRs programmieren.
Grundlegende Idee:

LDR1 erreicht einen niedrigen Wert → Servos gehen runter und Andreaskreuze blinken
LDR2 erreicht niedrigen Wert → Servos gehen wieder hoch und Andreaskreuze blinken nicht mehr

Unser Problem ist, dass die Servos ständig hoch und runter fahren, obwohl wir erreichen wollen, dass sie an einer Stelle warten, bis der zweite LDR sie wieder hochschickt.

Hier das Programm.

int sensorPin = A0; 
int sensorPin2 = A1;
int sensorValue = 0;
int sensorValue2 = 0;
#include <Servo.h>
Servo servo1;
Servo servo2; 


void setup() {
servo1.attach(7);
servo2.attach(8);
Serial.begin(9600); 
pinMode(11, OUTPUT);

}


void loop() {
sensorValue = analogRead(sensorPin);
sensorValue2 = analogRead(sensorPin2); 
Serial.println(sensorValue); 
delay(100);

if (analogRead(sensorValue2)< 100)
{
  digitalWrite(11, HIGH);
  delay(50);
  digitalWrite(11, LOW);
  delay(50);
  digitalWrite(11, HIGH);
  delay(50);
  digitalWrite(11, LOW);
  delay(50);
  digitalWrite(11, HIGH);
  delay(50);
  digitalWrite(11, LOW);
  delay(30);
  digitalWrite(11, HIGH);

  servo1.write(10); delay(15);
  servo2.write(10); delay(15);
  servo1.write(15); delay(15);
  servo2.write(15); delay(15);
  servo1.write(20); delay(15);
  servo2.write(20); delay(15);
  servo1.write(25); delay(15);
  servo2.write(25); delay(15);
  servo1.write(30); delay(15);
  servo2.write(30); delay(15);
  servo1.write(35); delay(15);
  servo2.write(35); delay(15);
  servo1.write(40); delay(15);
  servo2.write(40); delay(15);
  servo1.write(45); delay(15);
  servo2.write(45); delay(15);
  servo1.write(50); delay(15);
  servo2.write(50); delay(15);
  servo1.write(55); delay(15);
  servo2.write(55); delay(15);
  servo1.write(60); delay(15);
  servo2.write(60); delay(15);
  servo1.write(65); delay(15);
  servo2.write(65); delay(15);
  servo1.write(70); delay(15);
  servo2.write(70); delay(15);
  servo1.write(75); delay(15);
  servo2.write(75); delay(15);
  servo1.write(80); delay(15);
  servo2.write(80); delay(15);
  servo1.write(85); delay(15);
  servo2.write(85); delay(15);
  servo1.write(90); delay(15);
  servo2.write(90); delay(15);
  servo1.write(95); delay(15);
  servo2.write(95); delay(15);
  servo1.write(100); delay(15);
  servo2.write(100); delay(15);
  }

if (analogRead(sensorValue)< 100)
{
  digitalWrite(11, LOW);
  servo1.write(95); delay(15);
  servo2.write(95); delay(15);
  servo1.write(90); delay(15);
  servo2.write(90); delay(15);
  servo1.write(85); delay(15);
  servo2.write(85); delay(15);
  servo1.write(80); delay(15);
  servo2.write(80); delay(15);
  servo1.write(75); delay(15);
  servo2.write(75); delay(15);
  servo1.write(70); delay(15);
  servo2.write(70); delay(15);
  servo1.write(65); delay(15);
  servo2.write(65); delay(15);
  servo1.write(60); delay(15);
  servo2.write(60); delay(15);
  servo1.write(55); delay(15);
  servo2.write(55); delay(15);
  servo1.write(50); delay(15);
  servo2.write(50); delay(15);
  servo1.write(45); delay(15);
  servo2.write(45); delay(15);
  servo1.write(40); delay(15);
  servo2.write(40); delay(15);
  servo1.write(35); delay(15);
  servo2.write(35); delay(15);
  servo1.write(30); delay(15);
  servo2.write(30); delay(15);
  servo1.write(25); delay(15);
  servo2.write(25); delay(15);
  servo1.write(20); delay(15);
  servo2.write(20); delay(15);
  servo1.write(15); delay(15);
  servo2.write(15); delay(15);
  servo1.write(10); delay(15);
  digitalWrite(11, LOW);
}
}

Was genau haben wir falsch programmiert und wie ist es möglich die Servos an einer Stelle stehen zu lassen?

Wir würden uns sehr über Hilfe und Antworten freuen!

Mit freundlichen Grüßen

Hallo,

wenn ich mir deinen Code richtig anschaue, liest du folgendes aus:

analogRead(sensorValue2)

Lass das analogRead weg, du speicherst ja schon vorher das ausgelesene in sensorValue2

Gruß,
Ludwig

PS: du kannst dir sehr viel sparen wenn du es ähnlich wie ich es hier machst:

if(zsg == "GDown"
 {
     for(int idx = 50; idx <= 108; idx++)
     {
       greifer_Hoehe.write(idx);
       delay(10);
     }
 }

Die vielen delays sind etwas unelegant und betteln um unerwünschte Ergebnisse. Schau mal hier rein http://playground.arduino.cc/Code/Timer (oder google arduino timer - gibt mehrere timer Bibliotheken)

Die LDR-Abfrage muss für einen Zeitraum x deaktiviert werden sobald ausgelöst, wegen nutzlosem Signalwirrwar wenn die der Lok folgenden Waggons (und deren Zwischenräume) rüberrattern. Beispielsweise eine durch einen Timer negierte flag (einfache boolean Variable - bool_FlagDurchfahrt true/false) nach vielleicht 10 Sekunden. [edit] ... und/oder einer Variablen, die wenn größer null, angibt, welcher Sensor zuerst angeschlagen hat, um dann nur noch dem anderen zu lauschen. Stichwort switch-case.

Das Bewegen der Schrankenservos sollte auch über eine vom Timer aufgerufe Funktion überdommen werden. Beispielsweise mit Übergabe eines Zählers (oder meinetwegen auch einer globalen Zählervariablen). So kannste Grad für Grad hochfahren in genau definierter Zeit.

Für eindeutigere Signale würde ich einen Magnetfeldsensor (Hall-Sensor, Reed-Relais - Neodyn unter der Lok) im Austausch mit den LDRs vorschlagen. [edit] ... sowie einem dritten Servo, der nur hin und herfährt/ rotiert (oder einem Elektromagneten - Zylindermagnet) und dabei gegen ein kleines Glöckchen unter der Platte stößt.

Außerdem müssen beide Sensoren den Schrankenvorgang auslösen können. Was ist, wenn der Zug aus der anderen Richtung kommt?

Zerfetzte Plastikfigürchen in zermalmten Spielzeugautowraks mit heraushängendem Plastikgedärm, abgerissenen Gliedmäßchen und massenhaft verspritzter roter Farbe. Entgleister Zug im Bahnhofsgebäude. Hunderte von toten winkenden Männchen wegen eines nicht ausgelösen Schrankensignals... Das kann man doch nich in der Schule vor 22:00 Uhr bringen... :D

Hallo,
so wie das Programm momentan ist, bewegt sich die Schranke permanent hoch und runter, wenn beide LDRs eine Spannung < 100 an den Arduino geben. Um das zu vermeiden, muss abgewartet werden, dass die beiden Values wieder größer werden. Dies kann, wie panpira bereits gesagt hat, mit einem boolean gelöst werden.

Also vielen Dank schon mal, aber wir wollen drauf hinweisen, dass wir in der zehnten Klasse sind und jetzt nicht all zu viel wissen über das Programmieren (NXT können wir, sollen aber jetzt Arduino benutzen). Zudem wollen wir nur einen Zug simulieren, also wir haben Schienen etc, aber wollen keinen Zug und arbeiten nur mit den vorhandenen Licht, d.h. kommt ein Zug wird es ja dunkel ... Und die Strecke ist nur einspurig und nur von einer Richtung aus befahrbar ;-) .

sensorValue = analogRead(sensorPin);
sensorValue2 = analogRead(sensorPin2);

Diese Zeilen sind richtig, diese ergeben keinen Sinn (siehe #1):

if (analogRead(sensorValue2)< 100)
if (analogRead(sensorValue)< 100)

Wenn sensorValue beispielsweise den Wert 50 hätte, liest Du den analogen Wert von Pin 50, den es nicht gibt.

Die vielen servo1.write(10); kann man kürzer in eine Schleife bringen. Da ginge for oder while oder, meine Nummer Eins, loop().

Du verabredest Dich mit Deinen Kumpels in einer halben Stunde und dann erstarrst Du im Nichtstun. Ist das realistisch? Wohl kaum, Du checkst Deine Kontakte. Mit delay() verurteilst Du den Arduino zum (beinahe) Nichtstun. Ist das fair?

Tatsächlich verabredest Du Dich in einer halben Stunde, überprüfst gelegentlich die Uhr und machst irgendwas zwischendrin. Das solltest Du auch dem Arduino zugestehen. Wenn der Arduino mittels millis() auf die “Uhr” schaut, bekommt er eine Zahl zurück → altMillis. Dann schaut er, ob eine bestimmte Zeit abgelaufen ist millis() - altMillis >= intervall. Wenn das so ist, trifft er sich mit seinen Kumpels … ach nee, dann verstellt er den Servo ein Stück. millis() wird jede Millisekunde eins rauf gezählt, siehe Referenz. In den Beispielen der IDE findest Du BlinkWithoutDelay.ino als praktische Anwendung, hier im Forum noch viel mehr.

Fröhliches Grübeln :slight_smile: