Solved: Servo Zittern in Verbindung mit anderen Librarys

guntherb:

jurs:
Welche Library meinst Du?

interessante Frage!

Ich habe die Servo-lib die in der IDE mitgeliefert wurde;
die hier: Servo - Arduino Reference

mir scheint, die im Playground ist älter.
aber der Gedanke ist grundsätzlich richtig, ich könnte ja mal nach anderen Servo.lib suchen und die probieren.
Oder vielleicht doch die Versorgung abschalten....

Meine loop() läuft ohne delays.
Im Schnitt habe ich 400µs Loop wiederholrate, wenn eine der Zeitscheiben aufgerufen wird, können das aber auch 6-8ms werden.
Bei besonders Zeitaufwändigen Aktionen, wie z.B. wenn das Display komplett neu geschrieben wird, oder die SD-Karte gesteckt wird, können es auch mal 30ms sein. Aber das sind nicht die Zustände, die mir Probleme machen.
Im Normalbetrieb läuft die loop() mit maximal 8ms und auch da zittern die Servos. (Übrigens nicht immer beide gleichzeitig, mal das eine, mal das andere!)

Du musst nicht die Versorgung abschalten. Nur detach reicht.

guntherb:
Ich habe die Servo-lib die in der IDE mitgeliefert wurde;
die hier: Servo - Arduino Reference

Ah, moderne Zeiten, mitgelieferte Servo-Library!

Ja, die basiert auf Interrupts. Frißt Interrupt-Zeitscheiben weg, frißt PWM-Pins weg und begrenzt die maximal ansteuerbare Servoanzahl. Irgendwie ist nicht alles besser was neuer ist.

Jedenfalls Servo-Interrupts beißen sich in dem Fall mindestens mit Serial-Interrupts, wenn Du z.B. Debug-Ausgaben auf Serial sendest. Das kann ggf. das exakte Timing nachteilig beeinflussen, wenn z.B. noch ungesendete Zeichen im seriellen Sendepuffer sind während dann der interruptgesteuerte automatische Servo-Refresh zuschlägt. Dann kann (Serial-)Interrupt auf (Servo-)Interrupt treffen und ein Interrupt muss warten, bis der andere beendet ist, bevor er zum Zuge kommt.

Eine Möglichkeit wäre, Serial auf einer anderen, höheren Baudrate laufen zu lassen.
Wenn Du Serial jetzt auf 9600 laufen hast, z.B. mal Serial auf 115200 ausprobieren.
Änderung?

Die andere Sache ist die: Bei so einem Regler brauchst Du Serial doch nur für Debug-Ausgaben während der Programmentwicklung, oder und sonst für nichts anderes? Dann wäre eine andere Möglichkeit, per bedingter Kompilierung den Quellcode zur Kompilierung von zwei verschiedenen Versionen vorzusehen:

  • Debug-Version zur Programmentwicklung mit Debug-Ausgaben auf Serial.
  • Final-Version zum Einsetzen ohne Serial
    Weißt Du, wie Du "bedingte Kompilierung" nutzen kannst, um komfortabel dieselbe Quellcodeversion zu nutzen? Also um aus demselben Quellcode einen Sketch mit Serial-Debugausgaben und einen Sketch ohne Serial-Ausgaben erzeugen zu können?

guntherb:
mir scheint, die im Playground ist älter.

Älter muß nicht in jedem Fall schlechter sein. Die ältere Version knabbert z.B. keine PWM-Pins weg und ist auch in der Servoanzahl nicht limitiert.

guntherb:
Meine loop() läuft ohne delays.
Im Schnitt habe ich 400µs Loop wiederholrate, wenn eine der Zeitscheiben aufgerufen wird, können das aber auch 6-8ms werden.
Bei besonders Zeitaufwändigen Aktionen, wie z.B. wenn das Display komplett neu geschrieben wird, oder die SD-Karte gesteckt wird, können es auch mal 30ms sein. Aber das sind nicht die Zustände, die mir Probleme machen.

Das hört sich völlig einwandfrei für die Nutzung der alten Servo-Library an. Die refresh-Aufrufe sollen regelmäßig in Abständen von max. 20 ms erfolgen und höchstens 50 ms nicht überschreiten.

Vielleicht würde ich das mit den Änderungen an "Serial" (höhere Baudrate, Debug- und Final-Version) zuerst ausprobieren, damit Du die mitgelieferte Servo-Lib ggf. weiternutzen kannst. So ganz ohne Not braucht man auf mitgelieferte Libs ja vielleicht auch nicht verzichten.

Hallo Jurs,

das mit der bedingten Compilierung ist mir im Prinzip klar, habs aber beim Arduino noch nie verwendet.
ich kommentiere einfach das Serial.begin() im Setup aus, dann ist es ende mit Serial Monitor. :blush:

ich lasse den Smon auf 57600baud laufen, 115k sind mit USB-HUB nicht sicher.

aber der wichtigste Hinweis ist dein Tip mit der alten Servolib. Ich denke, ich werde die mal einbauen und testen, das klingt vielversprechend! :wink:

mde110:
Du musst nicht die Versorgung abschalten. Nur detach reicht.

Nein, reicht leider nicht.
Wenn, dann nur, falls man detach irgendwie mit dem Servosignal synchronisieren könnte. Wenn ich detach mache, dann dreht das Servo immer wieder mal im Abschalten ein Stückchen weg. Schon probiert.

Und wenn du den Pin manuell auf OUTPUT LOW schaltest?
Bei mir ging das detach immer super... komisch.

mde110:
Und wenn du den Pin manuell auf OUTPUT LOW schaltest?
Bei mir ging das detach immer super... komisch.

auch schon probiert - hilft nicht.
mir scheint, dass es zeitliche Zusammenhänge gibt.
Beim detach hatte eigentlich immer nur das Servo an einem Ausgang gelegentliches Zucken der andere nie. (Servos wurden getauscht, Effekt blieb am Ausgang)
Da ich aber keine eindeutige Zusammenhänge erkennen konnte (ich habe vieles probiert!) und die Gefahr bestand, dass bei einer Änderung in der Software an anderer Stelle das System sich wieder anders verhält, habe das mit dem detach verworfen.

Ja, da kann man schon verzweifeln.
Ich hab bei meiner Lib auch diverse Probleme gehabt. (rcarduin.tk)
Eine generelle Lösung gibt es leider nicht. Man muss schauen woher die Störungen kommen. Eigentlich ist die neue Lib schon gut. Durch die Interruptsteuerung ist die nicht mehr so anfällig gegen Störungen z.B. von der SD Lib. (Da kommt es manchmal ja zu Latenzen im 100ms Bereich.) Für den ATTinyx5 mußte ich eine komplett eigene Lib schreiben, weil die SoftwareServo nicht mit meiner Lib zum Auslesen von Fernsteuerempfängern harmonierte. (eigentlich mit keiner Lib, die auf den Systemtimer zugreift.)
Schau mal genau, welche Lib die Probleme macht. Einfach mit Bedingter Compilierung die entsprechenden Bibliotheken auskommentieren, (Die Codeteile, die die verwenden natürlich auch :-)) und schauen, bei welcher Lib das Zittern ein Ende hat.
Abschalten ist übrigens keine Lösung. Denn der Servo ist dann stromlos und kann nicht mehr gegen evt. äußere Änderungen gegenhalten. (Dafür ist er ja auch da)

Ich habe die "alte" Servolib nicht zu laufen gebracht.
Auch nachdem ich in der Lib das #include <arduino.h> eingefügt hatte, was zum compilieren nötig war, ging einfach nix.
Auch das Beispiel lief nicht.

ok. Alle Libs rausschmeissen um den "Störenfried" zu finden wäre evt eine Lösung, aber dann eine neue, eigene Lib schreiben, das geht definitiv über meine Kenntnisse. (und, ehrlich gesagt, fehlt mir auch die Lust dazu)

willie1968:
Abschalten ist übrigens keine Lösung. Denn der Servo ist dann stromlos und kann nicht mehr gegen evt. äußere Änderungen gegenhalten. (Dafür ist er ja auch da)

