welcom ! Handel home

2025年2月5日 星期三

(兩輪小車範例)PWM 訊號來自真實馬達控制板(如 Arduino 或 STM32)


✅ 讓 PWM 訊號來自真實馬達控制板(Arduino / STM32)

要讓 PWM 來自 Arduino 或 STM32,我們需要:

  1. 讓 ROS 2 與 Arduino / STM32 通訊(使用 ros2_serialros2_socketcan)。
  2. 讓 Arduino / STM32 接收 cmd_vel 並轉換為 PWM 訊號
  3. ros2_controlcmd_vel 控制馬達
  4. 測試並調整 PWM 轉速輸出

📌 1️⃣ 讓 ROS 2 與 Arduino / STM32 通訊

選擇通訊方式

方法硬體需求適用情境
USB (Serial)Arduino / STM32最簡單
CAN Bus (ros2_socketcan)STM32(有 CAN 模組)工業級應用
WiFi (ros2_microros / MQTT)ESP32 / STM32無線通訊

這裡我們用 Serial (USB) 作示範,適用於 Arduino 和 STM32


✅ 設定 ROS 2 與 Arduino 通訊

安裝 ros2_serial

sudo apt install ros-${ROS_DISTRO}-rosserial-arduino ros-${ROS_DISTRO}-rosserial

在 Arduino 上安裝 ROS 2

  1. 下載 Arduino ROS 庫
    cd ~/Arduino/libraries git clone https://github.com/ros-drivers/rosserial.git
  2. 在 Arduino IDE 中開啟 rosserial 範例
    • 選擇 ros_lib 庫,開啟 HelloWorld,確保 Arduino 能與 ROS 通訊。

📌 2️⃣ Arduino / STM32 轉換 cmd_vel 為 PWM

📜 Arduino 代碼

#include <ros.h> #include <geometry_msgs/Twist.h> // 定義 PWM 輸出腳位 #define LEFT_MOTOR_PWM 5 #define RIGHT_MOTOR_PWM 6 ros::NodeHandle nh; // 設定最大 PWM 值 const int MAX_PWM = 255; void cmdVelCallback(const geometry_msgs::Twist& msg) { float linear = msg.linear.x; // 直線速度 float angular = msg.angular.z; // 旋轉速度 // 轉換成 PWM 值 int left_pwm = constrain((linear - angular) * MAX_PWM, -MAX_PWM, MAX_PWM); int right_pwm = constrain((linear + angular) * MAX_PWM, -MAX_PWM, MAX_PWM); // 設定 PWM 輸出 analogWrite(LEFT_MOTOR_PWM, abs(left_pwm)); analogWrite(RIGHT_MOTOR_PWM, abs(right_pwm)); // 設定方向 (簡單 H 橋控制) digitalWrite(4, left_pwm > 0); digitalWrite(7, right_pwm > 0); } ros::Subscriber<geometry_msgs::Twist> sub("cmd_vel", cmdVelCallback); void setup() { nh.initNode(); nh.subscribe(sub); pinMode(LEFT_MOTOR_PWM, OUTPUT); pinMode(RIGHT_MOTOR_PWM, OUTPUT); pinMode(4, OUTPUT); // 左馬達方向 pinMode(7, OUTPUT); // 右馬達方向 } void loop() { nh.spinOnce(); delay(10); }

📌 3️⃣ 設定 ros2_control

📜 ros2_control.yaml 設定

controller_manager: ros__parameters: update_rate: 100 joint_state_broadcaster: type: joint_state_broadcaster/JointStateBroadcaster diff_drive_controller: type: diff_drive_controller/DiffDriveController diff_drive_controller: ros__parameters: left_wheel_names: ["left_wheel_hinge"] right_wheel_names: ["right_wheel_hinge"] publish_rate: 50 base_frame_id: "chassis" wheel_separation: 0.3 wheel_radius: 0.1 use_stamped_vel: false open_loop: false velocity_command_interface: "velocity" linear: x: has_velocity_limits: true max_velocity: 1.0 has_acceleration_limits: true max_acceleration: 1.5 angular: z: has_velocity_limits: true max_velocity: 2.0 has_acceleration_limits: true max_acceleration: 2.5

這讓 Gazebo 的 cmd_vel 直接發送給 Arduino / STM32


📌 4️⃣ 啟動 ROS 2 並測試

✅ 啟動 Arduino Serial 通訊

ros2 run rosserial_python serial_node.py /dev/ttyUSB0 _baud:=57600

/dev/ttyUSB0Arduino / STM32 的 USB 端口。

✅ 啟動 Gazebo

ros2 launch gazebo_ros gazebo.launch.py

✅ 啟動 ros2_control

ros2 control load_controller --set-state start joint_state_broadcaster ros2 control load_controller --set-state start diff_drive_controller

✅ 測試 cmd_vel

ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.5}, angular: {z: 0.0}}"
  • 這會讓 Arduino 讀取速度,並轉換成 PWM 訊號

🚀 你還需要什麼?

  1. 要把 PWM 訊號轉成 RPM 反饋回 ROS 2?
  2. 要讓 STM32 透過 CAN Bus 接收 cmd_vel
  3. 要測試 PID 控制,讓 PWM 更穩定?

沒有留言: