2 Servo-Motoren ansteuern

Hallo,
ich wünsche euch allen schon einmal einen schönen Start in die neue Woche!

Zu meinem Problem:
Mit meiner Freundin baue ich gerade dieses Auge nach (nur eins davon) und alle Teile stehen. Nun brauche ich quasi nur noch den Code, um den Augapfel zu steuern und das Augenlid auf und ab zu bewegen.
Ich bin ein absoluter Anfänger, also wirklich, ich programmiere sonst überhaupt gar nicht. Ich habe jetzt nur versucht, mich ein bisschen in die Syntax einzulesen.
In meinem aktuellen Code gibt es das Problem, dass die Motoren sich zeitverzögert nacheinander bewegen. Also das Auge soll sich die ganze Zeit hin- und herbewegen und alle paar Minuten (zu Testzwecken erst einmal Sekunden) soll es mal zwinkern. Die Motoren bewegen sich also nicht wirklich zur gleichen Zeit, würde ich sagen. Im Moment jedoch zwinkert das Auge und erst lange Zeit danach bewegt es sich hin und her. Ich muss vermutlich mit Variablen oder Schleifen arbeiten, oder? Leider weiß ich noch nicht, wie ich das einbringen soll. Vielleicht kann man das auch so beschreiben: das Auge bewegt sich so lange hin und her bis es einmal zwinkert, dann erneut… usw…!

#include <Servo.h>

Servo myservo;
Servo myservo2;
void setup()
{
  myservo.attach (10);
  myservo2.attach (9);
}

void loop ()
{
 eyeball();
 eyelid();
}

void eyeball()
{
  myservo.writeMicroseconds (1500);
  delay (1000);
  
  myservo.writeMicroseconds (1000);
  delay (1000);
  
  myservo.writeMicroseconds (2000);
  delay(1000);
}

void eyelid()
{
  myservo2.writeMicroseconds (1000); //eyelid
  delay (10000);
  
  myservo2.writeMicroseconds (500); //eyelid
  delay (500);
  
  myservo2.writeMicroseconds (1000); //eyelid
  delay(1000);
}
}

Denine:
delay (1000);

delay (1000);

delay(1000);

delay (10000);

delay (500);

delay(1000);

Lerne programmieren ohne den Controller zu blockieren!

Die delay() Funktion blockiert den Controller für eine bestimmte Zeit für weitere Aktionen und schickt ihn in eine völlig sinnlose und blockierende Warteschleife, in der nichts weiter gemacht wird, als den Ablauf der Zeit abzuwarten!

Du brauchst eine eventbasierte Programmlogik, bei der dem Controller gesagt wird: Wenn die Zeit gekommen ist, um etwas zu tun, dann tue was!(Z.B. den Servosteuerwinkel um 3 Grad verstellen).

Dazu brauchst Du für die Bewegungen entweder eine Formel oder eine Nachschlagetabelle (look-up-table), aus der entweder in absoluten Zeiten seit Programmstart oder in relativen Zeiten (seit Beginn einer bestimmten Bewegung einer vorgegebenen Zeit ein bestimmter Servowinkel (oder Steuerzeit) zugeordnet wird.

Die delay()-Logik mit ständiger Blockierung des Controllers kannst Du komplett vergessen. So was ist allenfalls für völlig eindimensional ablaufende Vorgänge (mit einem einzigen Servo) noch zu realisieren.

Was Jurs damit sagen möchte:

Versuche zuerst mal das Beispiel "BlinkWithoutDelay" zu verstehen.

;)

Okay, ich hab jetzt aber nochmal mit ner for-Schleife versucht, weiterzumachen.
Ich wollte die Runden zählen und sagen, dass sobald sich der eine Motor für eyeball sich 4 Mal hin und her bewegt hat, das Auge zwinkern soll (eyelid soll sich demnach bewegen). Das passiert hier nur leider nicht. Delay ist jetzt immer noch dabei, aber ich wollte den Code noch einmal hier reinschmeißen bevor ich mich darum kümmere. Kann mir da jemand helfen?

#include <Servo.h>

Servo eyeball;         
Servo eyelid;
int pos = 0;
int pos2 = 0;
int count = 0;

void setup() { 
  eyeball.attach(10);
  eyelid.attach(9);
} 

void loop() {
  for(pos = 0; pos < 180; pos +=1){
    closeEye();
    delay(500);
    openEye();

    for(pos2 = 180; pos2 > 0; pos2 -=1){

      turnRight();
      delay(1000);
      turnLeft();
      delay(1000);

    }
  }
  if (count = 4){
    pos = 0;
    count = 0;
  }
}

void closeEye(){
  eyelid.write(180);
}

void openEye(){
  eyelid.write(0);
}

void turnRight() {
  eyeball.write(100);
}

void turnLeft() {
  eyeball.write(0);
}

Denine: Okay, ich hab jetzt aber nochmal mit ner for-Schleife versucht, weiterzumachen. Ich wollte die Runden zählen und sagen, dass sobald sich der eine Motor für eyeball sich 4 Mal hin und her bewegt hat, das Auge zwinkern soll (eyelid soll sich demnach bewegen). Das passiert hier nur leider nicht. Delay ist jetzt immer noch dabei, aber ich wollte den Code noch einmal hier reinschmeißen bevor ich mich darum kümmere. Kann mir da jemand helfen?

Also ich habe es wohl immer noch nicht verstanden: Sollen sich Bewegungen beider Servos zeitlich überlappen? Oder fahren beide Servos unabhängig für sich: Erst startet ein Servo - dann stoppt der Servo. Und nur wenn der eine Servo still steht, fährt der zweite Servo (oder der erste nochmals)?

Also 1. Bewegung Servo-1 Kopf hin Servo-1 Kopf her Servo-1 stop

  1. Bewegung Servo-1 Kopf hin Servo-1 Kopf her Servo-1 stop

  2. Bewegung Servo-1 Kopf hin Servo-1 Kopf her Servo-1 stop

  3. Bewegung Servo-1 Kopf hin Servo-1 Kopf her Servo-1 stop

  4. Bewegung Servo-2 Lid schließen Servo-2 Lid öffnen Servo-2 stop

So? Dann wäre es auch mit delay machbar (solange sonst nichts anderes "gleichzeitig" laufen soll).

Delay ist jetzt immer noch dabei, aber ich wollte den Code noch einmal hier reinschmeißen bevor ich mich darum kümmere.

Es wird nicht delay() durch millis() ersetzt., sondern das Programm grundsätzlich anders aufgebaut.

Wenn irgend etwas gleichzeitig oder überlappend passieren soll, gilt:

loop() ist nicht der Programmablauf, sondern nur die Beschreibung jedes Moments davon. loop() dauert keine Zeit und kommt unendlich oft dran.

Wie oft das Auge gezwinkert hat, merkt man sich in einer Variablen von einem Durchlauf zum nächsten, genauso seit wann etwas läuft, wenn es um Zeiten geht (hier kommt das berühmte millis() ins Spiel)

Ob du in loop alles untereinander schreibst mit delay() dazwischen oder ob du for-Schleifen verwendest: Beides ist gleich falsch.

Je früher du neu anfängst, desto einfacher.