In meinem Spezielle Anwendungsfall ist das kein Problem.
Wie eingangs erwähnt, betätigen die Servos Lüftungsschieber eines Grills. Die haben keine Rückstellkräfte.
Auch ist das System so langsam, dass es reicht, wenn ich alle paar Sekunden mal prüfe, ob sicher das Stellsignal überhaupt geändert hat, und dann ggf für eine Sekunde die Spannung einschalte und die Servos stelle.

Ich habe mir jetzt mal ein paar P-Kanal Mosfet bestellt um die Versorgung der Servos zu schalten. Ich werde berichten.

guntherb:
Ich habe die "alte" Servolib nicht zu laufen gebracht.

Die Lib wird wohl auch nur laufen, wenn Du die in der Arduino-Installation vorhandene Servo-Lib von der Platte putzt, denn da bestehen Namensgleichheiten bei Dateinamen, Objekten und Funktionen und damit kommt der Compiler bestimmt nicht klar, dass er trotz gleicher Dateinamen die Lib einbindet, die Dir gerade vorschwebt.

Ich frage mich, wozu man überhaupt eine Library braucht, wenn nur ein bis zwei Servos anzusteuern sind. Da reicht doch eine simple Funktion mit delayMicroseconds() drin, die man regelmäßig von der loop aus aufruft und die folgendes macht:

  • falls weniger als 20 ms seit dem letzten Servo-Refresh vergangen sind => Ende der Funktion
  • falls mindestens 20 ms vergangen sind ==> Impuls ans Servo
    Dabei wird ein Winkel von 0 bis 180 auf eine Impulsdauer von 1500 bis 2000 Mikrosekunden umgerechnet.

Bei Dir sind von der Anzahl her zwei Servos anzusteuern, oder?
Das schreibe ich so runter.
Weißt Du zufällit, ob der Servo-Pegel normalerweise LOW ist und der Impuls HIGH, oder ob es umgekehrt ist? Sonst schaue ich mal in einer vorhandenen Servo-Lib nach.

jurs:
Das schreibe ich so runter.

Das ist nicht nötig, aber vielen Dank fürs Angebot! :*

Die Idee an sich ist nicht schlecht, und das ist etwas, was ich auch hinkriege.
das werde ich mal ausprobieren, wenn ich mal Zeit habe!

guntherb:
Die Idee an sich ist nicht schlecht, und das ist etwas, was ich auch hinkriege.
das werde ich mal ausprobieren, wenn ich mal Zeit habe!

Falls jemand zwei Servos hat und Lust zu testen, anbei mein Code für einen 2-Servo Test-Sketch:

// Two-Servo-Test by 'jurs' for German Arduino Forum
// Code is UNTESTED - Please feel free to test by yourself!

#define SERVO1PIN  4    // Ein Servo an D4
#define SERVO2PIN  5    // Ein Servo an D5
#define MINPULSE 1000   // Minimale Impulslänge bei Linksausschlag
#define MAXPULSE 2000   // Maximale Impulslänge bei Rechtsausschlag

void twoServoRefresh(byte pin1, byte angle1, byte pin2, byte angle2)
{
  static unsigned long lastRefresh=0;
  if (millis()-lastRefresh<20) return; // noch keine 20 ms vergangen
  lastRefresh=millis(); // Zeit des erfolgten Refresh merken
  if (angle1>180) angle1=180; // Stellwinkel bis 180 Grad erlaubt
  if (angle2>180) angle2=180;
  int pulselen1 = MINPULSE + (MAXPULSE-MINPULSE)*(long)angle1/180;
  int pulselen2 = MINPULSE + (MAXPULSE-MINPULSE)*(long)angle2/180;
//  noInterrupts();
  digitalWrite(pin1,HIGH); // Beide Refresh-Impulse "gleichzeitig" starten
  digitalWrite(pin2,HIGH); // Beide Refresh-Impulse "gleichzeitig" starten
  if (pulselen1<pulselen2) // der erste Refresh-Impuls ist der kürzere
  {
    delayMicroseconds(pulselen1);
    digitalWrite(pin1,LOW);
    delayMicroseconds(pulselen2-pulselen1);
    digitalWrite(pin2,LOW);
  }
  else  // der zweite Refresh-Impuls ist der kürzere oder gleichlang
  {
    delayMicroseconds(pulselen2);
    digitalWrite(pin2,LOW);
    delayMicroseconds(pulselen1-pulselen2);
    digitalWrite(pin1,LOW);
  }
//  interrupts();  
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(SERVO1PIN,OUTPUT);
  pinMode(SERVO2PIN,OUTPUT);
}


