Unlocking Publisher Data with ROS

Diagnosing PWM Value Issues in ROS Based Motor Control System

Recently, I encountered an intriguing issue while working on a robotic project that involves a ROS (Robot Operating System) based system interfaced with an Arduino for motor control. The core problem revolved around an unusual observation where the output of a PWM (Pulse Width Modulation) command was consistently showing a value of 50 when I expected it to vary dynamically based on inputs.

Understanding the Code Setup

Let’s first understand the code setup I have. The system uses multiple global variables and ROS subscribers to handle cmd_vel (command velocity) messages, which define the robot’s linear and angular movement commands. My Arduino script subscribes to these topics and uses callback functions to update relevant global variables (linear_value and angular_value).

float linear_value = 0;
float angular_value = 0;
void twistCallback(const geometry_msgs::Twist& twist_msg) {
  linear_value = twist_msg.linear.x;
  angular_value = twist_msg.angular.z;
}

These variables are then mapped from their typical range to a desired PWM value range and used to control motor speeds:

float ang_value = map(angular_value, -2, 2, 0, 100);
float lin_value = map(linear_value, -2, 2, 0, 100);
int pwm_value = lin_value + ang_value;
analogWrite(motorPin_r, lin_value);
analogWrite(motorPin_l, ang_value);

Pinpointing the Problem

Despite expecting a varying PWM output based on the linear_value and angular_value, the system only published a constant value of 50 for pwm_value. To debug, I closely examined each component of the system:

  1. Mapping Function: The Arduino map() function may not work as expected with floating-point numbers due to its usual handling of integer values. This unexpected behavior could lead to erroneous or truncated results. Debugging this part could involve printing the intermediate values right after mapping:

Serial.print("Mapped linear value: ");
   Serial.println(lin_value);

  1. PWM Calculation: I noticed that the calculation of pwm_value (pwm_value = lin_value + ang_value;) might not reflect a correct approach, especially if both lin_value and ang_value are not expressing the intended logic of motor control, and might lead to non-additive values reducing the dynamic range.
  1. Subscription Misconfiguration: Another observation was the subscription to pwm_value within the same node that publishes pwm_value:

ros::Subscriber<std_msgs::UInt8> sub_pwm("pwm_value", &pwmCallback);

This setup does not make sense in most practical scenarios since it creates a feedback loop or circular dependency where the node listens to its output.

Adjusting and Testing the Solution

To address these issues, I recommend:

  • Revising the PWM mapping to handle floating point directly or ensure adequate translation from float to integers.
  • Removing the unnecessary subscription to pwm_value which could interfere with proper value propagation.
  • Ensure that Angular and Linear values are correctly combined to reflect the desired behavior. For debugging, add serial print statements to monitor these dynamically.

Finally, to test, simulate varying cmd_vel messages from a ROS publisher on a computer, and monitor the adjustments on the Arduino serial monitor. By treating each variable and connection with precision, I was able to gradually refine the control logic, ensuring more responsive and accurate motor behaviors.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *