3 Servos mit 3Tastern einschalten und über Timer zurückfahren

Hallo zusammen, ich möchte für ein carsystem Modellbahn 3 Stoppstellen für Bus einrichten. Dazu fährt je ein Magnet hoch und schaltet Reedkontakt am Fahrzeug. Auslösung mittels Hallsensor.
Dann soll der der Servo nach zB. 10 sec wieder in Ausgangsstellung fahren und Fahrzeug freigeben.
ich habe einen kleinen Code geschrieben mit delays . das klappt prima bei einer Stoppstelle. Aber bei 3 sind drei delays durch die Programmschleife eher hinderlich. Kann man das auch mit millis lösen bzw. am Code etwas anpassen? Oder sind millis nur für wiederkehrende Programme?
Danke

#include <Servo.h>

Servo servo1 ;               //Stoppstelle 1
Servo servo2 ;               //Stoppstelle 2
Servo servo3 ;               //Stoppstelle 3
int h1 = 2;                  //Hallsensor 1
int h2 = 3;                  //Hallsensor 2
int h3 = 4;                  //Hallsensor 3

void setup() {

  pinMode(h1, INPUT);
  pinMode(h2, INPUT);
  pinMode(h3, INPUT);
  servo1.attach(8); 
  servo2.attach(9);
  servo3.attach(10);
}

void loop() {

  //Stopstelle 1

  int val1 = digitalRead (h1) ;
  if (val1 == LOW) {
    servo1.write(0);
    delay(5000);
  }
  else {
    servo1.write(50);
    delay(100);
  }

  //Stopstelle 2

  int val2 = digitalRead (h2) ;
  if (val2 == LOW) {
    servo2.write(0);
    delay(5000);
  }
  else {
    servo2.write(50);
    delay(100);
  }

  //Stopstelle 3

  int val3 = digitalRead (h3) ;
  if (val3 == LOW) {
    servo3.write(0);
    delay(5000);
  }
  else {
    servo3.write(50);
    delay(100);
  }

}

Blockquote

Ihr Beitrag wurde an seinen aktuellen Speicherort verschoben, da er besser geeignet ist.

  1. Millis ist kein Timer.
  2. Reed-Kontakt und Hallsensor sind 2 verschiedene Bauteile. Beide sind auf Magnetfelder empfindlich.

Ja Du kannst mit Millis() mehrere unabhängige Zeitsteuerungen bauen. Du brauchst nur für jede Zeitsteuerung ein Variablenset ( aktualmillis oldmillis).

Grüße Uwe

Du könntest auch meine MobaTools hernehmen. Da ist ein Beispiel drin, was genau sowas mit Led's macht ( per Taster einschalten, und über die Zeit ausschalten ).
Wenn Du da statt dem Ein-Ausschalten der Led's den Servoaufruf verwendest, macht er genau was Du willst. Und wenn Du noch die MoToServo statt der standard-Servo verwendest, rumpelt das Servo auch nicht immer mit full speed hin- und her :wink:

also nur zur Erklärung:
die Hallsensoren sind in der Straße, das Fahrzeug löst mittels Führungsmagnet den Servo aus, der wiederum einen Magnet Richtung Auto / Strasse fährt und so den Reedkontakt im Fahrzeug betätigt.
mit den millis (aktual/old) werd ich mal schauen ob ich bissel Erklärung im Netz finde/ bzw. mir von microbahner das mal anschauen.
Danke euch

ich kann anbieten: einen Digitalausgang nach einer bestimmten Zeit wieder zurück stellen:
https://werner.rothschopf.net/202003_arduino_retriggerbares_nachlaufrelais.htm
oder in OOP
https://werner.rothschopf.net/202003_arduino_retriggerbares_nachlaufrelais_oop.htm

ob du ein digitalWrite oder ein servo.write machst, sollte eigentlich ziemlich egal sein. Das Konzept ist das gleiche.

Hallo microbahner, ich komme irgendwie nicht weiter

Blockquote

#include <MobaTools.h>

const byte servo1P =  8;
const byte servo2P =  9;

const byte taster1P = 2;
const byte taster2P = 3;

Servo servo1P ;               //Stopstelle 1
Servo servo2P ;               //Stopstelle 2

MoToTimer Blinkzeit1;
MoToTimer Blinkzeit2;

void setup() {
  Serial.begin(115200);
  while (!Serial);  // nur für Arduino Micro/Leonardo notwendig
  pinMode(servo1P, OUTPUT);
  pinMode(servo2P, OUTPUT);
  pinMode(taster1P, INPUT_PULLUP );
  pinMode(taster2P, INPUT_PULLUP );
}

