Esp32 car with xbox controller

Ich habe ein kleines Skript geschrieben, das den Motor und Servo abhängig von Trigger- und Stickwerten steuert. Das Skript funktioniert soweit. Leider ist es nicht möglich analogwrite zu benutzen, weil sich Motor und Servo dann nicht mehr steuern lassen bzw. alles machen aber nicht das was sie machen sollen. Mit analogwrite wäre es möglich die Motordrehzahl abhängig der Triggerwerte anzupassen. Mit digitalwrite kann ich jedoch bloß aus und anschalten (maximal Drehzahl)

Ich vermute das es den Unterschiedlichen PWM von Servo und Motor liegt. Ich möchte einen xiao esp32s3 sense nutzen. Ich weiß nicht inwiefern es möglich ist Unterschiedliche Module für die PWM generation zu nutzen oder ob dieser ESP32 das überhaupt kann.
Ich habe auch schon versucht ein PWM über rmt zu erzeugen. Leider hat das mehr schlecht als recht geklappt.

Hardware:
mx1508
xiao esp32s3 sense
SG90 servo
dc motor 130
3.7v battery

#include <ESP32Servo.h>
#include <XboxSeriesXControllerESP32_asukiaaa.hpp>

// Servo-Pin und Winkelbereich
const int MOTOR_IN1 = 8;
const int MOTOR_IN2 = 9;
const int SERVO_PIN = 7;

const int SERVO_MIN_PULSE_WIDTH = 500;  // Minimum Pulsweite in Mikrosekunden
const int SERVO_MAX_PULSE_WIDTH = 2500; // Maximum Pulsweite in Mikrosekunden

// Servo-Objekt
Servo myServo;

// Xbox Controller-Objekt
XboxSeriesXControllerESP32_asukiaaa::Core xboxController;

void setup() {
  Serial.begin(115200);
  Serial.println("Starting Xbox Controller and Servo Setup");

  // Servo initialisieren
  myServo.attach(SERVO_PIN, SERVO_MIN_PULSE_WIDTH, SERVO_MAX_PULSE_WIDTH);

  // Motor-Pins als Ausgang festlegen
  pinMode(MOTOR_IN1, OUTPUT);
  pinMode(MOTOR_IN2, OUTPUT);

  // Xbox Controller initialisieren
  xboxController.begin();
}

void loop() {
  xboxController.onLoop();
  if (xboxController.isConnected()) {
    Serial.println("connected");
    delay(100);
    if (xboxController.isWaitingForFirstNotification()) {
      Serial.println("waiting for first notification");
    } else {
      // Xbox Joystick-Werte erhalten
      int joyLHori = xboxController.xboxNotif.joyLHori;
      int joyLVert = xboxController.xboxNotif.joyLVert;
      uint16_t joystickMax = XboxControllerNotificationParser::maxJoy;





      int triggerLeft = xboxController.xboxNotif.trigLT;
      int triggerRight = xboxController.xboxNotif.trigRT;
      uint16_t triggerMax = XboxControllerNotificationParser::maxTrig;

      uint8_t scaledTriggerLeft = map(triggerLeft, 0, triggerMax, 0, 255);
      Serial.print("scaled Trigger Left: ");
      Serial.println(scaledTriggerLeft);
      uint8_t scaledTriggerRight = map(triggerRight, 0, triggerMax, 0, 255);      
      Serial.print("scaled Trigger Right: ");
      Serial.println(scaledTriggerRight);



      // Steuerung des Servos mit dem linken Joystick (horizontal)
      int servoPosition = map(joyLHori, 0, joystickMax, 0, 180);
      myServo.write(servoPosition);
      Serial.println("Servo Position: " + String(servoPosition));

      // Steuerung des DC-Motors mit dem linken Joystick (vertikal)
      if (scaledTriggerLeft > 0 && scaledTriggerRight == 0) { // Motor vorwärts
        digitalWrite(MOTOR_IN1, HIGH);
        digitalWrite(MOTOR_IN2, LOW);
        Serial.println("DC Motor: Forward");
      } else if (scaledTriggerRight > 0 && scaledTriggerLeft == 0) { // Motor rückwärts
        digitalWrite(MOTOR_IN1, LOW);
        digitalWrite(MOTOR_IN2, HIGH);
        Serial.println("DC Motor: Reverse");
      } else { // Motor stoppen
        digitalWrite(MOTOR_IN1, LOW);
        digitalWrite(MOTOR_IN2, LOW);
        Serial.println("DC Motor: Stopped");
      }
    }
  } else { // Hier den else-Block korrekt zuordnen
    Serial.println("Xbox Controller not connected");
        delay(100);
    if (xboxController.getCountFailedConnection() > 2) {
      ESP.restart();
    }
  }
}

die Funktion analogWrite() heißt bei ESP32 anders

Hier gibt es Hinweise dazu

Das LEDC analogwrite abgelöst hat wusste ich nicht. Jedoch funktioniert analogwrite problemlos wenn ich den Teil für den Servo aus dem skript entferne. Ich habe vor ein paar Tagen schon versucht mit den LEDC befehlen rum zuspielen jedoch habe ich weder eine Motordrehung noch eine Servo bewegung an der Hardware erreichen können.
Soweit ich weiß hat der Servo frequency 50hz und dutycycle 1-2ms dem zufolge müsste es so aussehen:
im setup:
ledcAttachChannel(7, 50, 12, 0)
zur steuerung:
ledcWrite(7, scaled_stick_value)
wobei scaled_stick_value von 1000-2000 geht und dem duty cycle entsprechen müsste

für den motor:
im setup:
ledcAttachChannel(8,500,8,1)
ledcAttachChannel(9,500,8,2)
zum steuern:
ledcwrite(8,scaledLeftTrigger)
ledcwrite(9,scaledRightTrigger)

(bitte korrigiert mich wenn was falsch ist bin neu auf dem Gebiet)
so habe ich das die Tage auch versucht aber ich konnte dem System kein gescheite Steuerung entlocken. Bei bewegung des Sticks hat sich dann zum beispiel der Motor angefangen zu drehen und der servo bloß ab und zu minimal bewegt.

Für Servo-Ansteuerung gibt es fertige libraries
google mal
Arduino Github ESP32 servo

Richtig diese wird auch im obigen Skript benutzt.
Jedoch vermute ich das die Servo libary im Konflikt stehen könnte.
Ich habe mir die ESP32Servo libary mal zu gemüte geführt dort scheint es so als würde das PWM wiederum eine andere libary (ESP32PWM.h) generiert werden.

#include <ESP32Servo.h>
#include <XboxSeriesXControllerESP32_asukiaaa.hpp>

// Servo-Pin und Winkelbereich
const int MOTOR_IN1 = 8;
const int MOTOR_IN2 = 9;
const int SERVO_PIN = 7;

const int SERVO_MIN_PULSE_WIDTH = 1000;  // Minimum Pulsweite in Mikrosekunden
const int SERVO_MAX_PULSE_WIDTH = 2000; // Maximum Pulsweite in Mikrosekunden

// Servo-Objekt
Servo myServo;

// Xbox Controller-Objekt
XboxSeriesXControllerESP32_asukiaaa::Core xboxController;

void setup() {
  Serial.begin(115200);
  Serial.println("Starting Xbox Controller and Servo Setup");

  // Servo initialisieren
  myServo.attach(SERVO_PIN, SERVO_MIN_PULSE_WIDTH, SERVO_MAX_PULSE_WIDTH);

  // Motor-Pins als Ausgang festlegen
  pinMode(MOTOR_IN1, OUTPUT);
  pinMode(MOTOR_IN2, OUTPUT);
  ledcAttachChannel(MOTOR_IN1, 500, 8, 1);
  ledcAttachChannel(MOTOR_IN2, 500, 8, 2);
  // Xbox Controller initialisieren
  xboxController.begin();
}

void loop() {
  xboxController.onLoop();
  if (xboxController.isConnected()) {
    Serial.println("connected");
    delay(100);
    if (xboxController.isWaitingForFirstNotification()) {
      Serial.println("waiting for first notification");
    } else {
      // Xbox Joystick-Werte erhalten
      int joyLHori = xboxController.xboxNotif.joyLHori;
      int joyLVert = xboxController.xboxNotif.joyLVert;
      uint16_t joystickMax = XboxControllerNotificationParser::maxJoy;





      int triggerLeft = xboxController.xboxNotif.trigLT;
      int triggerRight = xboxController.xboxNotif.trigRT;
      uint16_t triggerMax = XboxControllerNotificationParser::maxTrig;

      uint8_t scaledTriggerLeft = map(triggerLeft, 0, triggerMax, 0, 255);
      Serial.print("scaled Trigger Left: ");
      Serial.println(scaledTriggerLeft);
      uint8_t scaledTriggerRight = map(triggerRight, 0, triggerMax, 0, 255);      
      Serial.print("scaled Trigger Right: ");
      Serial.println(scaledTriggerRight);



      // Steuerung des Servos mit dem linken Joystick (horizontal)
      int servoPosition = map(joyLHori, 0, joystickMax, 0, 180);
      myServo.write(servoPosition);
      Serial.println("Servo Position: " + String(servoPosition));

      // Steuerung des DC-Motors mit dem linken Joystick (vertikal)
      if (scaledTriggerLeft > 0 && scaledTriggerRight == 0) { // Motor vorwärts
        ledcWrite(MOTOR_IN1, 0);
        ledcWrite(MOTOR_IN2, scaledTriggerLeft);
        Serial.println("DC Motor: Forward");
      } else if (scaledTriggerRight > 0 && scaledTriggerLeft == 0) { // Motor rückwärts
        ledcWrite(MOTOR_IN2, 0);
        ledcWrite(MOTOR_IN1, scaledTriggerRight);
        Serial.println("DC Motor: Reverse");
      } else { // Motor stoppen
        ledcWrite(MOTOR_IN1, 0);
        ledcWrite(MOTOR_IN2, 0);
        Serial.println("DC Motor: Stopped");
      }
    }
  } else { // Hier den else-Block korrekt zuordnen
    Serial.println("Xbox Controller not connected");
        delay(100);
    if (xboxController.getCountFailedConnection() > 2) {
      ESP.restart();
    }
  }
}

Das skript funktioniert soweit jedoch lässt sich der servo nur nach links bewegen.
In die andere Richtung bewegt er sich nur ein kleines Stückchen.

wenn ich bei
ledcAttachChannel(MOTOR_IN1, 500, 8, 1);
ledcAttachChannel(MOTOR_IN2, 500, 8, 2);
die frequency auf 50 setze funktioniert der servo perfekt jedoch der motor nicht

Ich habe nun die Dutycycle werte des Servos ein bissel angepasst
warum auch immer Bewegt sich der servo jetzt bloß ca. 45grad in gesamten
Das ist aber ausreichend für das Rc car
Für andere Projekte bzw. RC cars wäre es schon sehr interessant zuwissen warum der servo sich jetzt bloß 45grad statt den üblichen 180grad bewegt.

#include <ESP32Servo.h>
#include <XboxSeriesXControllerESP32_asukiaaa.hpp>

// Servo-Pin und Winkelbereich
const int MOTOR_IN1 = 8;
const int MOTOR_IN2 = 9;
const int SERVO_PIN = 7;

const int SERVO_MIN_PULSE_WIDTH = 1040;  // Minimum Pulsweite in Mikrosekunden
const int SERVO_MAX_PULSE_WIDTH = 2490; // Maximum Pulsweite in Mikrosekunden

// Servo-Objekt
Servo myServo;

// Xbox Controller-Objekt
XboxSeriesXControllerESP32_asukiaaa::Core xboxController;

