Hilfe bei der Servo Steuerung

he ihr. ich habe berreits meinen code fertig.
ich möchte 2 servos gleichzeitig ansteuern mit einer sprachsteuerung.
funktioniert alles auch super, nur dass die servos nacheinander reagieren. ich weis der fehler liegt darran das in meinem action part die befehle so aufgeführt sind dass sie nacheinander abgearbeitet werden, aber ich weis nicht wie ich sie zeitgleich ausführen kann. kann mir da jmd helfen ? bitte^^ =(

hier mal mein code ab action:

void action()
{
    switch (group)
    {
    case GROUP_0:
      switch (idx)
      {
      case G0_JARVIS:
        // write your action code here
        group = GROUP_1;
        // group = GROUP_X; 
        break;
      }
      break;
    case GROUP_1:
      switch (idx)
      {
      case G1_HELM_AUF:
       
        for(pos = 90; pos < 180; pos += 1) 
        {                                  
          myservo.write(pos);             
          delay(40);  
        }        
        for(pos2 = 10; pos2 < 100; pos2 += 1)
        {
          myservo2.write(pos2);
          delay(40);
        } 
        
        group = GROUP_0;
        // group = GROUP_X; 
        break;
      case G1_HELM_ZU:
        // write your action code here
        for(pos = 180; pos>=90; pos-=1)     
        {                                
          myservo.write(pos);              
          delay(40);             
        }
        for(pos2 = 100; pos2>=10; pos2-=1) 
        {
          myservo2.write(pos2);
          delay(40);
        } 
        
        
        group = GROUP_0;
        // group = GROUP_X;
        break;
      }
      break;
    }
}

Naja, zeitgleich geht nicht, aber Du kannst die Servos abwechselnd je um 1° bewegen.

for (int i=0; i<90; i++) {   // Drehung um 90°
	myservo.write(pos+90);  // 1.Servo von 90°-180°
	myservo2.write(pos+10);  // 2.Servo von 10°-100°
	delay(80);
}

Dein Programm ist momentan so wie Blink aufgebaut. Du müsstest dein Programm grundsätzlich ändern, um den von dir gewünschten Effekt zu erhalten.

Die for Schleifen müssen mit den Delays raus. Dann müsstest du die Position der Servos mit Hilfe der Funktion millis() errechnen. Ziel ist es dein Programm wie das Beispiel aufzubauen: BlinkWithoutDelay

denke ich versuch erstmal suis version aus^^ danke schonmal. mal sehen obs klappt. aber wo ist bei deinem vorschlag die stelle wo se sich abwechselnd um 1° bewegen?

Hier:

myservo.write(pos+90);  // 1.Servo von 90°-180°
myservo2.write(pos+10);  // 2.Servo von 10°-100°

ok ich bin jetzt wieder zurrück zu meinem code gegangen. irgendwie konnte ich den helm nicht mehr schließen lassen mit dem vorgeschlagenem code. danke trotzdem

ich weis es ist umständlich und braucht viel speicher, aber ich habe es jetzt so gelöst, dass ich einfach die befehle wiederhole und die servos abwechseln um 1 ° bewegen lasse. bei dem vorschlag von euch schnellen die servos auf die grad zahl (ich brauche aber eine langsame gleichmäßige bewegung). am geschicktesten wäre es, wenn es ginge das so zu schreiben: Es wird eine ausgangspossition angegeben, dann wird +1! dazu addiert und die neue position ausgelesen. dannach das gleiche für den 2. servo und im anschluss das ganze wieder von anfang an wiederholen (schleife eben). am ende dann wenn eine bestimmte gradzahl erreicht ist, wird die schleife beendet. ne schleife ist leicht ich weis, aber ich scheiter heute echt an allem -.-

Ich habe mich bezüglich deiner Aufgabenstellung wohl geirrt. Ich habe angenommen, du möchtest zwei unterschiedliche Bewegungen kombinieren.

Poste doch mal deinen Sketch, indem die Servos gleich auf die Endposition fahren. Da lässt sich sicher was finden.

Wenn du ein par Euro mehr in die Hand nimmst und gleich mit digitalen Servos arbeitest, erlangst du in deinem Programm erheblich mehr Freiheiten und das Timing entspannt sich drastisch. Digitalen Servos genügen bereits 10…20 Pulse um zu “verstehen”, welche Position sie anfahren sollen. Desweiteren speichern sie diese Zielposition und wenn für eine Weile gar keine Pulse mehr kommen, halten Sie diese trotzdem und ruckeln nicht!

Du kannst also die Pulsausgabe ganz entspannt in eine Funkton packen und nahezu beliebig “selten” aufrufen … (Servonummer und Stellwert als Parameter)
Dann werden deine Servos trotdem noch nacheinander angesteuert, aber z.B. 10 ms Unterschied sind ohne Messmittel bestimmt nicht wahrnehmbar.

also zur entwirrung:
ich habe in einem helm 2 servos seitlich die die klappe des helmes bei dem kommando “helm auf” öffnen sollen.
dazu muss der eine im und der andere gegen den uhrzeigersinn drehen.
icb rauche 90 ° und habe 2 digitale servos.

hier mal mein ganzer code:
wie mann sieht habe ich sehr viel aus den beispielen einfach übernommen

#if defined(ARDUINO) && ARDUINO >= 100
  #include "Arduino.h"
  #include "SoftwareSerial.h"
  SoftwareSerial port(12,13);
#else // Arduino 0022 - use modified NewSoftSerial
  #include "WProgram.h"
  #include "NewSoftSerial.h"
  NewSoftSerial port(12,13);
#endif

#include <Servo.h>  // Eingefügter Servo
Servo myservo2;
#include <Servo.h>  // Eingefügter Servo
Servo myservo;
#include "EasyVR.h"
EasyVR easyvr(port);

int pos = 0;    // variable to store the servo position 
int pos2 = 0;
//Groups and Commands
enum Groups
{
  GROUP_0  = 0,
  GROUP_1  = 1,
};

enum Group0 
{
  G0_JARVIS = 0,
};

enum Group1 
{
  G1_HELM_AUF = 0,
  G1_HELM_ZU = 1,
};


EasyVRBridge bridge;

int8_t group, idx;

void setup()
{
  // bridge mode?
  if (bridge.check())
  {
    cli();
    bridge.loop(0, 1, 12, 13);
  }
  // run normally
  Serial.begin(9600);
  port.begin(9600);

  if (!easyvr.detect())
  {
    Serial.println("EasyVR not detected!");
    for (;;);
  }

  easyvr.setPinOutput(EasyVR::IO1, LOW);
  Serial.println("EasyVR detected!");
  easyvr.setTimeout(5);
  easyvr.setLanguage(3);

  group = EasyVR::TRIGGER; //<-- start group (customize)
  myservo2.attach(7);
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
} 
void action();

void loop()
{
  easyvr.setPinOutput(EasyVR::IO1, HIGH); // LED on (listening)

  Serial.print("Say a command in Group ");
  Serial.println(group);
  easyvr.recognizeCommand(group);

  do
  {
    // can do some processing while waiting for a spoken command
  }
  while (!easyvr.hasFinished());
  
  easyvr.setPinOutput(EasyVR::IO1, LOW); // LED off

  idx = easyvr.getWord();
  if (idx >= 0)
  {
    // built-in trigger (ROBOT)
    // group = GROUP_X; <-- jump to another group X
    return;
  }
  idx = easyvr.getCommand();
  if (idx >= 0)
  {
    // print debug message
    uint8_t train = 0;
    char name[32];
    Serial.print("Command: ");
    Serial.print(idx);
    if (easyvr.dumpCommand(group, idx, name, train))
    {
      Serial.print(" = ");
      Serial.println(name);
    }
    else
      Serial.println();
    easyvr.playSound(0, EasyVR::VOL_FULL);
    // perform some action
    action();
  }
  else // errors or timeout
  {
    if (easyvr.isTimeout())
      Serial.println("Timed out, try again...");
    int16_t err = easyvr.getError();
    if (err >= 0)
    {
      Serial.print("Error ");
      Serial.println(err, HEX);
    }
  }
}

void action()
{
    switch (group)
    {
    case GROUP_0:
      switch (idx)
      {
      case G0_JARVIS:
        // write your action code here
        group = GROUP_1;
        // group = GROUP_X; <-- or jump to another group X for composite commands
        break;
      }
      break;
    case GROUP_1:
      switch (idx)
      {
      case G1_HELM_AUF:
        // write your action code here
        for(pos = 90; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees
        {                                  // in steps of 1 degree 
          myservo.write(pos);              // tell servo to go to position in variable 'pos' 
          delay(40);  
        }        
        for(pos2 = 10; pos2 < 100; pos2 += 1)
        {
          myservo2.write(pos2);
          delay(40);
        } 
        
        group = GROUP_0;
        // group = GROUP_X; <-- or jump to another group X for composite commands
        break;
      case G1_HELM_ZU:
        // write your action code here
        for(pos = 180; pos>=90; pos-=1)     // goes from 180 degrees to 0 degrees 
        {                                
          myservo.write(pos);              // tell servo to go to position in variable 'pos' 
          delay(40);             // waits 15ms for the servo to reach the position 
        }
        for(pos2 = 100; pos2>=10; pos2-=1) 
        {
          myservo2.write(pos2);
          delay(40);
        } 
        
        
        group = GROUP_0;
        // group = GROUP_X; <-- or jump to another group X for composite commands
        break;
      }
      break;
    }
}

diverse kommentare auf deutsch und englisch und verschobene, hab ich einfach drinnen gelassen, war mir zu doof die alle rauszusuchen^^

qualidat:
Wenn du ein par Euro mehr in die Hand nimmst und gleich mit digitalen Servos arbeitest, erlangst du in deinem Programm erheblich mehr Freiheiten und das Timing entspannt sich drastisch. Digitalen Servos genügen bereits 10…20 Pulse um zu “verstehen”, welche Position sie anfahren sollen. Desweiteren speichern sie diese Zielposition und wenn für eine Weile gar keine Pulse mehr kommen, halten Sie diese trotzdem und ruckeln nicht!

Du kannst also die Pulsausgabe ganz entspannt in eine Funkton packen und nahezu beliebig “selten” aufrufen … (Servonummer und Stellwert als Parameter)
Dann werden deine Servos trotdem noch nacheinander angesteuert, aber z.B. 10 ms Unterschied sind ohne Messmittel bestimmt nicht wahrnehmbar.

oh momment mal, kann es desshalb sein dass sie ab und zu mal nen kleinen ruckler von sich geben?
dachte des sei einfach ein impuls der vom board kommt damit mann sieht das die servos den befehl bekommen.
so ein ruckeln hab ich immer dann, wenn das board irgendwas tut: also befehl erhalten, befehl fehlerhaft ausgesprochen usw.

also ich habe mir etz mal ordendliche servos zugelegt, sogar welche die sowol analog als auch digital sind also ist es egal :wink:

ich habe nur noch immer ein probleme mitm einem code. die billigen servos haben mit folgendem code funktioniert:

#if defined(ARDUINO) && ARDUINO >= 100
  #include "Arduino.h"
  #include "SoftwareSerial.h"
  SoftwareSerial port(12,13);
#else // Arduino 0022 - use modified NewSoftSerial
  #include "WProgram.h"
  #include "NewSoftSerial.h"
  NewSoftSerial port(12,13);
#endif

#include <Servo.h>  // Eingefügter Servo
Servo myservo2;
#include <Servo.h>  // Eingefügter Servo
Servo myservo;
#include "EasyVR.h"
EasyVR easyvr(port);

int pos = 0;    // variable to store the servo position 
int pos2 = 60;
//Groups and Commands
enum Groups
{
  GROUP_0  = 0,
  GROUP_1  = 1,
};

enum Group0 
{
  G0_JARVIS = 0,
};

enum Group1 
{
  G1_HELM_AUF = 0,
  G1_HELM_ZU = 1,
};


EasyVRBridge bridge;

int8_t group, idx;

void setup()
{
  // bridge mode?
  if (bridge.check())
  {
    cli();
    bridge.loop(0, 1, 12, 13);
  }
  // run normally
  Serial.begin(9600);
  port.begin(9600);

  if (!easyvr.detect())
  {
    Serial.println("EasyVR not detected!");
    for (;;);
  }

  easyvr.setPinOutput(EasyVR::IO1, LOW);
  Serial.println("EasyVR detected!");
  easyvr.setTimeout(5);
  easyvr.setLanguage(3);

  group = EasyVR::TRIGGER; //<-- start group (customize)
  myservo2.attach(7);
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
} 
void action();

void loop()
{
  easyvr.setPinOutput(EasyVR::IO1, HIGH); // LED on (listening)

  Serial.print("Say a command in Group ");
  Serial.println(group);
  easyvr.recognizeCommand(group);

  do
  {
    // can do some processing while waiting for a spoken command
  }
  while (!easyvr.hasFinished());
  
  easyvr.setPinOutput(EasyVR::IO1, LOW); // LED off

  idx = easyvr.getWord();
  if (idx >= 0)
  {
    // built-in trigger (ROBOT)
    // group = GROUP_X; <-- jump to another group X
    return;
  }
  idx = easyvr.getCommand();
  if (idx >= 0)
  {
    // print debug message
    uint8_t train = 0;
    char name[32];
    Serial.print("Command: ");
    Serial.print(idx);
    if (easyvr.dumpCommand(group, idx, name, train))
    {
      Serial.print(" = ");
      Serial.println(name);
    }
    else
      Serial.println();
    easyvr.playSound(0, EasyVR::VOL_FULL);
    // perform some action
    action();
  }
  else // errors or timeout
  {
    if (easyvr.isTimeout())
      Serial.println("Timed out, try again...");
    int16_t err = easyvr.getError();
    if (err >= 0)
    {
      Serial.print("Error ");
      Serial.println(err, HEX);
    }
  }
}

void action()
{
    switch (group)
    {
    case GROUP_0:
      switch (idx)
      {
      case G0_JARVIS:
        // write your action code here
        group = GROUP_1;
        // group = GROUP_X; <-- or jump to another group X for composite commands
        break;
      }
      break;
    case GROUP_1:
      switch (idx)
      {
      case G1_HELM_AUF:
        // write your action code here
        {
          myservo.write(pos+60);  // 1.Servo von 90°-180°
          myservo2.write(pos2-60);  // 2.Servo von 10°-100°
          
        } 
        
        // HELM ZU !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        
        group = GROUP_0;
        // group = GROUP_X; <-- or jump to another group X for composite commands
        break;
      case G1_HELM_ZU:
        // write your action code here
          myservo.write(pos);  // 1.Servo von 90°-180°
          myservo2.write(pos2);  // 2.Servo von 10°-100°
        
        group = GROUP_0;
        // group = GROUP_X; <-- or jump to another group X for composite commands
        break;
      }
      break;
    }
}

die neuen zicken da aber rumm, funktionieren allerdings mit dem alten code:
hier nur der action berreich:

case G1_HELM_AUF:
        // write your action code here
        for(pos = 90; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees
        {                                  // in steps of 1 degree 
          myservo.write(pos);              // tell servo to go to position in variable 'pos' 
          delay(40);  
        }        
        for(pos2 = 10; pos2 < 100; pos2 += 1)
        {
          myservo2.write(pos2);
          delay(40);
        } 
        
        group = GROUP_0;
        // group = GROUP_X; <-- or jump to another group X for composite commands
        break;
      case G1_HELM_ZU:
        // write your action code here
        for(pos = 180; pos>=90; pos-=1)     // goes from 180 degrees to 0 degrees 
        {                                
          myservo.write(pos);              // tell servo to go to position in variable 'pos' 
          delay(40);             // waits 15ms for the servo to reach the position 
        }
        for(pos2 = 100; pos2>=10; pos2-=1) 
        {
          myservo2.write(pos2);
          delay(40);
        }

beid dem letzten code wird ja leider jeder servo einzelt angesteuert und sie bewegen sich nacheinander.
ich brauche es ja aber dass beide gleichzeitig drehen (was mit dem ersten code nicht funktioniert.

ich dneke ich sollte es einfach sein lassen. in einer woche muss ich fertig sein und nichts funktioniert, selbst nach mehrfachem nachlesen in allen möglichen anleitungen

wie wäre es einfach statt mit:

for(pos = 90; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees
        {                                  // in steps of 1 degree 
          myservo.write(pos);              // tell servo to go to position in variable 'pos' 
          delay(40);  
        }        
        for(pos2 = 10; pos2 < 100; pos2 += 1)
        {
          myservo2.write(pos2);
          delay(40);
        }

mit

for(pos = 90; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees
        {                                  // in steps of 1 degree 
          myservo.write(pos);              // tell servo to go to position in variable 'pos' 
          myservo2.write((pos - 80));
          delay(40);  
        }

dann zählt die pos von 90 bis 180 und der zweite server bekommt die werte mit jeweils -80 serviert, zählt also von 10 bis 100.
Mario.

danke, werd ich gleich mal ausprobieren, denke die neuen servos kann ich eh vergessen. die verändern ständig ihre posi von alleine

schade funktioniert nicht. der servo1 läuft wie er soll, aber der 2. servo läuft immer in die falsche richtung und nach dem helm zu befehl geht er nach der bewegung automatisch wieder in die grundstellung.

ich habe jetzt mal das beispiel von Arduino genommen (das Sweep servo beispiel)
also:

// Sweep
// by BARRAGAN <http://barraganstudio.com> 
// This example code is in the public domain.


#include <Servo.h> 
 
Servo myservo;  // create servo object to control a servo 
                // a maximum of eight servo objects can be created 
 
int pos = 0;    // variable to store the servo position 
 
void setup() 
{ 
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
} 
 
 
void loop() 
{ 
  for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(15);                       // waits 15ms for the servo to reach the position 
  } 
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees 
  {                                
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(15);                       // waits 15ms for the servo to reach the position 
  } 
}

und hab mir die befehler rausgenommen.
sieht dann so aus:

#if defined(ARDUINO) && ARDUINO >= 100
  #include "Arduino.h"
  #include "SoftwareSerial.h"
  SoftwareSerial port(12,13);
#else // Arduino 0022 - use modified NewSoftSerial
  #include "WProgram.h"
  #include "NewSoftSerial.h"
  NewSoftSerial port(12,13);
#endif

#include <Servo.h>  // Eingefügter Servo
Servo myservo;
#include <Servo.h>  // Eingefügter Servo
Servo myservo2;
#include "EasyVR.h"
EasyVR easyvr(port);

int pos = 0;    // variable to store the servo position 
int pos2 = 0;
//Groups and Commands
enum Groups
{
  GROUP_0  = 0,
  GROUP_1  = 1,
};

enum Group0 
{
  G0_JARVIS = 0,
};

enum Group1 
{
  G1_HELM_AUF = 0,
  G1_HELM_ZU = 1,
};


EasyVRBridge bridge;

int8_t group, idx;

void setup()
{
  // bridge mode?
  if (bridge.check())
  {
    cli();
    bridge.loop(0, 1, 12, 13);
  }
  // run normally
  Serial.begin(9600);
  port.begin(9600);

  if (!easyvr.detect())
  {
    Serial.println("EasyVR not detected!");
    for (;;);
  }

  easyvr.setPinOutput(EasyVR::IO1, LOW);
  Serial.println("EasyVR detected!");
  easyvr.setTimeout(5);
  easyvr.setLanguage(3);

  group = EasyVR::TRIGGER; //<-- start group (customize)
  myservo.attach(9);
  myservo2.attach(7);  // attaches the servo on pin 9 to the servo object 
} 
void action();

void loop()
{
  easyvr.setPinOutput(EasyVR::IO1, HIGH); // LED on (listening)

  Serial.print("Say a command in Group ");
  Serial.println(group);
  easyvr.recognizeCommand(group);

  do
  {
    // can do some processing while waiting for a spoken command
  }
  while (!easyvr.hasFinished());
  
  easyvr.setPinOutput(EasyVR::IO1, LOW); // LED off

  idx = easyvr.getWord();
  if (idx >= 0)
  {
    // built-in trigger (ROBOT)
    // group = GROUP_X; <-- jump to another group X
    return;
  }
  idx = easyvr.getCommand();
  if (idx >= 0)
  {
    // print debug message
    uint8_t train = 0;
    char name[32];
    Serial.print("Command: ");
    Serial.print(idx);
    if (easyvr.dumpCommand(group, idx, name, train))
    {
      Serial.print(" = ");
      Serial.println(name);
    }
    else
      Serial.println();
    easyvr.playSound(0, EasyVR::VOL_FULL);
    // perform some action
    action();
  }
  else // errors or timeout
  {
    if (easyvr.isTimeout())
      Serial.println("Timed out, try again...");
    int16_t err = easyvr.getError();
    if (err >= 0)
    {
      Serial.print("Error ");
      Serial.println(err, HEX);
    }
  }
}

void action()
{
    switch (group)
    {
    case GROUP_0:
      switch (idx)
      {
      case G0_JARVIS:
        // write your action code here
        group = GROUP_1;
        // group = GROUP_X; <-- or jump to another group X for composite commands
        break;
      }
      break;
    case GROUP_1:
      switch (idx)
      {
      case G1_HELM_AUF:
        // write your action code here
        {
           for(pos = 0; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees 
          {                                  // in steps of 1 degree 
            myservo.write(pos);
            myservo2.write(pos-80);            // tell servo to go to position in variable 'pos' 
            delay(15);                       // waits 15ms for the servo to reach the position 
          } 
          
        } 
        
        group = GROUP_0;
        // group = GROUP_X; <-- or jump to another group X for composite commands
        break;
      case G1_HELM_ZU:
        // write your action code here
          for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees 
          {                                
            myservo.write(pos);              // tell servo to go to position in variable 'pos' 
            delay(15);                       // waits 15ms for the servo to reach the position 
          } 
        
        group = GROUP_0;
        // group = GROUP_X; <-- or jump to another group X for composite commands
        break;
      }
      break;
    }
}

da es mit 2 servos nciht klappt, nehm ich einen starken servo und hoffe dass mein gestell sich nciht verbiegt wenn es nur von einer seite angehoben wird.

leider hatt sich jetzt ein neues problem aufgetan.
nachdem ich einmal beide befehle gegeben habe, fängt der servo sich auf einmal an von selber ab und zu in irgend eine position zu bewegen.
spukt es in meinem servo?