Help! Cant seem to get three PWM channels working on the same controller

I am trying to code a drivetrain using two servo motors with differential style of turing and rotation using PWM signals. I have a contoller and im trying to achieve forward/backward movement and left/right movement on the right joystick and rotation (the motors spin in opposite directions so that it can turn in place) when moving the left joystick horizontally. The problem im getting is in my code i have three PWM channels but i cant seem to get the rotation and other movements working at the same time. For example the right josystick movement works perfectly but it doesnt respond to the left joystick movement, meaning it doesnt rotate. In terms of the motors im using big industrial ones. What could be the problem?

Heres my code:

#include <Servo.h>

#define RCPinFWD 2
#define RCPinSide 3
#define RCPinRotation 18

Servo leftMotor;
Servo rightMotor;

long PulsesFWD = 0;
long PulsesSide = 0;
long PulsesRotation = 0;

void setup() {
  // setup serial, pin mode
  Serial.begin(9600);
  pinMode(RCPinFWD, INPUT_PULLUP);
  pinMode(RCPinSide, INPUT_PULLUP);
  pinMode(RCPinRotation, INPUT_PULLUP);

  leftMotor.attach(5);
  rightMotor.attach(6);
}

void loop() {
  // Read pulse lengths
  PulsesFWD = pulseIn(RCPinFWD, HIGH);
  PulsesSide = pulseIn(RCPinSide, HIGH);
  PulsesRotation = pulseIn(RCPinRotation, HIGH);

  // save pulse lengths that are <2000ms
  int PulseWidthFWD = min(PulsesFWD, 2000);
  int PulseWidthSide = min(PulsesSide, 2000);
  int PulseWidthRotation = min(PulsesRotation, 2000);

  // Determine forward/backward speed and direction
  int leftMotorAngle = 90;
  int rightMotorAngle = 90;

  // Get initial value from forward channel
  leftMotorAngle = map(PulseWidthFWD, 1000, 2000, 0, 180);
  rightMotorAngle = map(PulseWidthFWD, 1000, 2000, 0, 180);

  // Correct for turning channel value
  int directionOfTurnSlowDown = 1;

  if (PulseWidthSide < 1500) {
    // Turning left
    if (leftMotorAngle > 90) {
      // If going forward
      directionOfTurnSlowDown = map(PulseWidthSide, 1000, 1499, 95, 85);
    } else {
      // If going backward
      directionOfTurnSlowDown = map(PulseWidthSide, 1000, 1499, 105, 115);
    }
    leftMotorAngle = (leftMotorAngle * directionOfTurnSlowDown) / 100;
  } else if (PulseWidthSide > 1500) {
    // Turning right
    if (rightMotorAngle > 90) {
      // If going forward
      directionOfTurnSlowDown = map(PulseWidthSide, 1501, 2000, 95, 85);
    } else {
      // If going backward
      directionOfTurnSlowDown = map(PulseWidthSide, 1501, 2000, 105, 115);
    }
    rightMotorAngle = (rightMotorAngle * directionOfTurnSlowDown) / 100;
  }

  // Calculate rotation angles
  int leftRotationAngle = 90;
  int rightRotationAngle = 90;

 // Update motor angles for left joystick control (rotation)
if (PulseWidthRotation < 1500) {
  // Move motors in opposite directions for rotation left
  int rotationAmount = map(PulseWidthRotation, 1000, 1499, -45, 0); // Adjust angle range as needed
  leftRotationAngle -= rotationAmount;
  rightRotationAngle += rotationAmount;
} else if (PulseWidthRotation > 1500) {
  // Move motors in opposite directions for rotation right
  int rotationAmount = map(PulseWidthRotation, 1501, 2000, 0, 45); // Adjust angle range as needed
  leftRotationAngle += rotationAmount;
  rightRotationAngle -= rotationAmount;
}

  // Control the servo motors
  leftMotor.write(leftMotorAngle);
  rightMotor.write(rightMotorAngle);

  // Debugging output
  Serial.print("PulseWidthFWD: ");
  Serial.print(PulseWidthFWD);
  Serial.print("   PulseWidthSide: ");
  Serial.print(PulseWidthSide);
  Serial.print("   PulseWidthRotation: ");
  Serial.println(PulseWidthRotation);

  Serial.print("Left motor angle: ");
  Serial.print(leftMotorAngle);
  Serial.print("   Right motor angle: ");
  Serial.println(rightMotorAngle);

  // Add a delay to control the update rate if needed
  delay(10); // Adjust this delay as needed
}