void setup() {
  Serial.begin(115200);
  Serial.println("Starting Xbox Controller and Servo Setup");

  // Servo initialisieren
  myServo.attach(SERVO_PIN, SERVO_MIN_PULSE_WIDTH, SERVO_MAX_PULSE_WIDTH);
  // Motor-Pins als Ausgang festlegen
  pinMode(MOTOR_IN1, OUTPUT);
  pinMode(MOTOR_IN2, OUTPUT);
  ledcAttachChannel(MOTOR_IN2, 500, 8, 1);
  ledcAttachChannel(MOTOR_IN1, 500, 8, 2);
  // Xbox Controller initialisieren
  xboxController.begin();
}

void loop() {
  xboxController.onLoop();
  if (xboxController.isConnected()) {
    Serial.println("connected");
    delay(100);
    if (xboxController.isWaitingForFirstNotification()) {
      Serial.println("waiting for first notification");
    } else {
      // Xbox Joystick-Werte erhalten
      int joyLHori = xboxController.xboxNotif.joyLHori;
      int joyLVert = xboxController.xboxNotif.joyLVert;
      uint16_t joystickMax = XboxControllerNotificationParser::maxJoy;





      int triggerLeft = xboxController.xboxNotif.trigLT;
      int triggerRight = xboxController.xboxNotif.trigRT;
      uint16_t triggerMax = XboxControllerNotificationParser::maxTrig;

      uint8_t scaledTriggerLeft = map(triggerLeft, 0, triggerMax, 0, 255);
      Serial.print("scaled Trigger Left: ");
      Serial.println(scaledTriggerLeft);
      uint8_t scaledTriggerRight = map(triggerRight, 0, triggerMax, 0, 255);      
      Serial.print("scaled Trigger Right: ");
      Serial.println(scaledTriggerRight);



      // Steuerung des Servos mit dem linken Joystick (horizontal)
      int servoPosition = map(joyLHori, 0, joystickMax, 0, 180);
      myServo.write(servoPosition);
      Serial.println("Servo Position: " + String(servoPosition));

      // Steuerung des DC-Motors mit dem linken Joystick (vertikal)
      if (scaledTriggerLeft > 0 && scaledTriggerRight == 0) { // Motor vorwärts
        ledcWrite(MOTOR_IN1, 0);
        ledcWrite(MOTOR_IN2, scaledTriggerLeft);
        Serial.println("DC Motor: Forward");
      } else if (scaledTriggerRight > 0 && scaledTriggerLeft == 0) {
        ledcWrite(MOTOR_IN2, 0);
        ledcWrite(MOTOR_IN1, scaledTriggerRight);
        Serial.println("DC Motor: Reverse");
      } else { // Motor stoppen
        ledcWrite(MOTOR_IN1, 0);
        ledcWrite(MOTOR_IN2, 0);
        Serial.println("DC Motor: Stopped");
      }
    }
  } else { // Hier den else-Block korrekt zuordnen
    Serial.println("Xbox Controller not connected");
        delay(100);
    if (xboxController.getCountFailedConnection() > 2) {
      ESP.restart();
    }
  }
}

Hast du dir die mit der Servo-library mitgelieferten Beispiele angeschaut?

Hast du das Servo mal zuerst mit einem kleinen Test-Programm das einfach nur das Servo hin- und herfahren lässt getestet?

Hast du mal ausprobiert wie sich das Servo bewegt wenn du

const int SERVO_MIN_PULSE_WIDTH = 1200;  // Minimum Pulsweite in Mikrosekunden
const int SERVO_MAX_PULSE_WIDTH = 1800; // Maximum Pulsweite in Mikrosekunden

setzt?

Was für Werte werden denn in deinem

ausgegeben?
Wenn man die Parameter in der map-function falsch setzt dann können da ganz komische Werte herauskommen.

Hast du ein Digitalmultimeter dass Frequenz und duty-cycle messen kann?

Haste einen zweiten ESP32 mit du das Servosignal wieder einlesen kannst um mal zu messen was wirklich herauskommt.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.