void loop() {
  // -------- Schalten der 1. Led ------------------
  if ( !digitalRead(taster1P) && !Blinkzeit1.running() ) {
    Serial.println("Zeit1 starten");
    // Zeit aufziehen und Led schalten
    Blinkzeit1.setTime( 2000 );
    servo1.write(10);
  }
  if ( Blinkzeit1.expired() ) {
  //if (! Blinkzeit1.running() ) {
    Serial.println("Zeit 1 abgelaufen");
    servo1.write(30);
  }
  // -------- Schalten der 2. Led ------------------
  if ( !digitalRead(taster2P) && !Blinkzeit2.running() ) {
    // Zeit aufziehen und Led schalten
    Serial.println("Zeit2 starten");
    Blinkzeit2.setTime( 1500 );
    servo2.write(10);
  }
  if ( Blinkzeit2.expired() ) {
    Serial.println("Zeit 2 abgelaufen");
    servo2.write(30);
  }
  
}

Naja, die Servos musst Du schon auch einrichten, genauso wie Du das in deinem ersten Sketch gemacht hast, sonst kann das nichts werden. Und wenn Du die Servoklasse der MobaTools verwenden willst, musst Du auch den entsprechenden Klassennamen nutzen: (ungetestet, hab gerade kein Testequipment zur Hand )

#include <MobaTools.h>

const byte servo1P =  8;
const byte servo2P =  9;

const byte taster1P = 2;
const byte taster2P = 3;

MoToServo servo1 ;               //Stopstelle 1
MoToServo servo2 ;               //Stopstelle 2

MoToTimer Blinkzeit1;
MoToTimer Blinkzeit2;

void setup() {
  Serial.begin(115200);
  while (!Serial);  // nur für Arduino Micro/Leonardo notwendig
  pinMode(servo1P, OUTPUT);
  pinMode(servo2P, OUTPUT);
  pinMode(taster1P, INPUT_PULLUP );
  pinMode(taster2P, INPUT_PULLUP );
  servo1.attach(servo1P); 
  servo1.setSpeed(20);      // optional, weenn sich das Servo langsamer bewegen soll
  servo2.attach(servo2P);
  servo2.setSpeed(20);      // optional, weenn sich das Servo langsamer bewegen soll

}

void loop() {
  // -------- Schalten der 1. Led ------------------
  if ( !digitalRead(taster1P) && !Blinkzeit1.running() ) {
    Serial.println("Zeit1 starten");
    // Zeit aufziehen und Led schalten
    Blinkzeit1.setTime( 2000 );
    servo1.write(10);
  }
  if ( Blinkzeit1.expired() ) {
  //if (! Blinkzeit1.running() ) {
    Serial.println("Zeit 1 abgelaufen");
    servo1.write(30);
  }
  // -------- Schalten der 2. Led ------------------
  if ( !digitalRead(taster2P) && !Blinkzeit2.running() ) {
    // Zeit aufziehen und Led schalten
    Serial.println("Zeit2 starten");
    Blinkzeit2.setTime( 1500 );
    servo2.write(10);
  }
  if ( Blinkzeit2.expired() ) {
    Serial.println("Zeit 2 abgelaufen");
    servo2.write(30);
  }
  
}

Supi ich danke dir. Man macht das zu selten und steigt da nicht wirklich tief rein und ehe mal wieder was kommt ist wieder was im Kopf verschwunden. :unamused:

Geht's denn jetzt?
Und was ich noch gesehen habe: den pinMode für servo1P und servo2P brauchst Du nicht, das macht das attach mit. Stört zwar nicht, ist aber überflüssig.

ja funzt, :ok_hand:
okay, nehm ich raus.

Hallo Microbahner,
ich habe nun versucht meinen 3. Servo hinzuzufügen.
Geht allerdings nicht. Weiß gerade nicht weiter, :thinking:

Blockquote

// Carsystem Bushaltestellen //

// Arduino Nano //

#include <MobaTools.h>

const byte servo1P =  8;
const byte servo2P =  9;
const byte servo3P =  10;

const byte taster1P = 2;         // Hallsensor 1
const byte taster2P = 3;         // Hallsensor 2
const byte taster3P = 4;         // Hallsensor 3

MoToServo servo1 ;               //Stopstelle 1
MoToServo servo2 ;               //Stopstelle 2
MoToServo servo3 ;               //Stopstelle 3

MoToTimer Blinkzeit1;
MoToTimer Blinkzeit2;
MoToTimer Blinkzeit3;

void setup() {
  Serial.begin(115200);
  pinMode(servo1P, OUTPUT);
  pinMode(servo2P, OUTPUT);
  pinMode(servo3P, OUTPUT);
  pinMode(taster1P, INPUT_PULLUP );
  pinMode(taster2P, INPUT_PULLUP );
  pinMode(taster3P, INPUT_PULLUP );
  servo1.attach(servo1P);
  servo2.attach(servo2P);
  servo2.attach(servo3P);

}

void loop() {
  // -------- Schalten Servo/Haltestelle 1 ------------------
  if ( !digitalRead(taster1P) && !Blinkzeit1.running() ) {
    Serial.println("Zeit1 starten");
    // Zeit aufziehen und Servo fahren
    Blinkzeit1.setTime( 5000 );
    servo1.write(0);
  }
  if ( Blinkzeit1.expired() ) {
    //if (! Blinkzeit1.running() ) {
    Serial.println("Zeit 1 abgelaufen");
    servo1.write(80);
  }
  // -------- Schalten Servo/Haltestelle 2 ------------------
  if ( !digitalRead(taster2P) && !Blinkzeit2.running() ) {
    // Zeit aufziehen und Servo fahren
    Serial.println("Zeit2 starten");
    Blinkzeit2.setTime( 5000 );
    servo2.write(0);
  }
  if ( Blinkzeit2.expired() ) {
    Serial.println("Zeit 2 abgelaufen");
    servo2.write(80);
  }
  // -------- Schalten Servo/Haltestelle 3 ------------------
  if ( !digitalRead(taster3P) && !Blinkzeit3.running() ) {
    Serial.println("Zeit3 starten");
    // Zeit aufziehen und Servo fahren
    Blinkzeit3.setTime( 5000 );
    servo3.write(0);
  }
  if ( Blinkzeit3.expired() ) {
    //if (! Blinkzeit3.running() ) {
    Serial.println("Zeit 3 abgelaufen");
    servo3.write(80);
  }
}

Das ist eine ziemlich nichtssagende Aussage ...
Die seriellen Ausgaben funktionieren, nur des 3. Servo bewegt sich nicht.

  servo1.attach(servo1P);
  servo2.attach(servo2P);
  servo2.attach(servo3P); // <--- Hier solltest Du schon auch 'servo3' schreiben

Danke, immer wieder drüber geschaut, aber das hab ich übersehen. :face_with_raised_eyebrow:

Bei 3 Stopstellen lohnt sich dann auch die Nutzung von Arrays. Der Sketch wird kürzer, und solche Kopierfehler unwahrscheinlicher:

// Carsystem Bushaltestellen //

// Arduino Nano //

#include <MobaTools.h>

const byte servoP[] =  {8, 9, 10};
const byte tasterP[] = {2, 3, 4};         // Hallsensoren
const byte stopAnzahl = sizeof(servoP);

MoToServo servo[stopAnzahl];            //Stopstellen
MoToTimer Blinkzeit[stopAnzahl];

void setup() {
    Serial.begin(115200);
    for ( byte iX = 0; iX < stopAnzahl; iX++ ) {
        pinMode(tasterP[iX], INPUT_PULLUP );
        servo[iX].attach(servoP[iX]);
    }
}

void loop() {
    for ( byte iX = 0; iX < stopAnzahl; iX++ ) {
        // -------- Schalten Servos/Haltestellen ------------------
        if ( !digitalRead(tasterP[iX]) && !Blinkzeit[iX].running() ) {
            Serial.print("Starte Zeit "); Serial.println(iX+1);
            // Zeit aufziehen und Servo fahren
            Blinkzeit[iX].setTime( 5000 );
            servo[iX].write(0);
        }
        if ( Blinkzeit[iX].expired() ) {
            Serial.print(iX+1); Serial.println(". Zeit abgelaufen");
            servo[iX].write(80);
        }
    }
}

Möchtest Du eine 4. Stopstelle hinzufügen, musst Du nur hier:

const byte servoP[] =  {8, 9, 10};
const byte tasterP[] = {2, 3, 4};         // Hallsensoren

jeweils die Pins ergänzen, sonst nichts.

Okay :+1:

Komisch der Hallsensor funzt super direkt am Arduino aber mit 50cm Draht dazwischen nicht mehr. Habe mit
A3144 und mit KY003 probiert. Gleiches Problem.
:thinking:

Hallo zusammen
Hier noch eine Erklärung:
im Programm war der Hallkontakt als pullup, so innerlicher Widerstand und am Hallsensor zusätzlicher Widerstand. Außerdem war die Versorgungsspannung provisorisch von einem Breadboard , die habe ich dann an eine andere Trafospannung mit allem drum und dran angeschlossen. Nun geht es endgültig.
Nochmal danke an alle die mir geholfen haben.
Gruß Uwe