void loop() {
 int servo1angle, servo2angle;
 if ((millis()/10000)%2==0) // Immer je 10 Sekunden lang
 {
   servo1angle=45;
   servo2angle=135;
 }
 else   // nach 10 Sekunden Servoposition wechseln
 {
   servo1angle=135;
   servo2angle=45;
 }
 twoServoRefresh(SERVO1PIN, servo1angle, SERVO2PIN, servo2angle);
}

Der Code ist vollkommen ungetestet, da ich keine Servos hier habe.
Die Grundlagen zur Servoansteuerung habe ich diesem Wikipedia-Artikel entnommen:

und entsprechend eingebaut:

  • Normalpegel ist LOW, Impulse sind HIGH
  • Mikrosekundengenaues Timing zwischen 1000 ?s (Linksausschlag) und 2000 ?s (Rechtsausschlag)
  • Aufruf alle ca. 20 Millisekunden, aber es kommt nicht so genau darauf an (daher Aufruf aus der loop)

Falls die Servos immer noch Zittern (ggf. in anderen Sketchen, die I2C-Hardware und anderes ansteuern), einfach mal die Kommentarstriche bei "noInterrupts" und "interrupts" entfernen für eine noch exaktere Einhaltung des Timings.

Irgendwo muss ich mal in meinen alten Sachen rumkramen, da hatte ich vor etlichen Jahren Modellbauartikel verpackt und es müßten auch Servos dabei sein.

Würde mich ja selbst mal interessieren, wie das funktioniert.

Hoi jurs,

hab's getestet mit 2 Billig-Servos aus der Bucht (diese durchsichtigen hellblauen Plastikteile) sowie in Kombi mit einem "richtigen" Servo 8)
Läuft tadellos ohne Zittern & Zagen - TopJob :smiley:

Ich bin mit meinem Servogelumpe auch noch nicht wirklich weiter.
Habs aus Frust erst mal ans Ende der ToDo-Liste gestellt.
Ich gehe nach wie vor (bei mir) davon aus, das sich da irgendwas intern im Mega "beharkt".
Allerdings wird bei mir mit externem Interrupt getaktet - scheint das Hauptprob zu sein ......

Hier würde ich das auch vermuten.
Eine andere Sache ist: Verwendet man Standard-Servos, muss die Wiederholfrequenz ziemlich genau 20ms sein.
Geht man darüber hinaus, bekommen manche Servo's auch das große Zittern, bzw. werden sehr ungenau im Stellbreich und ruckeln.

Ich würde mal hier einfach solo mit der Servo-Lib anfangen und nen Poti als Steller verwenden.
Dann sukzessive die weiteren Libs und Funktionen einbinden, bis sich der Störenfried zu erkennen gibt.

jurs:
Falls jemand zwei Servos hat und Lust zu testen, anbei mein Code für einen 2-Servo Test-Sketch:

Hallo Jurs,
deine Lösung ist wie immer viel eleganter!
Trotzdem eine Frage:
Warum die beiden Pulse gleichzeitig, warum nicht nacheinander?

Den Code funktioniert (standalone) toll, aber wenn beide Servos den gleichen Winkel stellen sollen, dann geht eines der Servos auf Block.
Wenn ich den Ausgabeteil einfach seriell schreibe, dann gehts:

//  noInterrupts();
  digitalWrite(pin1,HIGH); // ersten Refresh-Impuls  starten
  delayMicroseconds(pulselen1);
  digitalWrite(pin1,LOW);
  digitalWrite(pin2,HIGH); // zweiten Refresh-Impuls  starten
  delayMicroseconds(pulselen2);
  digitalWrite(pin2,LOW);
//  interrupts();

Ich habe übrigens auch die Empfindlichkeit meiner (digitalen) Servos auf die Einhaltung der 20ms getestet: kein Problem!
Selbst ein "Refresh" mit mehr als 100ms Abstand macht das Servo zwar langsamer, aber es funktioniert.

guntherb:
Trotzdem eine Frage:
Warum die beiden Pulse gleichzeitig, warum nicht nacheinander?

Geschwindigkeit ist keine Hexerei:
Wenn beide Servos Ihren Refresh-Impuls zur selben Zeit starten, und der eine beendet seinen Impuls früher und der andere etwas später, dann brauchen zwei Servos für die Ausführung der Funktion immer genau so lange wie ein Servo: Maximal 2 Millisekunden.

Wenn man die Refresh-Impulse nacheinander sendet, dann brauchen 2 Servos zusammen bis zu 4 Millisekunden, also doppelt so lange.

Die Ansteuerung soll ja auch ein bisschen effektiv sein. Im Endeffekt kann ich eine Ansteuerung für 15 oder 30 Servos schreiben und die Funktion braucht immer nur: maximal 2 Millisekunden für den Refresh-Impuls, egal wie viele Servos. Aber damit das klappt, müssen sie eben gleichzeitig mit dem Refresh-Impuls anfangen, und dann nacheinander abschalten, je weiter nach links der Servo gedreht ist, desto früher beendet er seinen Impuls und die anderen Servos dann nach und nach je nach Drehwinkel, bis der mit dem längsten Refresh-Impuls als letzter fertig wird, aber auch innerhalb von 2 Millisekunden.

Ich weiß, für ein lahmes Temperaturregelungsprogramm mit nur zwei Servos ist das völlig irrelevant.
Aber es gibt auch Anwendungen, da sind 2 Millisekunden viel Zeit, die man nicht mal eben alle 20ms verschenken möchte.

guntherb:
Den Code funktioniert (standalone) toll, aber wenn beide Servos den gleichen Winkel stellen sollen, dann geht eines der Servos auf Block.

Hm, dann funktioniert entweder die Funktion delayMicroseconds() mit dem Parameter "0" nicht richtig.
Oder Deine Servos haben ein deutliches Problem mit der Stromversorgung, wenn beide Servomotoren in exakt derselben Mikrosekunde starten sollen. Bei Gleichstrommotoren ist es ja so: Der Anlaufstrom ist am höchsten. Die Stromaufnahme beim drehenden Motor ist geringer als beim Anlaufen im Moment des Einschaltens.

Vielleicht blockiert ein Motor, weil er zum Anlaufen nicht genug Strom erhält?

Ich habe bei mir auf dem Dachboden inzwischen einen einzelnen Servo wiedergefunden: Einen Graupner C601 von ca. 1980, und mit dem habe ich einige Tests gemacht. Ich teste aber nochmal weiter und schreibe dann nochmal etwas dazu.

Wie gesagt: Prüfe mal die Servo-Stromversorgung! Bei diesen Servos können kleinste Spannungsschwankungen zum Zittern führen und die Servos ziehen kräftig Strom!

Als Fehlerquelle beim Zittern kommen Interrupts und Spannungsschwankungen in Frage. Vielleicht hast Du neben den Servos auch noch andere Bauteile in der Schaltung, die schwankenden Strom ziehen?

Ich habe ehrlich gesagt das I2C-Display im Verdacht, dass das Spnnungsswankungen verursacht, wenn es angesteuert wird. Ich versorge meinen Servo momentan auf dem 5V Pin auf dem Arduino. Selbst wenn ich die Refresh-Impulse zwischen "noInterrupts()" und "interrupts()" packe, scheint das bei der Aktualisierung des Displays einen kleinen und mit der Fingerkuppe spürbaren "Zupp" zu geben. Und das kann eigentlich gar nicht sein.

guntherb:
Ich habe übrigens auch die Empfindlichkeit meiner (digitalen) Servos auf die Einhaltung der 20ms getestet: kein Problem!
Selbst ein "Refresh" mit mehr als 100ms Abstand macht das Servo zwar langsamer, aber es funktioniert.

Das ist schön. Mein Graupner "Vintage" Servo von 1980 zeigt folgendes Verhalten: Offenbar erfolgt das Nachstellen der Servoposition immer nur eine ganz kurze Zeit nach einem Refresh-Impuls. Möglicherweise immer genau die 20 ms lang, bis der nächste Refresh-Impuls kommen sollte. Wenn ich bei diesem Servo mal eine Refresh-Zeit von 500 ms statt 20 ms einstelle, dann kannst Du beim Verstellen die Refresh-Impulse mitzählen: Der Servo braucht dann von 45 auf 135 Grad insgesamt 7 Refresh "Ticks" und läuft sieben mal ein ganz kleines Stück, bis er den gesamten Verstellweg zurückgelegt hat. D.h. den Verstellweg, den der Servo bei 20ms Refresh in weniger als 0,2s zurücklegt, legt er dann in 3,5s zurück. Zwischendurch ist er dann immer im Zustand "nicht angesteuert" und läßt sich leicht von der Sollposition wegdrücken. Aber im Endeffekt: Der Servo erreicht mit beliebig langen Refresh-Zeiten immer auch seine Sollposition, auch wenn es dann sehr lange dauern kann.

Wie gesagt, ich betreibe wegen des Zitterns und seiner möglichen Gründe nochmal ein bisschen Ursachenforschung.

Wie jurs schrieb; sollte die Spannungsversorgung nicht stabil bzw. stabilsiert sein (vom Board (wegen zuviel Last) oder mit Netzteil) dann Zittern die Servos ebenfalls.
Sollte das Fall sein, einfach einen Spannungsstabilisator z.B. 7807 oder 7809 oder 7812 vorschalten.

Hallo Jurs,

vielen Dank für deine Mühe!

Die Versogungsspannung ist ok. Die Servos werden aus einer externen 6V-Quelle gespeist, die mit kurzem Kabel mit NiMh-Akkus gepuffert ist. Das ist ok. (Hardware kann ich, nur mit der Software haperts!)

Bei den verlängerten Pausen zeigen meine Servos genau das Verhalten das du auch beschrieben hast: bei jedem Puls schiebt sich das Servo in die richtige Richtung, bis es irgendwann da ist. Für Anwendungen die Rückstellkräfte haben untauglich, für mich kein Problem.

Nochmal zum Verhalten bei gleichen Winkeln:
Wenn ich beide Servos mit gleichem Winkel ansteuere, dann wird Servo2 auf den richtigen Winkel gestellt, Servo1 aber geht auf Vollauschlag (>180°) und knurrt.

Deine Vermutung mit dem delayMicroseconds(0) scheint richtig zu sein.
Wenn ich bei Pulslängengleichheit den einen 1µs länger mache, funktionierts:

void twoServoRefresh(byte pin1, byte angle1, byte pin2, byte angle2)
{
  static unsigned long lastRefresh=0;
  if (millis()-lastRefresh<20) return; // noch keine 20 ms vergangen
  lastRefresh=millis(); // Zeit des erfolgten Refresh merken
  
  if (angle1>180) angle1=180; // Stellwinkel bis 180 Grad erlaubt
  if (angle2>180) angle2=180;
  int pulselen1 = MINPULSE + (MAXPULSE-MINPULSE)*(long)angle1/180;
  int pulselen2 = MINPULSE + (MAXPULSE-MINPULSE)*(long)angle2/180;
  int pulslendiff = pulselen1-pulselen2;
  if (pulslendiff == 0) pulslendiff = 1;
//  noInterrupts();
  digitalWrite(pin1,HIGH); // Beide Refresh-Impulse "gleichzeitig" starten
  digitalWrite(pin2,HIGH); // Beide Refresh-Impulse "gleichzeitig" starten
  if (pulselen1<pulselen2) // der erste Refresh-Impuls ist der kürzere
  {
    delayMicroseconds(pulselen1);
    digitalWrite(pin1,LOW);
    delayMicroseconds(pulselen2-pulselen1);
    digitalWrite(pin2,LOW);
  }
  else  // der zweite Refresh-Impuls ist der kürzere oder gleichlang
  {
    delayMicroseconds(pulselen2);
    digitalWrite(pin2,LOW);
    delayMicroseconds(pulslendiff);
    digitalWrite(pin1,LOW);
  }
//  interrupts();  
}

Jetzt werde ich mich mal dranmachen, und die Funkion in meinen gesamtcode mit einzubauen. Bin schon gespannt.

guntherb:
Die Versogungsspannung ist ok. Die Servos werden aus einer externen 6V-Quelle gespeist, die mit kurzem Kabel mit NiMh-Akkus gepuffert ist. Das ist ok.

Was ich inzwischen noch herausgefunden habe: Senden auf der seriellen Schnittstelle scheint keine negativen Effekte zu haben (getestet bei 9600 Baud), aber das Empfangen von Zeichen auf Serial erzeugt einen kleinen "Zupp" am Servo, wenn Zeichen eintreffen. Den kann man dann mit der Aktivierung von "noInterrupts()" und "interrupts()" zwar vermeiden (dann herrscht wieder Ruhe), aber dadurch dürften beim Empfang auf Serial Zeichen verlorengehen.

guntherb:
Bei den verlängerten Pausen zeigen meine Servos genau das Verhalten das du auch beschrieben hast: bei jedem Puls schiebt sich das Servo in die richtige Richtung, bis es irgendwann da ist. Für Anwendungen die Rückstellkräfte haben untauglich, für mich kein Problem.

Und plötzlich kann man Dinge testen und ausprobieren, mit denen einen die Servo-Library gar nicht experimentieren läßt.

guntherb:
Nochmal zum Verhalten bei gleichen Winkeln:
Wenn ich beide Servos mit gleichem Winkel ansteuere, dann wird Servo2 auf den richtigen Winkel gestellt, Servo1 aber geht auf Vollauschlag (>180°) und knurrt.

Deine Vermutung mit dem delayMicroseconds(0) scheint richtig zu sein.
Wenn ich bei Pulslängengleichheit den einen 1µs länger mache, funktionierts

Wenn delayMicroseconds keinen Null-Parameter mag, würde ich beim zweiten delay vielleicht nur auf Ungleichheit der beiden delays testen und

im "else" Fall einsetzen:
if (pulselen1!=pulselen2) delayMicroseconds(pulselen1-pulselen2);

guntherb:
Jetzt werde ich mich mal dranmachen, und die Funkion in meinen gesamtcode mit einzubauen. Bin schon gespannt.

Na dann auf gutes Gelingen!
Vielleicht gibt es ja bei Ansteuerung aus der loop einen Unterschied zum Verhalten mit der Servo-Library.

Edit/Nachtrag: delayMicroseconds(0) ist tatsächlich buggy und führt zu einem delay von ca. 1020 Mikrosekunden.
Böse Falle!

Oh ihr armen geplagten ... :.
Wartet mal bis zum WE, dann bin ich wieder zu Hause und hau den Servos hier was an den Glockenaker. :disappointed_relieved:

Keiner hat Mitleid mit mir !
Ich schwitz mir hier den ganzen Tag auf Malle so was von dermaßen einen ab .... knapp 30° auf der Terrasse im Schatten.
... na ist ja bald zu Ende !

]:smiley: TERWI

Armer TERWI, Sklave seiner Freizeit :stuck_out_tongue:

Applaus

Applaus

Applaus

Dem Meister der Codierung!

Manchmal ist weniger wirklich mehr.
Ich habe jetzt Jurs vereinfachten Servoansteuercode (leicht modifiziert mit der delayMicroseconds(0) Unterdrückung) in meinen Code eingebaut. Und, was soll ich sagen:
Läuft.

Kein Knurren, kein Zucken, kein einziger Laut von den Servos! (ausser wenn Sie verstellt werden)

Vielen Dank
tiefverneigend

Gunther