Servozittern bei auslesen von RC-Empfänger und ausgabe per servo.write

Servus zusammen, ich muss mal wieder das Schwarmwissen anzapfen, da ich momentan bei einem Projekt hänge. Ich steuere mit einem Arduino zwei Servos an. Dazu habe ich zwei Optionen, entweder kommen die Positionssignale über einen RC-Empfänger, oder über die serielle Schnittstelle (von einem Python-Programm, welches ein Kamerabild auswertet und über die zwei Servos die Kamera nachführt). Über einen dritten Kanal der RC-Fernbedienung kann ich umschalten zwischen den beiden Möglichkeiten. Der jeweilige Status wir über eine Neopixel-LED angezeigt. Jetzt habe ich das Problem, dass die Servos teilweise ziemlich stark zucken, wenn ich sie über den RC-Empfänger ansteuere. Das RC-Signal sieht sauber aus auf dem Oszilloskop, das PWM-Signal, dass vom Arduino an die Servos rausgeht, sieht man auch am Oszi in der Pulslänge schwanken. Scheinbar funkt mir hier irgendwas in die PWM-Erzeugung rein. Ich hab auch schon die Neopixel-Ansteuerung rausgeworfen, ohne Erfolg. Die Massen von Empfänger, Arduino und Servos sind miteinander verbunden.
Hat vielleicht jemand eine Idee, von was die Zuckungen kommen könnten?

Viele Grüße,

Martin

#include <Servo.h>
#include <Adafruit_NeoPixel.h>

// Erstelle Servo-Objekte
Servo servoX;
Servo servoY;

// Definiere die Pins für die Servos und RC-Empfänger
const int Channel1 = 6;
const int Channel2 = 7;
const int StatusSwitch = 8;
const int servoPinX = 9;
const int servoPinY = 10;

// Definiere Neopixel LED-Pin
#define LED_PIN    4
#define LED_COUNT 1
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

// Variablen zum Speichern der aktuellen Position der Servos
int posX = 90; // Startposition in der Mitte (90 Grad)
int posY = 90;

// Variablen für die Bildmitte (angepasst an die Kameraauflösung)
const int centerX = 320; // Beispielwert für die Mitte bei einer Auflösung von 640x480
const int centerY = 240;

// Kalibrierungsschritte für die Servos (wie viel Grad pro Pixelverschiebung)
const float stepX = 0.02; // Beispielwert, anpassen je nach Servo und Mechanik
const float stepY = 0.02; // geändert von 0,02

void setup() {

  // Initialisiere Neopixel
  strip.begin();
  strip.show();
  
  // Initialisiere die Servos an den angegebenen Pins
  servoX.attach(servoPinX);
  servoY.attach(servoPinY);
  
  // Setze die Anfangsposition der Servos
  servoX.write(posX);
  servoY.write(posY);
  
  // Initialisiere die serielle Kommunikation
  Serial.begin(9600);

  // Initialisiere die RC-Empfänger Pins
  pinMode(StatusSwitch, INPUT);
  pinMode(Channel1, INPUT);
  pinMode(Channel2, INPUT);
}

void loop() {
  unsigned long rcValue1 = pulseIn(Channel1, HIGH);
  unsigned long rcValue2 = pulseIn(Channel2, HIGH);
  unsigned long rcValue3 = pulseIn(StatusSwitch, HIGH);

  if (rcValue3 < 1500) {
    // Wenn Daten über die serielle Schnittstelle empfangen werden
    if (Serial.available() > 0) {
      // Lese die empfangenen Daten
      String data = Serial.readStringUntil('\r');

      // Splitte die Daten bei ','
      int commaIndex = data.indexOf(',');
      if (commaIndex > 0) {
        String xStr = data.substring(0, commaIndex);
        String yStr = data.substring(commaIndex + 1);
        
        // Konvertiere die Strings in Integer
        int x = xStr.toInt();
        int y = yStr.toInt();

        // Berechne die Abweichungen von der Bildmitte
        int deltaX = x - centerX;
        int deltaY = y - centerY;

        // Aktualisiere die Servo-Positionen basierend auf den Abweichungen
        posX = constrain(posX - deltaX * stepX, 0, 180); // Einschränken auf den Bereich 0-180 Grad
        posY = constrain(posY + deltaY * stepY, 0, 180); // Einschränken auf den Bereich 0-180 Grad

        // Bewege die Servos zu den neuen Positionen
        servoX.write(posX);
        servoY.write(posY);

        // Setze Neopixel
        strip.setPixelColor(0, 0, 150, 150);
        strip.show();
        
        // Debugging-Ausgabe
        Serial.print("Servo X: ");
        Serial.print(posX);
        Serial.print(" | Servo Y: ");
        Serial.println(posY);
      }
    }
  } else {
    // Berechne die Servo-Positionen basierend auf den RC-Empfänger Signalen
    posX = map(rcValue1, 1000, 2000, 0, 180);
    posY = map(rcValue2, 1000, 2000, 0, 180);
    
    // Bewege die Servos zu den neuen Positionen
    servoX.write(posX);
    servoY.write(posY);

    // Setze Neopixel
    strip.setPixelColor(0, 150, 0, 150);
    strip.show();

    // Debugging-Ausgabe
    Serial.print("RC Servo X: ");
    Serial.print(posX);
    Serial.print(" | RC Servo Y: ");
    Serial.println(posY);
  }
}

Nimm' MoBaTools statt Servo.h

Bist Du Dir sicher, dass da keine Klammern fehlen?

Lass dir die doch mal ausgeben. Schwanken die auch?

Ich denke die Neopixel spucken dir in die Suppe. Die Servo.h ( und übrigens auch die MobaTools ) erzeugen die Servo-Impulse per Timer-Interrupt. Beim Update der Neopixel werden die Interrupts aber wegen des sehr engen Timings der Neopixel abgeschaltet. Das hat dann Auswirkungen auf die Servo-Pulse. Dass Du die Neopixel in jedem loop()-Durchlauf ansteuerst macht die Sache noch schlimmer.
Welchen Arduino verwendest Du? Für AVR gibt es meines Wissens auch eine Servo-Lib, die die Impulse direkt per Timer HW erzeugt. Da können dann zwar nicht so viele Servos angesteuert werden, aber 2 gehen wohl.

Bei zu längeren Leitungen vom Empfänger zum Servo benutzen wir im Modellflug Ferritringe um das Problem:

zu vermeiden. 3-4 Umwicklungen mit dem Servokabel um den Ferritring reichen.

Ich denke das das 3er Gespann aus Neopixel, Servo und pulseIn sich gegenseitig stören.

Gib mal rcValue1 auf der seriellen Schnittstelle aus. Ist der Wert stabil?

So, ich hab heute ein wenig weiter experimentiert. Scheinbar ist wirklich das Eingangssignal vom RC-Empfänger zum Arduino nicht ganz sauber. Ich hatte aber auch erst die Neopixels im Verdacht. Jetzt muss ich mal schauen, ob ich das RC-Signal irgendwie sauberer bekomme. Oder ich versuch mal einen SBUS-Empfänger, wär evtl. auch noch eine Möglichkeit.

ist nicht gut: Wie kommst du darauf?

Ich stelle meine Frage noch einmal.
Vielleicht bekomme ich ja eine Antwort.

habs mir mal über die serielle Schnittstelle ausgegeben, da sehe ich auch leichte Schwankungen.

Wie sieht es aus, wenn du keine Servoansteuerung machst?

Welchen Arduino hast du?

Sollte doch normal funktionieren, oder? Wo siehst du ein Problem?

Punktrechnung vor Strichrechnung.
Mir sieht das komisch aus.
Oder erkläre mir, warum Du ein Delta mit Steps multiplizierst.

Ich nutze einen Arduino Nano, das RC-Signal ist stabil, wenn ich nicht steuere, aber hat plötzliche, kurze, leichte Schwankungen.

was den jetzt: Stabil oder Schwankungen?

Das Signal ist eine zeitlang Stabil, mit minimalen Schwankungen, und haut mir dann plötzlich eine größere Schwankung rein.

Schön das du einen 4k Monitor hast. Ich kann nix erkennen. Wahrscheinlich zeigst du und ^s jetzt bereits verarbeitete Daten. Das bringt nix. Du musst mit dem Oszi am Pin messen.

Oszi? Wo ist da ein Oszi?

Hatte ich schon mal angedeutet oder? Ferritring