Welcome to the forum

You seem to be going to a lot of effort to calculate the required pulse widths and then convert them to angles. Why not work either in angles and use the write() function or in microseconds and use the writeMicroseconds() function ?

2 Likes

Can you post an annotated schematic showing how this is all connected. Also links to technical information on the hardware items will be a big help.

Tried both methods but for some reason either the motors dont respond at all or the movement is not fluid and stops randomly for a moment. Plus, im kinda new to working with arudino so im still trying to figure out things.This is code i wrote using the writeMicroseconds() function but for some reason its not responding. Im using the Radio Link at10 controller.

#include <Servo.h>

#define RCPinFWD 2
#define RCPinSide 3
#define RCPinRotation 18

Servo leftMotor;
Servo rightMotor;

void setup() {
  // setup serial, pin mode
  Serial.begin(9600);
  pinMode(RCPinFWD, INPUT_PULLUP);
  pinMode(RCPinSide, INPUT_PULLUP);
  pinMode(RCPinRotation, INPUT_PULLUP);

  leftMotor.attach(5);
  rightMotor.attach(6);
}

void loop() {
  // Read joystick angles
  int forwardAngle = map(analogRead(RCPinFWD), 1000, 2000, -90, 90);
  int sideAngle = map(analogRead(RCPinSide), 1000, 2000, -90, 90);
  int rotationAngle = map(analogRead(RCPinRotation), 1000, 2000, -90, 90);

  // Determine motor speeds based on joystick angles
  int leftMotorSpeed = forwardAngle + rotationAngle;
  int rightMotorSpeed = forwardAngle - rotationAngle;

  // Slow down motor speeds when turning
  int turningSlowDown = map(abs(sideAngle), 0, 90, 100, 85);
  leftMotorSpeed = (leftMotorSpeed * turningSlowDown) / 100;
  rightMotorSpeed = (rightMotorSpeed * turningSlowDown) / 100;

  // Convert speeds to microsecond values
  int leftMicros = map(leftMotorSpeed, -90, 90, 1000, 2000);
  int rightMicros = map(rightMotorSpeed, -90, 90, 1000, 2000);

  // Control the servo motors using writeMicroseconds()
  leftMotor.writeMicroseconds(leftMicros);
  rightMotor.writeMicroseconds(rightMicros);

  // Debugging output
  Serial.print("Forward Angle: ");
  Serial.print(forwardAngle);
  Serial.print("   Side Angle: ");
  Serial.print(sideAngle);
  Serial.print("   Rotation Angle: ");
  Serial.println(rotationAngle);

  Serial.print("Left Motor Speed: ");
  Serial.print(leftMotorSpeed);
  Serial.print("   Right Motor Speed: ");
  Serial.println(rightMotorSpeed);

  delay(10);
}

The RadioLink AT10 has pre built models for adaptability to all RC models. Did you make sure that you are using the remote in the multicopter mode?

Recenty in another thread it took 3 days and 50 postings to find out that the newcomers used a pretty old motordriver-board that required a certain library to make it work.

Your description "controller" is wayy to unprecise to give really helpful advice on the code. As we (the other users on the forum) can't look onto your table to see what controller this is
and
as we can't look into your head to see what kind of knowledge you have
there is only one way to solve your problems quickly:

Post a datasheet, the manual, or at least a picture of your "controller"
It might even be that it is not for servo-PWM but for "general"-PWM.

Describe your knowledge-level about electronics in general.

Trying to be fast through short postings is the best way to slow things down.

So please please
Post a datasheet, the manual, or at least a picture of your "controller"
and
Describe your knowledge-level about electronics in general.

It might turn out that you know quite a lot. We don't know it yet.

best regards Stefan

1 Like

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