1. 项目背景与目标
在实际机器人开发中,ROS2作为机器人操作系统核心,经常需要与嵌入式硬件(如STM32)协同工作。飞控系统提供的IMU数据是机器人姿态感知的关键来源,而STM32则擅长执行底层硬件控制。通过串口通信将二者结合,可以实现高效的数据交换与硬件联动控制。
本项目要实现的效果是:ROS2节点订阅飞控发布的IMU话题数据,解析出横滚角(roll)和俯仰角(pitch)。当这两个姿态角的绝对值都小于30度时,通过串口向STM32发送字符'A',点亮板载LED;否则发送字符'B',熄灭LED。这种基础但实用的场景,是机器人嵌入式控制的典型应用。
我实际测试使用的环境是树莓派4B运行Ubuntu 22.04和ROS2 Humble,飞控为ArduCopter 4.0.7,STM32使用常见的F103系列。这个组合成本低、易获取,非常适合初学者上手实践。
2. STM32端程序编写
STM32端的任务很简单:监听串口数据,根据接收到的字符控制LED状态。我们先来看完整的代码实现:
#include "stm32f10x.h"
#include "Serial.h"
#include "Led.h"
#include "Delay.h"
uint8_t RxData;
int main(void) {
Serial_Init();
LED_Init();
while (1) {
if (Serial_GetRxFlag() == 1) {
RxData = Serial_GetRxData();
if(RxData == 'A') {
LED_ON();
} else {
LED_OFF();
}
}
}
}
这段代码的逻辑非常清晰:初始化串口和LED后,在主循环中不断检查是否收到串口数据。如果收到字符'A'就点亮LED,收到其他字符(主要是'B')就熄灭LED。
在实际项目中,我建议增加一些 robustness 设计。比如添加简单的协议校验,避免误触发。可以修改为接收固定格式的数据帧,例如:"CMD:A\n" 和 "CMD:B\n"。这样虽然增加了少量复杂度,但大大提高了通信可靠性。
LED和串口的初始化函数需要根据你使用的具体硬件来编写。如果你用的是STM32标准库,LED初始化可能像这样:
void LED_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC, GPIO_Pin_13);
}
串口初始化也需要配置相应的参数,确保与ROS2端的设置一致:115200波特率、8数据位、无校验位、1停止位。
3. 硬件连接与串口识别
将STM32通过USB转TTL模块连接到树莓派后,第一件事就是确认系统是否正确识别了串口设备。这个步骤看似简单,却是我见过最多初学者踩坑的地方。
在终端中输入以下命令查看串口设备:
ls -l /dev | grep ttyUSB
如果一切正常,你会看到类似这样的输出:


被折叠的 条评论
为什么被折叠?



