ROS2系列教程:实体机器人硬件搭建(原理) 本文是 ROS2 系列教程的第 31 篇本文是 ROS2 系列教程的第 31 篇实体机器人硬件搭建原理。第 26-30 篇我们打通了硬件控制全链路电机、舵机、传感器、MicroROS、ROS2-Control。但那些都是在零件层面。本篇开始进入实体机器人阶段31-34把前面所有的零件组装成一台能跑、能感知、能建图导航的真机器人。本篇聚焦硬件搭建的完整原理总体架构、选型、电气连接、电源管理、车架结构并给出计算与调试方法为第 32-34 篇的软件开发打基础。一、实体机器人总体架构1.1 经典两轮差速小车的组成一台能跑 ROS2 的最小实体机器人两轮差速小车由以下部分组成模块组成作用车架底盘板、连接件、轮子承载所有部件动力直流减速电机 ×2、编码器、电机驱动TB6612驱动车轮、测速下位机STM32 / ESP32电机闭环控制、传感器采集上位机树莓派 / Jetson Nano运行 ROS2、建图导航电源锂电池、稳压模块供电感知激光雷达、IMU、超声波环境感知通信USB 串口、Wi-Fi上/下位机通信经典数据流激光雷达 ─┐ IMU ──────┼→ 上位机(ROS2) ──/cmd_vel──→ 下位机(STM32) ──PWM──→ 电机驱动 ──→ 电机 超声波 ───┘ ↑ │ /odom ◄──── 编码器测速 ── 下位机闭环 ────────────────┘1.2 为什么选两轮差速两轮差速2WD是最适合入门和学习的底盘构型底盘类型优点缺点适合两轮差速结构简单、成本低、控制成熟只能原地旋转和前后走入门、室内、教学四轮差速负载大、越野转向需要滑移室外麦克纳姆轮全向移动、可横移贵、控制复杂、效率低竞赛、仓储阿克曼转向接近真车结构复杂、不能原地转室外车模两轮差速的运动学模型第 13 篇讲过给线速度 v 和角速度 ω换算左右轮速v_left (v - ω × L/2) / r v_right (v ω × L/2) / r 其中 L轮距r轮半径1.3 上下位机分工再明确上位机树莓派/Jetson跑 ROS2、SLAM、Nav2。算力强但功耗高5V 2-3A。下位机STM32电机闭环、编码器、超声波等实时性要求高的任务。功耗低、实时性强。分界点所有控制周期 ≤ 10ms的任务放下位机其余放上位机。二、硬件选型原理与要点2.1 电机选型机器人电机选择的核心参数参数说明选择要点减速比电机转速 vs 输出转速小车常用 1:30 ~ 1:90额定电压常见 3.7V/6V/12V与电池电压匹配额定转速输出轴 RPM小车 100-300 RPM 合适扭矩决定爬坡/加速能力越大越有力编码器每转脉冲数PPR至少 11-13 PPR配 4 倍频选型计算示例目标最高速度 0.5 m/s轮径 65mm半径 0.0325m轮子转速 v / (2πr) 0.5 / (2 × 3.14 × 0.0325) ≈ 2.45 转/秒 ≈ 147 RPM 电机减速前转速 147 × 减速比 选 1:30 减速比 → 电机 ≈ 4410 RPM合理常见 3000-12000 RPM 电机 所需扭矩估算车重 1kg摩擦系数 0.3加速度 1m/s² F m×a μ×m×g 1×1 0.3×1×9.8 ≈ 3.94 N 每轮扭矩 F×r / 2 / 效率 ≈ 3.94×0.0325/2/0.6 ≈ 0.107 N·m结论选择 12V、减速比 1:30、额定转速 ~5000RPM、扭矩 ≥ 0.15 N·m、带编码器的直流减速电机。2.2 上位机选型平台优点缺点建议树莓派 4B/5生态好、教程多、便宜算力一般、散热入门首选Jetson Nano/OrinGPU 算力强贵、功耗高视觉项目工控机稳定、接口全大、贵工业运行 ROS2 Humble 至少需要4GB 内存、16GB 存储、支持 USB3.0接激光雷达。2.3 激光雷达选型型号测距频率特点RPLIDAR A112m5.5Hz最经典性价比高YDLIDAR X410m6-7Hz国产性价比高RPLIDAR A2/A312-25m8-16Hz精度更高Livox Mid-36040m10Hz3D 雷达贵入门选 RPLIDAR A1 或 YDLIDAR X4 即可满足室内 SLAM。2.4 电源选型电池电压优点缺点18650 锂电2S/3S7.4/11.1V便宜、容量大需要保护板航模锂电 LiPo7.4-11.1V放电猛娇贵、怕过放磷酸铁锂6.4-9.6V安全、寿命长电压低电源架构关键锂电池11.1V ├── 降压模块 → 12V/5A → 电机驱动电机供电 ├── 降压模块 → 5V/3A → 树莓派上位机 └── 降压模块 → 5V/1A → STM32 传感器注意电机启动电流大电机供电必须与逻辑供电隔离至少分开走线、电容滤波否则电机一启动上位机就复位。三、电气连接与布线原理3.1 接线规范实体机器人接线是细节决定成败的环节规范如下电源线粗、信号线细电机线用 20AWG 以上信号线 26-28AWG。共地所有模块 GND 必须连在一起否则通信不稳定。上下位机串口交叉上位机 TX → 下位机 RX上位机 RX → 下位机 TX共地。屏蔽与隔离电机线与传感器线分开走避免干扰长线用双绞或屏蔽线。防反接电源入口加防反接二极管或防反接模块。3.2 完整接线清单示例电源 11.1V 电池 → 电源开关 → 分线排 ├─→ 5V/5A 降压 → 树莓派 5V/GND ├─→ 5V/2A 降压 → STM32 5V 传感器 VCC └─→ 12V 直供 → TB6612 VM电机电源 下位机STM32 PA0/PA1 → 左电机编码器 A/B PB6/PB7 → 右电机编码器 A/B或用定时器编码器模式 PA6/PA7 → TB6612 PWMA/PWMB PA4/PA5 → TB6612 AIN1/AIN2 PB0/PB1 → TB6612 BIN1/BIN2 PA8 → TB6612 STBY PA9/PA10→ 串口1 → 树莓派 UART115200 上位机树莓派 GPIO14/15 → 串口 → STM32 USB0 → RPLIDAR A1 I2C → IMU可选 雷达 RPLIDAR → 5V/GND USB3.3 电流估算防电源不足总电流估算满载树莓派 4B ~1.2A峰值 2.5A STM32 传感器 ~0.3A 激光雷达 ~0.4A 电机2 个堵转 2 × 1.5A 3A 合计 ~5A峰值 电池容量建议≥ 5000mAh2S/3S续航 1-2 小时 降压模块额定电机路 ≥ 5A逻辑路 ≥ 3A四、示例 1车架与结构设计原理4.1 车架结构要点重心低电池放最底层重心尽量贴近地面转弯更稳。重心居中电池、上位机尽量居中对称避免偏载导致跑偏。轮距与轴距轮距越宽越稳但转弯半径越大两轮小车通常轮距 车宽的 60-70%。驱动轮与万向轮两轮差速需要配 1-2 个万向轮牛眼轮/万向球做支撑。模块固定减震雷达、IMU 用硅胶垫防松动螺丝胶。4.2 建模辅助可选可以用 FreeCAD/Onshape 建 3D 模型验证干涉也可以用简单画图工具画布线图。实体搭建前先画一张俯视布局图标注每个模块位置和走线能省大量返工。五、示例 2下位机固件框架原理下位机 STM32 固件采用定时中断 状态机结构主循环处理通信定时中断处理控制// main.c 框架下位机固件主循环伪代码 关键逻辑#includemain.h#includemotor_driver.h#includeencoder.h#includepid.h#includeprotocol.h// 全局变量volatilefloattarget_v0,target_w0;// 目标线速度/角速度volatilefloatcurrent_v0,current_w0;// 10ms 控制定时器中断速度闭环voidHAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef*htim){if(htim-InstanceTIM6){// 1. 编码器测速 → 计算实际线/角速度floatv_leftencoder_speed(ENC_LEFT);// rad/sfloatv_rightencoder_speed(ENC_RIGHT);current_v(v_leftv_right)*WHEEL_RADIUS/2.0;current_w(v_right-v_left)*WHEEL_RADIUS/WHEEL_BASE;// 2. 逆运动学目标线/角速度 → 左右轮速floatwl(target_v-target_w*WHEEL_BASE/2.0)/WHEEL_RADIUS;floatwr(target_vtarget_w*WHEEL_BASE/2.0)/WHEEL_RADIUS;// 3. PID 闭环 → PWMmotor_left_set_speed((int)pid_update(pid_l,wl,v_left));motor_right_set_speed((int)pid_update(pid_r,wr,v_right));}}// 主循环处理串口协议帧intmain(void){HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_TIM6_Init();// 10ms 控制定时器MX_USART1_UART_Init();motor_init();HAL_TIM_Base_Start_IT(htim6);// 启动控制定时器protocol_frame_tframe;while(1){// 解析串口帧协议见第 29 篇帧头命令校验if(protocol_parse(frame)PROTOCOL_OK){switch(frame.cmd){caseCMD_SET_VEL:// 设置目标速度target_vframe.f32[0];target_wframe.f32[1];break;caseCMD_GET_ODOM:// 上位机查询里程计protocol_send_odom(current_v,current_w);break;caseCMD_RESET:// 复位__NVIC_SystemReset();break;}}}}这个框架体现了下位机的核心原则控制中断 通信主循环分离保证实时性。六、示例 3上位机串口通信节点Python上位机用 ROS2 节点与下位机通信订阅/cmd_vel打包发送读取里程计回传发布/odom# serial_bridge.py上位机-下位机串口桥ROS2 节点importrclpyimportserialimportstructfromrclpy.nodeimportNodefromgeometry_msgs.msgimportTwistfromnav_msgs.msgimportOdometryfromstd_msgs.msgimportHeaderclassSerialBridge(Node):FRAME_HEAD0xAA55def__init__(self):super().__init__(serial_bridge)# 串口配置与下位机一致self.serserial.Serial(/dev/ttyUSB0,115200,timeout0.02)# 订阅速度指令self.cmd_subself.create_subscription(Twist,/cmd_vel,self.on_cmd_vel,10)# 发布里程计self.odom_pubself.create_publisher(Odometry,/odom,10)self.timerself.create_timer(0.02,self.read_odom)# 50Hzdefon_cmd_vel(self,msg:Twist):# 打包帧头(2B) 命令(1B) 数据(8B float×2) 校验(1B)datastruct.pack(2ff,msg.linear.x,msg.angular.z)checksum0forbindata:checksum^b framestruct.pack(HB,self.FRAME_HEAD,0x01)databytes([checksum])self.ser.write(frame)defread_odom(self):# 读下位机回传帧简化固定格式bufself.ser.read(15)iflen(buf)!15:returnhead,cmdstruct.unpack(HB,buf[:3])ifhead!self.FRAME_HEADorcmd!0x02:returnv,wstruct.unpack(2f,buf[3:11])# 发布里程计简化仅速度实际工程应积分位姿odomOdometry()odom.headerHeader()odom.header.stampself.get_clock().now().to_msg()odom.header.frame_idodomodom.child_frame_idbase_linkodom.twist.twist.linear.xv odom.twist.twist.angular.zw self.odom_pub.publish(odom)defmain(argsNone):rclpy.init(argsargs)nodeSerialBridge()rclpy.spin(node)node.destroy_node()rclpy.shutdown()if__name____main__:main()验证链路# 终端 1启动串口桥ros2 run robot_bringup serial_bridge.py# 终端 2发速度指令观察电机是否转ros2 topic pub /cmd_vel geometry_msgs/msg/Twist\{linear: {x: 0.1}, angular: {z: 0.0}}--once# 终端 3查看里程计轮子转起来 /odom 才有数据ros2 topicecho/odom七、示例 4整机启动流程与调试launch实体机器人调试要分层验证先硬件后软件先单模块后整机。7.1 分层调试顺序第 1 层 电源各模块电压正常指示灯亮 第 2 层 下位机串口打印正常电机能转编码器有读数 第 3 层 通信上位机 serial_bridge 能收发ros2 topic 有数据 第 4 层 传感器雷达 /scan 正常IMU /imu 正常 第 5 层 建图导航SLAM 建图、Nav2 导航7.2 一键启动 launch# robot_bringup.launch.py整机启动串口桥 雷达 底盘状态fromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([# 串口桥上/下位机通信Node(packagerobot_bringup,executableserial_bridge.py,outputscreen),# 激光雷达驱动Node(packagerplidar_ros,executablerplidar_composition,parameters[{serial_port:/dev/ttyUSB1,frame_id:laser,angle_compensate:True}],outputscreen),# 发布 TFodom → base_link → laserNode(packagetf2_ros,executablestatic_transform_publisher,arguments[0,0,0.1,0,0,0,base_link,laser]),# 底盘状态发布/odom 已在串口桥里])启动后检查ros2 launch robot_bringup robot_bringup.launch.py# 验证话题ros2 topic list# 应看到/cmd_vel /odom /scan /tf ...# 验证 TF 树ros2 run tf2_tools view_frames# 生成 frames.pdf 检查坐标系八、常见问题与排障现象原因解决上位机反复重启电源不足/电机干扰电机与逻辑供电隔离加大电容单独供电电机不动但代码正常STBY 没拉高/电源没接电机路检查 TB6612 STBY 与 VM 电压车轮方向相反电机接线/编码器方向不一致软件里反转 IN 引脚或统一方向车跑偏直行走弧线左右轮速不等/机械不对称用 PID 速度闭环检查轮胎气压/磨损串口乱码波特率不一致/共地缺失统一 115200检查 GND 连接雷达扫描有盲区雷达安装位置遮挡雷达装在最高点避开云台/支架遮挡上电瞬间 USB 掉设备电流冲击加缓启动软启动模块或先上逻辑电再上动力电WiFi 丢包信号干扰/天线位置天线垂直朝上避开金属遮挡九、小结与下一篇预告本篇核心实体机器人 车架 动力电机/编码器/驱动 下位机 上位机 电源 感知。选型三要素电机减速比/扭矩/编码器、上位机算力 vs 功耗、电源电流估算与隔离。电气规范共地、电源隔离、信号线分离、防反接——细节决定稳定性。调试方法论分层验证电源→下位机→通信→传感器→整机用 launch 一键启动。至此实体机器人的骨架搭好了。下一篇第 32 篇进入嵌入式控制与通信开发原理仿真把第 31 篇的硬件框架落实成完整代码——下位机协议栈实现、里程计发布、传感器数据融合并在仿真环境里验证上/下位机通信的可靠性。敬请期待。