ROS与STM32通信(一)-rosserial

硬件

  • STM32F103c8t6
  • OLED(I2C)
  • USB2TTL
  • Stlink

接线

OLED(GPIO模拟I2C)

硬件引脚
OLEDSCLPA4
OLEDSDAPA5

USART1

硬件引脚作用
RXPA9USART1_TX
TXPA10USART1_RX

LED

硬件引脚
LED0PC13
LED1PC15

软件

  • STM32CubeMX
  • Clion

STM32CubeMX配置

  • SYS->Debug->Serial Wire
  • RCC->HSE->Crystal/Ceramic Resonator
  • PC15->OutPut ,Label为LED0
  • PC13->OutPut ,Label为LED1
  • TIM1->Clock Source->Internal Clock
  • 时钟树,时钟设置为72M
  • USART1->Asynchronous Baud Rate: 115200

设置DMA

image-20230727095227292

开启串口中断

image-20230727095301013

rosserial

rosserial是ROS中的一个重要模块,它实现了ROS通信协议与各类嵌入式硬件平台之间的桥接,大大简化了ROS在底层硬件上的移植和应用。rosserial通过消息序列化和常用串行通信接口,实现了ROS主机和嵌入式客户端之间的消息交互,为各种嵌入式平台提供了C++和Python的ROS客户端库,使得在这些硬件上也能方便地使用ROS的通信架构来进行节点管理、话题通信和服务调用。rosserial还支持动态主题和服务,以较小的代码占用实现ROS功能,具有很强的可移植性。因此,rosserial是ROS物联网和机器人应用不可或缺的重要组件,极大地便利了ROS在各类嵌入式系统和小型机器人产品上的移植应用和开发。

rosserial_WIKI

image-20230727103754363

rosserial_stm32 Github地址

本文资源包stm32f103c8t6_rosserialCSDN资源下载

移植

下载上述资源stm32f103c8t6_rosserial

git clone https://github.com/GHigher12/STM32f103c8t6_rosserial.git

or 直接在CSDN下载

将RosLibs文件夹添加到stm32工作文件里

image-20230727160334430

还有Core文件夹中的mainpp.h , round.h, mainpp.cpp

此时如果用Clion作为开发环境还需要修改CMakeList.txt

包含文件的路径

main.c使用

//...
#include "mainpp.h"
//...
int main(void)
{
//...
  setup();
  while (1)
  {
      loop();
  }
  /* USER CODE END 3 */
}

上位机订阅-下位机发布

上位机订阅

python订阅 demo01_sub_py.py

#! /usr/bin/env python
import rospy
from std_msgs.msg import String

if __name__ == "__main__":
    rospy.init_node("ros_pc_pub")
    pub = rospy.Publisher("pc_to_stm32",String,queue_size=10)
    msg = String()
    msg_front = "ros_2_stm32->"
    count = 0
    rate = rospy.Rate(1)
    while not rospy.is_shutdown():
        msg.data = msg_front + str(count)
        pub.publish(msg)
        rate.sleep()
        rospy.loginfo("发布的数据为:%s",msg.data)
        count += 1

c++订阅 demo01_sub_c.cpp

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>


void doMsg(const std_msgs::String::ConstPtr &msg)
{
    ROS_INFO("订阅的数据为: %s", msg->data.c_str());
}

int main(int argc, char *argv[])
{

    setlocale(LC_ALL,"");
    ros::init(argc, argv, "ros_pc_sub");
    ros::NodeHandle nh;
    ros::Subscriber sub = nh.subscribe("stm32_to_pc", 10, doMsg);
    ros::spin();
    return 0;
}

安装rosserial_python

sudo apt-get install ros-noetic-rosserial-python

下位机发布

mainpp.cpp

#include <mainpp.h>
#include <ros.h>
#include <std_msgs/String.h>
#include "main.h"

ros::NodeHandle nh;

std_msgs::String stm32_to_pc_word;

ros::Publisher stm32_to_pc("stm32_to_pc", &stm32_to_pc_word);

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){
  nh.getHardware()->flush();
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
  nh.getHardware()->reset_rbuf();
}
char hello[13] = "hello ros!";
u8 cnt = 0;
void setup(void)
{
    nh.initNode();
	nh.advertise(stm32_to_pc);
}

void loop(void)
{
    cnt+=1;
    sprintf(oledBuf,"stm32_2_ros->%d",cnt);
    OLED_ShowString(0,24,(u8*)oledBuf,16);
    OLED_Refresh();
    stm32_to_pc_word.data = oledBuf;
    HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);
    HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
	HAL_Delay(1000);
	stm32_to_pc.publish(&stm32_to_pc_word);
	nh.spinOnce();
}

编译将程序烧录到stm32中

通信

将usb2ttl连接好usart1,连接电脑

执行下列命令

lsusb
ls /dev/ttyUSB*
sudo chmod 777 /dev/ttyUSB0

image-20230727162511985

启动rosserial_python节点

roscore
rosrun rosserial_python serial_node.py _port:=/dev/ttyUSB0 _baud:=115200

出现以下内容则表示运行正常

[INFO] [1690446448.903399]: ROS Serial Python Node
[INFO] [1690446448.908570]: Connecting to /dev/ttyUSB0 at 115200 baud
[INFO] [1690446451.013146]: Requesting topics...
[INFO] [1690446451.772474]: Note: publish buffer size is 512 bytes
[INFO] [1690446451.774498]: Setup publisher on stm32_to_pc [std_msgs/String]

可使用rostopic echo /stm32_to_pc查看话题

image-20230727163158146

不过这里会出现[ERROR] [1690446652.290474]: Lost sync with device, restarting...报错,导致收发频率不一致,博主现在还没解决,如有读者有解决办法,可在评论留言。

