Pages: [1] 2   Go Down
Author Topic: Das berühmte zucken der Servos  (Read 952 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo zusammen!

Bei der Inbetriebnahme des Arduino werden meine Servos irgendwie positionsmäßig initialisiert. Dies funktioniert auch wunderbar. Nachdem ich jedoch den ersten Servo stelle, fangen danach alle Servos ständig an zu zucken. Stellen lassen sie sich dennoch einwandfrei. Die Servos sind mit einer separaten Stromquelle (5V Netzteil) gespeist und die Masse geht parallel zum Arduino.  Muss hier u.U. mit einem Elko gearbeitet werden oder habe ich einen anderen Fehler?

Würde mich sehr über jede Hilfestellung freuen!

Besten Dank und viele Grüße aus Berlin
René

Nachstehend auch noch der Code:

#include <VarSpeedServo.h>

//#include <Servo.h>
#include <Wire.h>
#include <Centipede.h>

Centipede CS;

int taster9 = 0;
int taster8 = 0;
int taster10 = 0;
int taster6 = 0;
int taster5 = 0;
int taster4 = 0;
int taster13 = 0;
int taster14 = 0;

VarSpeedServo weiche1;
VarSpeedServo weiche6;
VarSpeedServo weiche7;

void setup() {
 
   weiche1.attach(12); //12
  weiche6.attach(11); //11
  weiche7.attach(10); //10
 
 
  Wire.begin();
  CS.initialize();
 
  CS.pinMode(11, OUTPUT);
  CS.pinMode(7, OUTPUT);
  CS.pinMode(0, OUTPUT);
  CS.pinMode(1, OUTPUT);
  CS.pinMode(2, OUTPUT);
  CS.pinMode(3, OUTPUT);
  CS.pinMode(15, OUTPUT);
  CS.pinMode(7, OUTPUT);
 
  CS.pinMode(9, INPUT); CS.pinPullup(9, HIGH);
  CS.pinMode(8, INPUT); CS.pinPullup(8, HIGH);
  CS.pinMode(10, INPUT); CS.pinPullup(10, HIGH);
  CS.pinMode(6, INPUT); CS.pinPullup(6, HIGH);
  CS.pinMode(5, INPUT); CS.pinPullup(5, HIGH);
  CS.pinMode(4, INPUT); CS.pinPullup(4, HIGH);
  CS.pinMode(13, INPUT); CS.pinPullup(13, HIGH);
  CS.pinMode(14, INPUT); CS.pinPullup(14, HIGH);
 
 
 
  }

void loop() {
 
  taster9 = CS.digitalRead(9);
  taster8 = CS.digitalRead(smiley-cool;
  taster10 = CS.digitalRead(10);
  taster6 = CS.digitalRead(6);
  taster5 = CS.digitalRead(5);
  taster4 = CS.digitalRead(4);
  taster13 = CS.digitalRead(13);
  taster14 = CS.digitalRead(14);
 
 
  // Ab hier werden die Fahrstraßen mit Hilfe von IF-Bedingungen gestellt
 
  // Fahrstraße HB - HBF1
 
  if (taster9 == LOW && taster6 == LOW) {
     delay(500);
     weiche1.slowmove(55,40); // abzweig
     delay(500);
     weiche6.slowmove(60,40); // gerade
     delay(500);
     CS.digitalWrite(11, HIGH);
     CS.digitalWrite(2, HIGH);
     CS.digitalWrite(0, HIGH);
     CS.digitalWrite(3, LOW);
     CS.digitalWrite(15, LOW);
     }
 
  // Fahstraße HB - HBF2
  if (taster9 == LOW && taster5 == LOW) {
     delay(500);
     weiche1.slowmove(100,40); // gerade
     delay(500);
     weiche7.slowmove (100, 40); // gerade 100 40
     delay(500);
     CS.digitalWrite(11, HIGH);
     CS.digitalWrite(3, HIGH);
     CS.digitalWrite(15, HIGH);
     CS.digitalWrite(2, LOW);
     CS.digitalWrite(0, LOW);
     }
     
  // Fahstraße HBF1 - HBF2 Umsezten
  if (taster6 == LOW && taster14 == LOW) {
     delay(500);
     weiche6.slowmove(100,40); // gerade
     delay(500);
     weiche7.slowmove(60,40); // gerade 60
     delay(500);
     CS.digitalWrite(2, HIGH);
     CS.digitalWrite(15, HIGH);
     //CS.digitalWrite(2, LOW);
     //CS.digitalWrite(0, LOW);
     }     
     
  // Fahstraße HBF2 - HbfEinfahrt
  if (taster14 == LOW && taster9 == LOW) {
     delay(500);
     weiche1.slowmove(100,40); // gerade
     delay(500);
     weiche7.slowmove(100,40); // gerade
     delay(500);
     CS.digitalWrite(11, HIGH);
     CS.digitalWrite(15, HIGH);
     CS.digitalWrite(3, HIGH);
     //CS.digitalWrite(2, LOW);
     //   
   }
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Noch eine recht lustige Entdeckung... Wenn ich (siehe Sketch) Taster9 gedrückt halte, ist das Zucken zwar nicht weg aber deutlich geringer, allerdings auch nur bei Taster9. Wirklich seltsam. Die Taster hängen an einem MCP23017, die Servos sind direkt am Arduino.
Logged

Münsterland
Offline Offline
Faraday Member
**
Karma: 48
Posts: 2853
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Wieviel Strom liefert das NT? Elkos sind in den Servos teils schon eingebaut (die blauen vom Chinesen)
Logged

Gruß Stefan

Keine Code-Anfrage über die Persönlichen Nachrichten.

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Output 5V, 3,5A... Lustig ist auch, wenn ich das Netzteil ziehe, dann dauert es noch ca. 5 Sekunden bis das Zucken weg ist. Eigentlich müsste doch sofort Ruhe sein...
Logged

Münsterland
Offline Offline
Faraday Member
**
Karma: 48
Posts: 2853
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Das Netzteil wird einen dicken Elko zur Glättung nutzen, somit soweit in Ordnung. Meist kann man das Phaenomen auch sehen, wenn man ein HandyNT mit Led Leuchte hat. Ist nur das Kabel eingesteckt, läuft die Led noch etwas nach. MIt Last direkt verschwunden. Aber aus deinem Zucken werde ich auch noch nicht schlau.
Logged

Gruß Stefan

Keine Code-Anfrage über die Persönlichen Nachrichten.

Offline Offline
Edison Member
*
Karma: 39
Posts: 1179
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Zucken die Servos auch, wenn du nicht die "VarSpeedServo.h" sonder dir normale "Servo.h" nimmst?
Logged

Grüße
Gunther

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Zucken die Servos auch, wenn du nicht die "VarSpeedServo.h" sonder dir normale "Servo.h" nimmst?

Leider ja.

Grüße
René
Logged

Offline Offline
Edison Member
*
Karma: 14
Posts: 1007
ATmega 2560
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,

ist das PWM Signal stabil? Ist das an allen PWM Ausgängen der Fall?

Logged

Tschau
Doc Arduino

Offline Offline
Edison Member
*
Karma: 39
Posts: 1179
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ich hatte bei mir auch die Servo.h verwendet und hatte mit ständigem Servozucken zu kämpfen.

Da ich nur 2 Servos hatte, habe ich, nach vielen Versuchen die Servo.h rausgeworfen und die Pulse manuell über delayMicroseconds() erzeugt.
Ich vermutete damals eine gegenseitige Störung durch den I2C bus.

Was mir aber auffiel: die 20ms Pulsabstand sind nicht unbedingt nötig. Wenn man die pulse seltener sendet, dann wird das Servo nur langsamer.

Eine andere Alternative: da du ja die Servos zum Weichenstellen verwendest, könntest du auch nur beim Stellen eine gewisse Anzahl von Stellpulsen senden, und dann nichts mehr. Wo nichts gesendet wird, kann auch nichts zittern.

Ich denke, bei Anwendungen,bei denen die Servos ständig in Bewegung sind, fällt das zittern und zucken nicht so auf. Aber für eher statische Anwendungen ist die "von Hand" Lösung nicht so verkehrt.
Logged

Grüße
Gunther

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo Gunther,

deine Ausführungen klingen extrem spannend! Auch ich vermute eine gegenseitige Störung mit dem I2C Bus. Hatte vorher in Experimenten mal Servos einfach so an den Arduino angeschlossen (ohne Erweiterungen via I2C) und da hatte ich solche Probleme nicht.

Quote
Ich denke, bei Anwendungen,bei denen die Servos ständig in Bewegung sind, fällt das zittern und zucken nicht so auf. Aber für eher statische Anwendungen ist die "von Hand" Lösung nicht so verkehrt.

Genau daran hatte ich auch gedacht, zumal alle Servos (Weichen) später sowieso bei erster Inbetriebnahme initialisiert werden sollen. Leider scheitert es hier nur an meinem bescheidenen Fachwissen hinsichtlich der Umsetzung. Da werde ich mich noch ordentlich reinlesen müssen um die Servos manuell anzusteuern und vor allem ohne die Servo.h!

@Doc_Arduino: Das Phänomen tritt bei allen Ausgängen auf.

Grüße
René
Logged

Offline Offline
Edison Member
*
Karma: 14
Posts: 1007
ATmega 2560
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,

ohne Servo.h könntest Du Dir eine Funktion schreiben die nichts weiter macht als einen Port ein und auszuschalten und dazwischen Wartezeit einzufügen. Diese rufst Du so lange/so oft auf wie es laut Servo Datenblatt dauert für einen vollne Bewegungsauschlag. Zur Vereinfachung kannste 2 Funktionen erstellen, je für links und rechts Anschlag. Dann mußte innerhalb der Funktion die Werte nicht anpassen. Vielleicht erstmal einfacher. Wenn in Kauf genommen werden kann das während dessen der Code nicht weiterläuft, kannste delay verwenden. Sonst mußte noch das delay durch millis() ersetzen.


Logged

Tschau
Doc Arduino

Offline Offline
Edison Member
*
Karma: 39
Posts: 1179
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nimm doch sowas:


Code:
const int wievieleServos = 1;
int ServoPin[wievieleServos] = {8,9,10};

/*************************************************************************************************
**  ServoRefresh() **
**************************************************************************************************
** muß in der loop stehen (ohne DELAY!) muß mindestens alle 20ms aufgerufen werden! **
** gibt >= alle 20ms einen Servopuls am Servopin aus **
** based on Two-Servo-Test by 'jurs' for German Arduino Forum **
**  **
**      **
**  Input:  Servonummer, Winkel (0-140°) **
**  Output: **
**  genutzte Globale Variablen: ServoPin[], wievieleServos **
**************************************************************************************************/
void ServoRefresh( int _Nr, int _angle)
{
  const int pulseabstand = 20;       // Definition der Kenngrößen
  const int Servo_minpulse = 800;    // der Servoansteuerung
  const int Servo_maxpulse = 2400;
  const int Servo_minW = 20;        // kleinster und größter Winkel
  const int Servo_maxW = 160;
  // berechnen der Geradengleichung des Servos
  const float m = ((Servo_maxpulse - Servo_minpulse)*1.0/(Servo_maxW - Servo_minW)*1.0);
  const int b = Servo_minpulse - m * Servo_minW;
 
  static unsigned long lastRefresh[wievieleServos];
  if (millis()-lastRefresh[_Nr] < pulseabstand) return; // noch keine 20 ms vergangen
  lastRefresh[_Nr] = millis(); // Zeit des erfolgten Refresh merken
 
  _angle = constrain(_angle, 20, 160); // Stellwinkel von 20 - 160 Grad erlaubt
  int pulselen1 = _angle * m + b;
Serial.print("Winkel = ");Serial.print(_angle);Serial.print("   Puls: ");Serial.println(pulselen1);
  noInterrupts();
  digitalWrite(ServoPin[_Nr],HIGH); // Ersten Refresh-Impuls starten
  delayMicroseconds(pulselen1);
  digitalWrite(ServoPin[_Nr],LOW);
  interrupts();
}  // end ServoRefresh

Das funktioniert bei mir mit 2 Servos, sollte mit 3 auchgehen.
Aufruf in der loop:
ServoRefresh( 0, Winkel0);  //  Aufruf erstes Servo
ServoRefresh( 1, Winkel1);  //  Aufruf zweites Servo
ServoRefresh( 2, Winkel2);  //  Aufruf drittes Servo

edit: Code korrigert, war falsch.
« Last Edit: February 09, 2014, 12:35:09 pm by guntherb » Logged

Grüße
Gunther

Offline Offline
Jr. Member
**
Karma: 11
Posts: 62
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo!
Direkt ansprechen geht auch...Pin auf High und danach Delay (1) für links oder (2) für rechts.  dann den Pin auf Low setzen.
Mit millis (EDIT:microseconds) gehts genauer...Servos nicht in ihre mechanische Endlage bringen (Blockierstrom), also rantasten.
..mit einem  Delay nach Low kannst die Stellgeschwindigkeit beeinflussen, fur die Position nicht relevant ( wenn > als 2 ms).
Der 20/22 ms Frame wird nur bei der RC Funkstrecke  (PPM) benutzt, um bis zu 8 (PWM) Servos anzusprechen.

mfg Martin

« Last Edit: February 09, 2014, 08:47:00 am by Wasjetzt » Logged

Germany
Offline Offline
Jr. Member
**
Karma: 0
Posts: 52
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nimm doch sowas:


Code:
  _angle constrain(_angle, 20, 160); // Stellwinkel von 20 - 160 Grad erlaubt
 



Kann es sein das dort bei _angle ein = fehlt ?
Also : _angle = constrain(_angle, 20, 160);

habe den Code gerade getestet und mein Servo mal volle Kanne gegen gefahren :-(
Irgend wie funktioniert das aber nicht bei mir.
Ich habe drei aufrufe :
Code:
ServoRefresh( 0, 40);
delay (1000);
ServoRefresh( 0,60);
delay (1000);
ServoRefresh( 0, 80);
delay (3000);

Die drei Positionen werden aber nicht richtig angefahren, bzw unterschiedlich. Einmal bewegt sich das Servon nur zwei mal bis zur größeren Pause, oder es bewegt sich manchmal viel weiter. Würde das gerne für meinen Attiny85 benutzen, das die SorftwareServo Library irgend wie zu ungenaue Positionen ausgibt. Dabei rede ich von mind. +/- 5mm bei einer Hebellänge von 7cm.
Aber es sollte dann zuerst mal mit dem Arduion UNO laufen.
Logged

Offline Offline
Edison Member
*
Karma: 39
Posts: 1179
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Kann es sein das dort bei _angle ein = fehlt ?
Also : _angle = constrain(_angle, 20, 160);
ja, das ist so, da ist wohl was beim kopieren passiert. smiley-red

Quote
Irgend wie funktioniert das aber nicht bei mir.
Das tut mir leid, ich habe das codeschnipsel aus den Tiefen meiner Festplatte ausgegraben.
Ich denke schon, dass es funktioniert, kanns aber gerade nicht testen.
Ich melde mich nochmal.

Logged

Grüße
Gunther

Pages: [1] 2   Go Up
Jump to: