Pages: [1] 2   Go Down
Author Topic: Solved: Servo Zittern in Verbindung mit anderen Librarys  (Read 1739 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Edison Member
*
Karma: 38
Posts: 1161
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo Leute,

nun bin ich wieder mal an einem Punkt, an dem ich nicht weiter komme.
Mein Projekt:
ein Grillregler, der  die Temperturen im Grill mißt, über einen PID-Regler dann zwei Servos für Zuluft- und Abluftklappe ansteuert und das ganze nochauf SD-Karte mitloggt.

Bereits beim Testlauf fiel mir auf, dass die Servos ständig zittern und knurren, habe das aber auf die billigen Servos und den fliegenden Aufbau geschoben.

Nun, mit festem Aufbau und digitalen Servos ist das leider immer noch so - Wenn ich meinen Grillreglercode laufen lassen.
Wenn ich einen nackten Servosketch drauflade (gleiche Hardware) dann laufen die Servos völlig ruhig, wenn sich der Wert nicht ändert, dann stehen die Servos völlig still.

Wenn ich aber den kompletten Code laden, dann zittern die servos, auch wenn sich die STellgröße garnicht ändert.
Meine Vermutung ist, dass sich der Interrupthandler der Servolib mit einer der anderen Libs in die Quere kommt, und dadurch der Puls zur Servoansteuerung nicht gleichmäßig kommt.

ich habe  diese Libs eingebunden:
Code:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include <PID_v1.h>
#include <Bounce.h>
#include <SD.h>
#include <DS1307new.h>
#include <Servo.h>

Den ganzen Code kann ich nicht posten, weil ich inzwischen knapp 4000Zeilen Code in verschiedenen Dateien habe.
Was ich ausschliessen kann:  Spannungsversorgung, Einstreuung, Übersprechen, gestörtes Signal.

Im Englischsrachigen Teil des Forums habe ich diverse Einträge gefunden, die einen Beeinflussung von wire.h und servo.h nahe legen.

Hat einer von euch sich damit schonmal rumgeschlagen, oder eine Idee, wie ich das vermeiden kann?
Das einzige, was mir momentan einfällt, ist in den Phasen, in denen sich der Stellwert nicht ändert, die Versorgung der Servos abzuschalten. Aber das wäre nur die quick & dirty Lösung.
« Last Edit: October 16, 2013, 01:00:38 pm by guntherb » Logged

Grüße
Gunther

Offline Offline
Faraday Member
**
Karma: 116
Posts: 3896
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich glaube TERWI hatte mal das Problem und war auch am verzweifeln.
Logged

Offline Offline
Edison Member
*
Karma: 38
Posts: 1161
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh weh!

wenn Terwi daran schon verzweifelt, was soll dann ich erst machen!  smiley-sad-blue
Logged

Grüße
Gunther

Germany S-H
Offline Offline
Faraday Member
**
Karma: 143
Posts: 2994
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

wenn Terwi daran schon verzweifelt, was soll dann ich erst machen!  smiley-sad-blue

Am besten erstmal eine Diagnose des Problems.

Ich kenne mich mit Servos und der Servo-Library am Arduino zwar eher theoretisch aus als dass ich damit schon viel realisiert hätte, aber ich habe gesehen, dass es eine "write" Funktion zum Setzen des Sollwertes gibt und eine "refresh" Funktion zum Halten des gesetzten Werts, die in der Loop regelmäßig und oft genug aufgerufen werden muss.

Fragen:

1. Wie oft bzw. in welchen Zeitabständen greift in Deinem Sketch denn die Regelung ein und wie oft werden mit "servo1.write(value);" neue Sollwerte gesetzt?

2. Erfolgen die Aufrufe von "SoftwareServo::refresh();" in der loop oft genug, also mindestens alle 20 Millisekunden?

Könnte es sein, dass Du da bereits einen Bock geschossen hast?

Wenn nein und Du auch keine zeitkritischen Aktionen am Laufen hast, könnte man vielleicht die Interrupts blockieren, während die refresh-Funktion läuft.

Erste Idee: Während des Servo-refresh-Aufrufs mal testweise die Interrupts komplett zu blockieren.

noInterrupts();
SoftwareServo::refresh();
interrupts();

Ändert sich dann etwas am Servo-Zittern mit blockierten Interrupts während des Servo-refresh?
Zerreißt es laufende Ausgaben auf Serial? Funktioniert irgendwas nicht mehr?
Logged

Offline Offline
Edison Member
*
Karma: 38
Posts: 1161
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo Jurs,

nein, in der Servo.lib gibt es kein Refresh.

die Werte werden einfach mit servo.write() geschrieben und ab da übernimmt die Lib, alle 20ms (vermutlich mit Interrupt) den Puls auszugeben.

Ich habe schon probiert:
  • in der Loop jedesmal zu schreiben (ca. alle 10-25ms)
  • in Zeitscheiben zu schreiben (100ms, 1sek, 5sek)
  • wenn sich der Wert nicht ändert detach() und vor dem nächsten Ansteuern attach() (ist am schlechtesten)

Das alles habe ich auch in einem Beispielsketch, in dem nur die Servolib aktiv ist probiert, immer mit dem Ergebnis, dass das Servo nicht zittert. (mit Ausnahme des letzten Versuches)

Also auch, wenn ich nur einmal den Servowinkel  schreibe, und dann nichts mehr mache, zuckt und knarzt das Servo immer wieder. Das  ist nix grosses, das ist höchstens 1-2°, und wieder  zurück. Aber es nervt.

Weil der Grillregler vor allem nachts  und draussen läuft, nervt das extrem, wenn hier ständig die Servos rumzucken!
Logged

Grüße
Gunther

Germany S-H
Offline Offline
Faraday Member
**
Karma: 143
Posts: 2994
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

nein, in der Servo.lib gibt es kein Refresh.

Welche Library meinst Du?
Nicht diese hier: http://playground.arduino.cc/ComponentLib/servo
???

Bei der heißt es "you must call the SoftwareServo::refresh() method at least once every 50ms or so to keep your servos updating".

Also verwendest Du wohl eine andere Library.
Welche Servo-Library verwendest Du?

Und wenn Du mal nicht die bisher verwendete nutzt, sondern die oben verlinkte und in der loop "refresh" für die Servos verwendest?

Du hast doch die loop-Funktion auf hoher Drehzahl und ohne delay laufen? Oder vielleicht nicht?
Logged

DE
Offline Offline
God Member
*****
Karma: 21
Posts: 707
| Germany | NRW |
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Kann man nicht einfach nach Stellen des Servos diesen stromlos machen ?
Dann sollte das Zittern doch aufhören.

Aus einem anderen Hobbybereich weiss ich auch, dass es Unterschiede bzgl. des Halte-Verhaltens zwischen Analog- und Digitalservos gibt.
Logged

Dum spiro, spero - if you find my posting helpful, please click my Karma smiley
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Do you know A.R.T

Offline Offline
Edison Member
*
Karma: 38
Posts: 1161
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Welche Library meinst Du?
interessante Frage!

Ich habe die Servo-lib die in der IDE mitgeliefert wurde;
die hier: http://arduino.cc/en/Reference/Servo

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!)

Logged

Grüße
Gunther

Germany, BW
Offline Offline
Sr. Member
****
Karma: 7
Posts: 302
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Welche Library meinst Du?
interessante Frage!

Ich habe die Servo-lib die in der IDE mitgeliefert wurde;
die hier: http://arduino.cc/en/Reference/Servo

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.
Logged

Germany S-H
Offline Offline
Faraday Member
**
Karma: 143
Posts: 2994
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich habe die Servo-lib die in der IDE mitgeliefert wurde;
die hier: http://arduino.cc/en/Reference/Servo

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?

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.

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.
Logged

Offline Offline
Edison Member
*
Karma: 38
Posts: 1161
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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. smiley-red

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!  smiley-wink

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.
Logged

Grüße
Gunther

Germany, BW
Offline Offline
Sr. Member
****
Karma: 7
Posts: 302
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Edison Member
*
Karma: 38
Posts: 1161
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Grüße
Gunther

Offline Offline
Jr. Member
**
Karma: 7
Posts: 86
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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)
Logged

und Tschoe
Willie
http://www.rcarduino.tk

Offline Offline
Edison Member
*
Karma: 38
Posts: 1161
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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)

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.
Logged

Grüße
Gunther

Pages: [1] 2   Go Up
Jump to: