Servo "zuckt"/macht Geräusche im Leerlauf

Hallo,

ich habe an einem Arduino Mega 4 Servos vom Typ AZDelivery MG996R hängen, wobei die 5 V am + Pol von einem separatem Netzteil kommen und nur der Steuer-IO vom Arduino kommt. GND ist vom Arduino und 5V Netzteil zusammengeschaltet.

Mein Problem ist aktuell, dass die Servos relatif oft im Leerlauf "mahlende" Geräusche machen und das obwohl sie laut Code ja eigentlich gar nichts machen sollten, außer auf den nächsten Steuerbefehl zu warten. Die Steuerung funktioniert soweit auch, aber mich stören diese Geräusche, da ich vermute, dass die auf Dauer auch nicht gut für die Servos sind.

Ich habe mal 3 Videos hier hochgeladen:

Das dritte Video mit dem Zucken ab 0:14 kommt, wenn ich am Steuerpin des Arduino für den Servo das Kabel bewege.

Hat jemand einen Tipp woran das liegen könnte ich wie ich das abstellen kann?

Hier auch noch mein Code:

#include <Servo.h>
#include <RCSwitch.h>
RCSwitch receiver = RCSwitch();
RCSwitch sender = RCSwitch();


// ===== Servo =====
// create servo object to control a servo
Servo servoA;
Servo servoB;
Servo servoC;
Servo servoD;
Servo servoF;

// variable to store the servo position
int start_position = 0;
int end_position = 180;

int posA = start_position;
int posB = start_position;
int posC = start_position;
int posD = start_position;
int posF = start_position;



// =====================================================
// Servo öffnen
// =====================================================
void openServo(Servo &servoOpen, int &posOpen)
{
  while (posOpen < end_position)
  {

    posOpen++;
    servoOpen.write(posOpen);

    Serial.print("Servo öffnet:");
    Serial.println(posOpen);
    
    //delay(100);
  }

}



// =====================================================
// Servo schließen
// =====================================================
void closeServo(Servo &servo, int &posClose)
{
  while (posClose > start_position)
  {

    posClose--;
    servo.write(posClose);

    Serial.print("Servo schließt:");
    Serial.println(posClose);

    //delay(100);
  }
    
}

// =====================================================
// Setup
// =====================================================
void setup()
{
  Serial.begin(9600);
  
  servoA.attach(4);
  servoB.attach(6);
  servoC.attach(11);
  servoD.attach(12);
  servoF.attach(13);

  servoA.write(start_position);
  servoB.write(start_position);
  servoC.write(start_position);
  servoD.write(start_position);
  servoF.write(start_position);

  //Funk Empfänger initialisieren
  receiver.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
  receiver.setProtocol(2);
  receiver.setPulseLength(690);

  //Funk Transmitter initialisieren
  sender.enableTransmit(10);  // An Pin 10
  sender.setProtocol(1);
  sender.setPulseLength(416);
  sender.setRepeatTransmit(15);

  //integrierte LED auf Arduino initialisieren
  pinMode(LED_BUILTIN, OUTPUT);

}

// =====================================================
// Loop
// =====================================================
void loop()
{
  
  unsigned long value = receiver.getReceivedValue();
  
  if (receiver.available()) {
    
    if (value == 2288270336){ //Button A ON
      Serial.println("A_AN");

      //kleine Pause, damit längeres Drücken nicht als mehrere Betätigungen interpretiert werden
      delay(200);

      //Funkdose aktivieren und integrierte LED anschalten
      digitalWrite(LED_BUILTIN, HIGH);
      sender.send("100100001001010010011001");
      Serial.println("Signal EIN gesendet");

      //Servo öffnen
      openServo(servoA, posA);

      //Alle anderen Servos schließen (falls überhaupt offen)
      closeServo(servoB, posB);
      closeServo(servoC, posC);
      closeServo(servoD, posD);

      

      
    }

    if (value == 2221161472){ //Button A OFF
      Serial.println("A_AUS");
      
      //kleine Pause, damit längeres Drücken nicht als mehrere Betätigungen interpretiert werden
      delay(200);
    

      digitalWrite(LED_BUILTIN, LOW);
      //Funkdose aktivieren und integrierte LED ausschalten
      sender.send("100100001001010010010001");
      Serial.println("Signal AUS gesendet"); 
      
    }
    
    if (value == 2281776640){ //Button B ON
      Serial.println("B_AN");

      //kleine Pause, damit längeres Drücken nicht als mehrere Betätigungen interpretiert werden
      delay(200);

      //Funkdose aktivieren und integrierte LED anschalten
      digitalWrite(LED_BUILTIN, HIGH);
      sender.send("100100001001010010011001");
      Serial.println("Signal EIN gesendet");

      //Servo öffnen
      openServo(servoB, posB);

      //Alle anderen Servos schließen (falls überhaupt offen)
      closeServo(servoA, posA);
      closeServo(servoC, posC);
      closeServo(servoD, posD);

      

      
    }

    if (value == 2214667776){ //Button B OFF
      Serial.println("B_AUS");
      
      //kleine Pause, damit längeres Drücken nicht als mehrere Betätigungen interpretiert werden
      delay(200);

      digitalWrite(LED_BUILTIN, LOW);
      //Funkdose aktivieren und integrierte LED ausschalten
      sender.send("100100001001010010010001");
      Serial.println("Signal AUS gesendet"); 


    }

    if (value == 2287266816){ //Button C ON
      Serial.println("C_AN");

      //kleine Pause, damit längeres Drücken nicht als mehrere Betätigungen interpretiert werden
      delay(200);

      //Funkdose aktivieren und integrierte LED anschalten
      digitalWrite(LED_BUILTIN, HIGH);
      sender.send("100100001001010010011001");
      Serial.println("Signal EIN gesendet");

      //Servo öffnen
      openServo(servoC, posC);

      //Alle anderen Servos schließen (falls überhaupt offen)
      closeServo(servoA, posA);
      closeServo(servoB, posB);
      closeServo(servoD, posD);

      

      
    }

    if (value == 2220157952){ //Button C OFF
      Serial.println("C_AUS");
      
      //kleine Pause, damit längeres Drücken nicht als mehrere Betätigungen interpretiert werden
      delay(200);

      digitalWrite(LED_BUILTIN, LOW);
      //Funkdose aktivieren und integrierte LED ausschalten
      sender.send("100100001001010010010001");
      Serial.println("Signal AUS gesendet"); 


    }


    if (value == 2284645376){ //Button D ON
      Serial.println("D_AN");

      //kleine Pause, damit längeres Drücken nicht als mehrere Betätigungen interpretiert werden
      delay(200);

      //Funkdose aktivieren und integrierte LED anschalten
      digitalWrite(LED_BUILTIN, HIGH);
      sender.send("100100001001010010011001");
      Serial.println("Signal EIN gesendet");

      //Servo öffnen
      openServo(servoD, posD);

      //Alle anderen Servos schließen (falls überhaupt offen)
      closeServo(servoA, posA);
      closeServo(servoB, posB);
      closeServo(servoC, posC);
      

      

      
    }

    if (value == 2217536512){ //Button D OFF
      Serial.println("D_AUS");
      
      //kleine Pause, damit längeres Drücken nicht als mehrere Betätigungen interpretiert werden
      delay(200);

      digitalWrite(LED_BUILTIN, LOW);
      //Funkdose aktivieren und integrierte LED ausschalten
      sender.send("100100001001010010010001");
      Serial.println("Signal AUS gesendet"); 


    }

    receiver.resetAvailable();
  }

}

Ganz einfach, wo anders neues Serwo kaufen, AZ ist bekant dafür das so manche Sachen Schrott sind.
Vor langer Zeit war das sehr serioser Händler.

Sieht dann wohl nach Kontaktproblemen aus.

Das läßt an Kontaktprobleme denken. Stecken die Kabel fest in den Buchsen oder sind sie ziemlich locker?

Daß diese Servos nicht leise und ruhig in der Zielposition stehen bleiben ist fisiologisch.

Grüße Uwe

Kannst du testweise RCSwitch rausnehmen?

Guten Morgen,

@fony & @uwefed habt ihr denn Empfehlungen welche Servos ich nehmen soll? Sie müssen 180 Grad drehen können.

Die Kontaktprobleme hätte ich (als Laie) eigentlich ausgeschlossen, da ich bei dem Mega so ein Breakout Board ( GeeekPi Terminal Block Breakout Board Hat with Reset Button and LED Indicator, GPIO Expansion Board Breakout Module for Arduino Mega 2560 R3: Amazon.de: Business, Industry & Science ) oben drauf installiert habe und die Kabel mit Aderendhülsen fest verschraubt habe. Das Zucken im Video 3 kommt dann sobald ich mit dem Schraubendreher nur an den Kontakt komme bzw. die Schraube rausdrehe, was ich ja im Betrieb nicht mache, aber diese mahlenden Geräusche aus Video 1 und 2 macht er fast die ganze Zeit.
Zu Hause mit dem Arduino Uno ohne ein solches Breakout Board hatte ich die Probleme in ganz leichter Form aber auch schon mal.

Aber ja @Rintin da ich die Funktion mit RCSwitch zuletzt eingebaut habe und davor keine Probleme hatte, versuche ich das mal zu deaktivieren. Für die komplette Funktionalität brauche ich das aber ;)

Ich vermute dass dein RF-Empfänger zu sehr rauscht und die Interrupts daher das Timing von den Servos stört.

Ein paar Ideen:

  • Für den Empfang das RMT Modul eines ESP32 verwenden
  • Servos über Hardware PWM Steuern (Uno/Nano R4 sollte genug Timer dafür haben)
  • Externer PWM Chip per I2c anschließen (PCA9685)

Was genau meinst du mit dem Punkt?

Servos über Hardware PWM Steuern (Uno/Nano R4 sollte genug Timer dafür haben)

Also soll ich die PWM Kanäle meines Arduino Mega nutzen und drauf achten, dass ich immer einen port mit einem anderen Timer nutze? (bzw. wieso soll ich noch einen extra Uno/Nano nehmen?)

Das Problem dürfte sein, dass die Servo Lib auf Interrupts basiert.
Eigentlich nicht schlimm....
Nur, dass dein FunkDingen ebenfalls Interrupts nuzt.

Die Servos zucken, weil deren Interrupts leider von den Funkinterrupts verzögert werden.

Einzige mir bekannte Möglichkeit/Abhilfe:
Deligieren!

z.B.:

Ja genau. Und scheinbar hat das schon wer in eine Library gegossen.

Nein, Der Mega2560 kommt mit 4 (16-Bit) Timern mit je 3 PWM Ausgängen. Da die Servos alle die selbe Wiederholrate des Signals benötigen, kannst du mit einem der Timer 3 Servos steuern.

Gedanklich bin ich bei Antworten meist beim Uno R3 der nicht genug PWM Kanäle für dich hat.
Der R4 war da nur ein Beispiel. Mit dem Mega sollte das auch gehen.

ich was übersehen? gibt es jetzt einen NANO R4?

https://docs.arduino.cc/hardware/nano-r4/

Das ist ja das Problem, dass alles auf Krampf UNO und NANO heißen soll, obwohl das nur die grundlegenden mechanischen Werte widerspiegelt.

Gruß Tommy

ups

Das Shield sollte die Kabel sicher verbinden. Also auf dieser Seite alles OK.
Daß ein Schraubenzieher am Servo Signal Kabel solche Störungen einstreut läßt mich denken daß die Masseverbindung zwischen Servo und Arduino fehlt.
Grüße Uwe

Wieso "obwohl" ?
Uno ist der Formfaktor, und gibt einen Hinweis darauf, dass die entsprechenden Shields draufgesteckt werden können.
Nano entsprechend die Steckbrett-Variante.

Dass wir Veteranen bei diesen Stichworten noch die AVR atmega328 Varianten im Kopf haben, die "Arduino" vor langer Zeit mal zum Erfolg gemacht haben, ist unser Problem.

Und was ist mit 5V und 3.3V? Passt das immer bei den Shields?

Zusätzlich sehe ich evtl. noch Probleme mit 5V und 3,3V, die das einfache Aufstecken der Shields zunichte machen können.

Gruß Tommy

Uno ist 5v und Zero ist 3v.

Deshalb finde ich den Uno Q eine totale Katastrophe.

Die Shields müssen für 3v oder 5v geeignet sein.

Edit: Sind wir schon OT genug das wir den Thread splitten sollten?

Seit R3 ist IOREF verpflichtend, sowohl für Boards als auch für Shields.