Servo soll von Fotozelle gestoppt werden

Hallo zusammen,

ich will mir für mein Heimkino die Leinwandmaskierung automatisieren.
Mein Plan ist das auf einen Tastendruck ein Servo die Maskierung langsam ins Bild fährt und wenn eine darauf montierte Fotozelle genug Licht erkennt soll der Servo stoppen und ein kleines Stück zurück fahren.

Ich habe schon ein paar kleinere Arduino Projekte am laufen, bin aber noch Anfänger.

Ich bräuchte in dem fall mal einen schubs in die richtige Richtung.
Mit was für einen Befehl mache ich das? eine while schleife? eine For schleife?

mfg Christoph

Gar keine Schleife, die gibt es schon.

Die Arduino-Umgebung erfordert ja, dass Du eine loop()-Funktion bereitstellst (@<wer auch immer sich angesprochen fühlt>: im Normalfall ;), ich weiß, das es auch anders geht).
Die wird immer wieder aufgerufen, sinngemäß wird der für uns nicht sichtbare Code dahinter vielleicht so aussehen:

setup()
while(1)
{
  // erledige was Geheimes
  ...
  // Rufe die Benutzerfunktion auf:
  loop();
}

In loop() prüfst Du die Taste, startest das Servo (Servo fährt), prüfst die Fotozelle, stoppst das Servo und fährst es zurück. Das läuft auf einen kleinen Zustandsautomaten hinaus, den Du in loop() implementierst.

Genug geschubst?

Hallo,
wenn du eine Sketch hast, dann lade den mal hier hoch, damit wir sehen können welche Hilfe du brauchst.
Oder brauchst du einen fertigen und geprüften Sketch, dann schicke mir einen PM :slight_smile:

Hallo Walter,

zumindest kann ich meine while schleifen versuche abbrechen.......

Ich dachte ich brauche eine Schleife um den Servo stoppen zuu können.

Mfg Christoph

Hallo
die Aufgabenstellung ist nicht komplett:
Unter welchen Bedinungen fährt der Servo wieder in die Grundstellung ?

Hallo
das IDE enthält zwei super Servo-Sketch-Beispiele.
Einfach mal ausprobieren und dann an deiner Anfoderungen erweitern.

Hallo Christoph,
okay, hier kommt der nächste Schubs - die Zustände, mit denen Du es zu tun hast:

  • Servo steht außerhalb auf Anfang
  • Servo fährt vorwärts
  • Servo fährt rückwärts
  • Servo steht
  • Servo fährt rückwärts auf Anfang (das ist die Unvollständigkeit)

Ich habe die mal nummerieren lassen - um die im Programm abzuhandeln, bietet sich ein enum an.
Was Du dann noch brauchst, sind die Bedingungen, die einen Zustandsübergang bewirken:

  • Von 1 nach 2: Tastendruck
  • Von 2 nach 3: Fotozelle wird dunkel
  • Von 3 nach 4: Fotozelle wird hell
  • Von 4 nach 5: (noch unbestimmt)
  • Nach 5 kommt dann automatisch wieder 1

Ein Zustandsautomat zeichnet sich nun dadurch aus, dass in jedem Zustand die Bedingung(en) - und nur die Bedingung - geprüft und ausgewertet werden, die für den Übergang in einen anderen Zustand relevant sind. Wenn die Bedingung erfüllt ist, erfolgt Wechsel in den nächsten Zustand, falls nicht bleibt es beim aktuellen Zustand.

Logisch geht das mit vielen if/else-Konstrukten, programmatisch ist ein switch/case vorzuziehen:

enum class Zustand {
  Anfang,
  FaehrtVorwaerts,
  ... // den Rest bekommst Du selber hin
};

Zustand z = Zustand::Anfang;

...
void loop()
{
  ...
  switch (z)
  {
  case Zustand::Anfang:
    // Taster prüfen
    if (/* Tastenzustand neu - man kann auf Druck oder Loslassen reagieren*/)
    {
      z = Zustand::FaehrtVorwaerts;
      // Servo fahren lassen
    }
    break;
  
  case Zustand::FaehrtVorwaerts:
    // Fotozelle prüfen und behandeln
    break;

  default:
    break;
  }
}

Hallo zusammen,

vielen dank für eure Bemühungen.

Meine Zustände sind:

  • Maskierung Offen (Servo auf 0°)
  • Maskierung fährt “langsam” zu (Servo fährt “langsam” auf 270°)
  • Maskierung stoppt und fährt die Lichtkante an (Servo stoppt und fährt 4° zurück)
  • Maskierung wird aufgeräumt (Servo fährt “langsam” auf 0°)

Die Bedienungen wären:

  • von 1 auf 2: Tastendruck A (Später per Infrarotbefehl.)
  • von 2 auf 3: Fotozelle überschreitet Helligkeitswert.
  • von 3 auf 4: Tastendruck B (Später per Infrarotbefehl.)
  • von 2 auf 4: wenn Servo 270° erreicht ohne das der Helligkeitswert überschritten wird.

Mein ersten beiden Probleme sind:

Wie stoppe ich den Servo?
Wie lasse ich ihn ohne for schleife langsam fahren?

In diesem Sketch funktioniert zwar der Zustandswechsel über die Fotozelle aber der Servo fährt halt auf 90°
Und der Servo fährt natürlich auch zu schnell.

#include <Servo.h>

Servo myservo;

int tasterstatus = 0;
int eingang = A0;
int sensorWert = 0;
int pos = 0;
int wink = 0;
int taster = 7;

enum class Zustand {
  Offen,
  Zufahren,
  StoppPositionieren,
  Aufraeumen,
};

Zustand z = Zustand::Offen;


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

  myservo.attach(9);
  pinMode (taster, INPUT);
  myservo.write(0);

}

void loop()
{
  sensorWert = analogRead(eingang);
  tasterstatus = digitalRead(taster);

  switch (z)
  {
    case Zustand::Offen:
      if (tasterstatus == HIGH)
      {
        z = Zustand::Zufahren;
        myservo.write(270);
      }

      break;

    case Zustand::Zufahren:
      if (sensorWert > 512 )
        myservo.write(90);
      break;



  }
}

In diesem Sketch fährt der Servo zwar langsam, aber die for schleife läuft immer durch und erst danach reagiert er auf die Fotozelle und wechselt den Zustand.
Und ich kann wieder nur auf einen festen wert fahren.
Ich dachte ich könnte die for schleife über die Fotozelle unterbrechen und im nächste zustand die Variable pos eintragen.
Etwa myservo.write(pos); und dadurch an der aktuellen Position stoppen.
Dann noch langsam 4° zurück fahren.

#include <Servo.h>

Servo myservo;

int tasterstatus = 0;
int eingang = A0;
int sensorWert = 0;
int pos = 0;
int wink = 0;
int taster = 7;

enum class Zustand {
  Offen,
  Zufahren,
  Stopp,
  Positionieren,
  Aufraeumen,
};

Zustand z = Zustand::Offen;


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

  myservo.attach(9);
  pinMode (taster, INPUT);
  myservo.write(0);

}

void loop()
{
  sensorWert = analogRead(eingang);
  tasterstatus = digitalRead(taster);

  switch (z)
  {
    case Zustand::Offen:
      if (tasterstatus == HIGH)
      {
        z = Zustand::Zufahren;

        for (pos = 0; pos <= 270; pos ++) {
          myservo.write(pos);
          delay(30);
        }
      }

      break;

    case Zustand::Zufahren:
      if (sensorWert > 512 )
        myservo.write(90);
      break;



  }
}

grindrand:
Wie stoppe ich den Servo?
Wie lasse ich ihn ohne for schleife langsam fahren?

Für sowas würde ich die MobaTools einsetzen; zum reinschnuppern: Die deutsche Doku findet sich hier (PDF).
Gibt es in der Bibliotheksverwaltung und der Autor ist hier aktiv.

Hallo Walter,

MobaTools hat funktioniert.
Der Servo fährt langsam und ich habe ihn zum stoppen gebracht.

#include <MobaTools.h>

MoToServo myservo;





int tasterstatus = 0;
int eingang = A0;
int sensorWert = 0;
int pos = 0;
int wink = 0;
int taster = 7;

enum class Zustand {
  Offen,
  Zufahren,
  StoppPositionieren,
  Aufraeumen,
};

Zustand z = Zustand::Offen;


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

  myservo.attach(9);
  myservo.setSpeed( 5 );
  pinMode (taster, INPUT);
  myservo.write(0);

}

void loop()
{
  sensorWert = analogRead(eingang);
  tasterstatus = digitalRead(taster);

  switch (z)
  {
    case Zustand::Offen:
      if (tasterstatus == HIGH)
      {
        z = Zustand::Zufahren;
        myservo.write(180);
      }

      break;

    case Zustand::Zufahren:
      if (sensorWert > 512 )
        myservo.write(myservo.readMicroseconds() );
      break;



  }
}

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.