Servo Probleme

Hallo Community,

ich habe eine einfache Testschaltung mit meinem Arduino Mega, einem Servo und einer Lichtschranke aufgebaut. Durch Betätigen der Lichtschranke soll sich der Servo in seiner Position um 90 Grad drehen, und dann wieder zurückstellen. Das Ganze funktioniert eigentlich soweit, nur habe ich noch zwei Probleme:

  1. Während ich ein Programm auf den Arduino übertrage, bewegt sich der Servo irgendwie - ich vermute, dass während des Übertragens das Potential der Servo-Ansteuerungsleitung nicht konstant gehalten wird?

  2. In regelmäßigen Abständen (ca. alle 30 Sekunden) fängt der Servo für ca. 5 Sekunden zu "zittern" an, also er führt ganz schnelle Bewegungen hin und her aus (ca. 10 Grad um seine Ruhelage).

Ich habe schon viel versucht, aber leider keine Antworten bzw. Lösungen für diese Probleme gefunden - vor allem das zweite hat mir schon viel Kopfzerbrechen bereitet. Zur Servosteuerung verwende ich die Servo.h Library, der Ausgang für die Servoansteuerung ist als solcher deklariert und mittels attach()-Befehl dem Servo zugeordnet. Ich sende sonst keine Befehle an den Servo, die eine Positionsänderung hervorrufen würden.

Mit einem anderen "kleineren" Testprogramm funktioniert der Servo einwandfrei, ohne dass er zu zittern anfängt. Das richtige Programm (wo er zittert) ist bereits ein ziemlich großes, da das fertige Programm ein Display bekommen soll und ich hierfür schon einiges programmiert habe (ich denke es würde keinen Sinn machen, den ganzen Code hier zu posten).

Danke für Hilfe und Tipps im Voraus! :slight_smile:

Sketch macht immer Sinn. Servo an einer externen Spannungsversorgung?

Hallo!
Das Servozucken ist leider "normal", sobald auf den Timer zugegriffen wird.
Besonders schön bei pulseIn oder US-Pings zu beobachten.

Wenn das Servo nicht "halten" muss, könnte man mittels Microseconds aus einer Abfrage des
Lichtschrankens heraus direkt stellen.

int servo=9;
void setup()
{
pinMode(servo, OUTPUT);
}
void loop()
{
digitalWrite(servo, HIGH),
delayMicroseconds(1500); // 1000 für links, 2000 für rechts
digitalWrite(servo, LOW),
delayMicroseconds(3000);
}

mfg Martin

Da hat Martin recht.
Wenns nur ein Servo ist, dann kann man das auch zu Fuß ansteuern, ohne Lib.

Ich hatte mir da mal eine einfache Funktion geschrieben:

int ServoPin = 8;
int winkel = 90;

void setup(){
  Serial.begin(115200);
  pinMode(ServoPin, OUTPUT);     
}

void loop(){
  while (Serial.available() >0){   // wartet auf Winkeleingabe im Seriellen Monitor 
    winkel = Serial.parseInt();
    Serial.print("Winkel = ");Serial.println(winkel);
  }
  _Servo(winkel);
}
  

/*************************************************************************************************
**  _Servo()											**
**************************************************************************************************
** muß in der loop stehen (ohne DELAY!) sollte  alle 20ms aufgerufen werden!			**
** gibt >= alle 20ms einen Servopuls am Servopin aus						**
** wenn pulseabstand > 20ms ist, wird das Servo langsamer.					**
** based on Two-Servo-Test by 'jurs' for German Arduino Forum					**
**  												**
**  											   	**
**  Input:  Winkel 										**
**  Output:											**
**  genutzte Globale Variablen:  								**
**************************************************************************************************/
void _Servo(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;
  if (millis()-lastRefresh < pulseabstand) return; // noch keine 20 ms vergangen
  lastRefresh = millis(); // Zeit des erfolgten Refresh merken
  
  _angle = constrain(_angle, Servo_minW, Servo_maxW); // Stellwinkel begrenzen
  int pulselength = _angle * m + b;
  //Serial.print("Winkel = ");Serial.print(_angle);Serial.print("   Puls: ");Serial.println(pulselength);
  noInterrupts();
  digitalWrite(ServoPin,HIGH); // Ersten Refresh-Impuls starten
  delayMicroseconds(pulselength);
  digitalWrite(ServoPin,LOW);
  interrupts(); 
}  // end _Servo