python订阅

cd ~/catkin_ws
source ./devel/setup.bash
rosrun hello_vscode demo01_sub_py.py

image-20230727163637705

c++订阅

cd ~/catkin_ws
source ./devel/setup.bash
rosrun hello_vscode demo01_sub_c

image-20230727163815409

下位机显示

image-20230727165726493

查看rqt_graph

image-20230727163848358

上位机发布-下位机订阅

上位机发布

python发布 demo01_pub_py.py

#! /usr/bin/env python
import rospy
from std_msgs.msg import String

if __name__ == "__main__":
    rospy.init_node("ros_pc_pub")
    pub = rospy.Publisher("pc_to_stm32",String,queue_size=10)
    msg = String()
    msg_front = "ros_2_stm32->"
    count = 0
    rate = rospy.Rate(1)
    while not rospy.is_shutdown():
        msg.data = msg_front + str(count)
        pub.publish(msg)
        rate.sleep()
        rospy.loginfo("发布的数据为:%s",msg.data)
        count += 1

c++发布 demo01_pub_c.cpp

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    ros::init(argc, argv, "ros_pc_pub");
    ros::NodeHandle nh;
    ros::Publisher pub = nh.advertise<std_msgs::String>("pc_to_stm32", 10);
    std_msgs::String msg;
    ros::Rate rate(1);
    int count = 0;
    ros::Duration(3).sleep();
    while (ros::ok)
    {
        count++;
        std::stringstream ss;
        ss << "ros_2_stm32->" << count;
        msg.data = ss.str();
        pub.publish(msg);
        ROS_INFO("发布的数据为: %s", ss.str().c_str());
        rate.sleep();
        ros::spinOnce();  //处理回调函数
    }
    return 0;
}

下位机订阅

mainpp.cpp

#include <mainpp.h>
#include <ros.h>
#include <std_msgs/String.h>
#include "main.h"
void command_callback( const std_msgs::String& rxbuff);

ros::NodeHandle nh;

std_msgs::String stm32_to_pc_word;

ros::Subscriber<std_msgs::String> cmd_sub("pc_to_stm32", command_callback);

void command_callback(const std_msgs::String &rxbuff)
{
    char oled_rxbuff[128];
    stm32_to_pc_word = rxbuff;
    snprintf(oled_rxbuff, sizeof(oled_rxbuff), "%s", rxbuff.data);
    OLED_ShowString(0,24, (u8*)oled_rxbuff,16);
    OLED_Refresh();
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){
  nh.getHardware()->flush();
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
  nh.getHardware()->reset_rbuf();
}
void setup(void)
{
    nh.initNode();
	nh.subscribe(cmd_sub);
}

void loop(void)
{
    HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);
    HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
	HAL_Delay(1000);
	nh.spinOnce();
}


通信

python发布

rosrun hello_vscode demo01_pub_py.py

image-20230727165011538

c++发布

rosrun hello_vscode demo01_pub_c

image-20230727165221524

下位机显示

image-20230727165700807

查看rqt_graph

image-20230727165258149

  • 6
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 安装rosserial库 在ros工作空间中运行以下命令: ``` $ sudo apt-get install ros-kinetic-rosserial-arduino $ sudo apt-get install ros-kinetic-rosserial ``` 2. 配置Arduino开发环境 将Arduino连接到计算机上,并在Arduino IDE中选择正确的板子和端口。然后,在“示例”菜单中选择“Firmata”,并上传到Arduino板子上。 3. 配置ROS节点 创建一个ROS节点来与Arduino通信。在ros工作空间中创建一个新的包,并在包中创建一个新的节点。 ``` $ cd ~/catkin_ws/src $ catkin_create_pkg my_robot roscpp rospy std_msgs $ cd my_robot $ mkdir include $ cd include $ touch my_robot_node.h $ cd .. $ touch CMakeLists.txt ``` 在my_robot_node.h文件中,添加以下内容: ```c++ #include <ros.h> #include <std_msgs/Int16.h> ros::NodeHandle nh; void messageCb(const std_msgs::Int16& msg) { // 处理接收到的消息 } ros::Subscriber<std_msgs::Int16> sub("my_topic", messageCb); void setup() { nh.initNode(); nh.subscribe(sub); } void loop() { nh.spinOnce(); } ``` 在CMakeLists.txt文件中,添加以下内容: ``` cmake_minimum_required(VERSION 2.8.3) project(my_robot) find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs ) catkin_package() include_directories( ${catkin_INCLUDE_DIRS} ) add_executable(my_robot_node src/my_robot_node.cpp) target_link_libraries(my_robot_node ${catkin_LIBRARIES} ) install(TARGETS my_robot_node RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} ) ``` 4. 配置Arduino代码 在Arduino IDE中打开Firmata代码,并添加以下内容: ```c++ #include <ros.h> #include <std_msgs/Int16.h> ros::NodeHandle nh; std_msgs::Int16 msg; ros::Publisher pub("my_topic", &msg); void setup() { nh.initNode(); nh.advertise(pub); } void loop() { msg.data = // 获取需要发送的数据 pub.publish(&msg); nh.spinOnce(); } ``` 5. 编译和上传代码 打开一个新的终端窗口,在ros工作空间中编译代码。 ``` $ cd ~/catkin_ws $ catkin_make ``` 然后,在Arduino IDE中上传代码到Arduino板子上。 6. 运行节点 在一个新的终端窗口中,运行ROS节点。 ``` $ rosrun my_robot my_robot_node ``` 现在,ROS节点和Arduino板子之间已经建立了串口通信。可以发送和接收数据了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值