【ROS】ROS上位机使用Serial库和boost::asio库与STM32进行USART通讯

2023-05-16

系列文章目录

·【STM32】新建工程模板及配置

·【STM32】STM32与PC端、HC-06、ROS进行USART串口通信

·【ROS】ROS上位机使用Serial库和boost::asio库与STM32进行USART通讯

·【STM32】STM32F103C8T6+L298N通过PWM控制直流电机转速

·【STM32】STM32F103C8T6使用外部中断法和输入捕获法进行编码器测速

·【STM32】STM32F103C8T6实现直流电机速度PID控制


目录

系列文章目录

前言

一、Serial库

1.安装Serial库

2.进行串口通讯

(1)创建串口类

(2)串口初始化

(3)编写串口接收函数

(4)发送数据

(5)循环冗余校验

二、Boost::asio库通讯

1.创建相关对象

2.串口初始化

3.数据发送

4.接收数据

三、ROS节点

总结


前言

上一篇文章实现了STM32与各个系统进行USART通讯,这一片文章讲解ROS上位机部分与STM32下位机部分进行通讯的测试,这篇文章是测试程序,主要讲解库的使用,在具体功能实现时还需要进行大刀阔斧的更改,再以后会进行讲解。


一、Serial库

Serial库是ros自带的专门用来串口通讯的库,它的基本函数调用比较简单,功能包的函数解释可以参考它的原文档。

1.安装Serial库

先安装Serial库,并查看需要进行串口通讯的串口,这里提供了两种下载方式

方法一:直接安装

$ sudo apt-get install ros-<版本号>-serial

然后在需要用到serial库时,在新建功能包时添加serial的依赖即可。

方法二:通过github源码安装

有时候直接安装可能会出现无法定位项目的情况,比如20.04的ros,可以直接通过源码安装,不过连接可能会失败,可以连手机热点多试几次。

$ cd ~
$ cd catkin_ws/src
$ git clone https://github.com/wjwwood/serial.git

然后编译一下:

$ cd serial
$ make
$ make install

创建功能包时添加依赖:

$ catkin_create_package serial_test rospy roscpp serial geometry_msgs

2.进行串口通讯

我自己总结的ROS的Serial进行串口通讯的步骤如下:

(1)创建串口类

在使用serial库进行串口通讯之前需要建立一个serial对象,基于这个对象进行各种功能的实现。

serial::Serial sp;//创建一个serial对象

(2)串口初始化

串口初始化的过程包括设置超时、波特率、设置要打开的串口等等,其中的一些设置要与通信的另一方保持一致!

在进行初始化后,使用try-catch语句打开串口,serial::IOException& e则是serial库提供的错误提示类。

/********************************************************
函数功能:串口参数初始化
入口参数:无
出口参数:无
作者:K.Fire
日期:2022.02.10
********************************************************/
void Serial_Init()
{
    
    serial::Timeout to = serial::Timeout::simpleTimeout(100);//创建timeout
	serial::parity_t pt = serial::parity_t::parity_none;//创建校验位为0位
	serial::bytesize_t bt = serial::bytesize_t::eightbits;//创建发送字节数为8位
	serial::flowcontrol_t ft = serial::flowcontrol_t::flowcontrol_none;//创建数据流控制,不使用
	serial::stopbits_t st = serial::stopbits_t::stopbits_one;//创建终止位为1位
    
    sp.setPort("/dev/ttyUSB0");//设置要打开的串口名称
    sp.setBaudrate(9600);//设置串口通信的波特率
    sp.setParity(pt);//设置校验位
    sp.setBytesize(bt);//设置发送字节数
    sp.setFlowcontrol(ft);//设置数据流控制
    sp.setStopbits(st);//设置终止位
    
    sp.setTimeout(to);//串口设置timeout

    try
    {
        //打开串口
        sp.open();
    }
    catch (serial::IOException& e)
    {
        ROS_ERROR_STREAM("Unable to open port.");
        return;
    }
}

其中用到的函数可以在官方文档中查到,如下图:

当然其实这些可以不设置,如果不进行手动设置的话,serial库也为我们准备了一套默认设置,在这里可以看到:

 timeout分为全局超时和间隔超时,简单来说,全局超时用来规定整个传输过程的总时长,如果超过这个时间,就会直接返回;间隔超时是在读或写后触发的超时,在接收到一个数据时超时开始计时,如果在规定时间内接收到下一个数据则说明接收未完,继续接收,如果未收到数据则直接返回。

(3)编写串口接收函数

串口接收功能的实现主要依赖于这个函数:sp.read(buf,n)

我们也可以使用sp.available函数获取接收缓冲区的字节数,或者使用sp.isopen函数判断串口是否打开。

在接收数据时,我们一般建立一个接收缓存数据buf[]进行数据接收,也可以使用ROS_INFO或者std::out将数据打印输出到终端上。

下面是我针对STM32下位机通讯编写的测试程序,在测试时,我是连接到了HC-06上进行的测试,因为买的单片机还没到。

在正式开始函数编写之前先做一些准备工作:

#include <serial/serial.h>
#include "MbotRosSerial.h"
#include <iostream>

/********************************************************
            串口发送接收相关常量、变量、共用体对象
********************************************************/
const unsigned char ender[2] = { 0x0d, 0x0a };
const unsigned char header[2] = { 0x55, 0xaa };

serial::Serial sp;//创建一个serial对象

//发送左右轮速控制速度共用体
union sendData
{
    short d;
    unsigned char data[2];
}leftVelSet, rightVelSet;

//接收数据(左轮速、右轮速、角度)共用体(-32767 - +32768)
union receiveData
{
    short d;
    unsigned char data[2];
}leftVelNow, rightVelNow, angleNow;

其中在接收过程中使用到了C语言的结构-共用体,以上述程序中的union sendData为例,它的作用简单来说是,其中的两个变量short和unsigned char data[2]公用一段内存,可以根据名字区分两个变量,这个共用体的占用字节数是成员变量中最大的字节数,这里的两个成员变量占用字节数都是2个字节。

在线程序可以看到,我将接收的速度和航向角存到了data[2]数组中,但是在赋值时我们需要的是double类型的变量,这时就可以将d赋值给接收的变量,因为它们公用一块内存。

关于union的知识大家可以查找相关的详细解释。

/********************************************************
函数功能:读取下位机数据,左右轮速度值、航向角、控制信息
入口参数:左右轮速度值、航向角、控制信息
出口参数:bool
作者:K.Fire
日期:2022.02.10
********************************************************/
bool ReceiveSTM32(double& Left_v, double& Right_v, double& Angle, unsigned char& CtrlCmd)
{
    char i, length = 0;
    unsigned char checkSum;
    unsigned char buf[150] = { 0 };
    int n;//信息长度

    size_t Receive_N = sp.available();//获取缓冲区内的字节数
    if (Receive_N  != 0)
    {
        n = sp.read(buf, Receive_N );//读出数据

        // 检查信息头
        if (buf[0] != header[0] || buf[1] != header[1])   //buf[0] buf[1]
        {
            ROS_ERROR("Received message header error!");
            return false;
        }

        //读取控制位
        CtrlCmd = buf[2];    //buf[2]

        //读取数据长度
        length = buf[3];    //buf[3]

        // 检查信息校验值
        checkSum = getCrc8(buf, 4 + length);             //buf[10] 计算得出
        if (checkSum != buf[4 + length])                 //buf[10] 串口接收
        {
            ROS_ERROR("Received data check sum error!");
            return false;
        }

        // 读取速度值和航向角
        for (i = 0; i < 2; i++)
        {
            leftVelNow.data[i] = buf[i + 4]; //buf[4] buf[5]
            rightVelNow.data[i] = buf[i + 6]; //buf[6] buf[7]
            angleNow.data[i] = buf[i + 8]; //buf[8] buf[9]
        }
        Left_v = leftVelNow.d;
        Right_v = rightVelNow.d;
        Angle = angleNow.d;

        return true;
    }

}

 其中用到的循环冗余校验函数在下面会写出。

(4)发送数据

发送数据主要使用sp.write(buf,n)函数,write函数有多种形式,可以在文档中查看使用,这里我使用的是第一种传入数据存储数组的首地址和发送字节长度的形式,返回值是实际写入串口的字节数,可以通过返回值判断是否发送成功,当然判断的过程在STM32端实现即可。

 具体发送数据的代码如下:

/********************************************************
函数功能:将对机器人的左右轮子控制速度,打包发送给下位机
入口参数:机器人线速度、角速度
出口参数:无
作者:K.Fire
日期:2022.02.10
********************************************************/
void SendSTM32(double Left_v, double Right_v, unsigned char CtrlCmd)
{
    unsigned char buf[11] = { 0 };//发送数组
    int i, length = 4;

    leftVelSet.d = Left_v;//mm/s
    rightVelSet.d = Right_v;

    // 设置消息头
    for (i = 0; i < 2; i++)
        buf[i] = header[i];             //buf[0]  buf[1]

    //设置控制位
    buf[2] = CtrlCmd;                   //buf[2]

    //设置数据长度
    buf[3] = length;                     //buf[3]

    // 设置机器人左右轮速度
    for (i = 0; i < 2; i++)
    {
        buf[i + 4] = leftVelSet.data[i];  //buf[4] buf[5]
        buf[i + 6] = rightVelSet.data[i]; //buf[6] buf[7]
    }

    // 设置校验值、消息尾
    buf[4 + length] = getCrc8(buf, 3 + length);//buf[8]
    buf[5 + length] = ender[0];     //buf[9]
    buf[6 + length] = ender[1];     //buf[10]

    // 通过串口下发数据
    sp.write(buf, 11);
}

(5)循环冗余校验

这没啥说的,具体内容看计算机组成原理吧。

/********************************************************
函数功能:获得8位循环冗余校验值
入口参数:数组地址、长度
出口参数:校验值
********************************************************/
unsigned char getCrc8(unsigned char* ptr, unsigned short len)
{
    unsigned char crc;
    unsigned char i;
    crc = 0;
    while (len--)
    {
        crc ^= *ptr++;
        for (i = 0; i < 8; i++)
        {
            if (crc & 0x01)
                crc = (crc >> 1) ^ 0x8C;
            else
                crc >>= 1;
        }
    }
    return crc;
}

二、Boost::asio库通讯

boost::asio库也是用来串口通讯的,这个库好像是C++库提供的,不需要自己再进行安装。

因为官方对于这个库的解释比较冗长,我也没仔细看,是通过看别人的实例程序一知半解,分享给大家参考。

1.创建相关对象

using namespace std;
using namespace boost::asio;
//串口相关对象
boost::asio::io_service iosev;
boost::asio::serial_port sp(iosev, "/dev/ttyUSB0");
boost::system::error_code err;

2.串口初始化

void serialInit()
{
    sp.set_option(serial_port::baud_rate(115200));
    sp.set_option(serial_port::flow_control(serial_port::flow_control::none));
    sp.set_option(serial_port::parity(serial_port::parity::none));
    sp.set_option(serial_port::stop_bits(serial_port::stop_bits::one));
    sp.set_option(serial_port::character_size(8));    
}

3.数据发送

void writeSpeed(double Left_v, double Right_v,unsigned char ctrlFlag)
{
    unsigned char buf[11] = {0};//
    int i, length = 0;

    leftVelSet.d  = Left_v;//mm/s
    rightVelSet.d = Right_v;

    // 设置消息头
    for(i = 0; i < 2; i++)
        buf[i] = header[i];             //buf[0]  buf[1]
    
    // 设置机器人左右轮速度
    length = 5;
    buf[2] = length;                    //buf[2]
    for(i = 0; i < 2; i++)
    {
        buf[i + 3] = leftVelSet.data[i];  //buf[3] buf[4]
        buf[i + 5] = rightVelSet.data[i]; //buf[5] buf[6]
    }
    // 预留控制指令
    buf[3 + length - 1] = ctrlFlag;       //buf[7]

    // 设置校验值、消息尾
    buf[3 + length] = getCrc8(buf, 3 + length);//buf[8]
    buf[3 + length + 1] = ender[0];     //buf[9]
    buf[3 + length + 2] = ender[1];     //buf[10]

    // 通过串口下发数据
    boost::asio::write(sp, boost::asio::buffer(buf));
}

其实和serial库差不多,前面的数据处理都是一样的,都是按照我们自己定义的协议进行的,只是发送的函数定义不一样而已,这里write函数时传入了串口对象和buf数组。

4.接收数据

bool readSpeed(double &Left_v,double &Right_v,double &Angle,unsigned char &ctrlFlag)
{
    char i, length = 0;
    unsigned char checkSum;
    unsigned char buf[150]={0};
    //=========================================================
    //此段代码可以读数据的结尾,进而来进行读取数据的头部
    try
    {
        boost::asio::streambuf response;
        boost::asio::read_until(sp, response, "\r\n",err);   
        copy(istream_iterator<unsigned char>(istream(&response)>>noskipws),
        istream_iterator<unsigned char>(),
        buf); 
    }  
    catch(boost::system::system_error &err)
    {
        ROS_INFO("read_until error");
    } 
    //=========================================================        

    // 检查信息头
    if (buf[0]!= header[0] || buf[1] != header[1])   //buf[0] buf[1]
    {
        ROS_ERROR("Received message header error!");
        return false;
    }
    // 数据长度
    length = buf[2];                                 //buf[2]

    // 检查信息校验值
    checkSum = getCrc8(buf, 3 + length);             //buf[10] 计算得出
    if (checkSum != buf[3 + length])                 //buf[10] 串口接收
    {
        ROS_ERROR("Received data check sum error!");
        return false;
    }    

    // 读取速度值
    for(i = 0; i < 2; i++)
    {
        leftVelNow.data[i]  = buf[i + 3]; //buf[3] buf[4]
        rightVelNow.data[i] = buf[i + 5]; //buf[5] buf[6]
        angleNow.data[i]    = buf[i + 7]; //buf[7] buf[8]
    }

    // 读取控制标志位
    ctrlFlag = buf[9];
    
    Left_v  =leftVelNow.d;
    Right_v =rightVelNow.d;
    Angle   =angleNow.d;

    return true;
}

这里的接收应该是用的read_until函数,但下面一顿操作我懒得查了,估计是数据结构的问题,应该是把数据接收到了迭代器,然后又转换成buf数组了吧。

循环冗余检验和上面是一样的,就不再重复写了。

三、ROS节点

ros节点中我是准备了几个测试数据,进行收发。

#include "ros/ros.h"
#include "std_msgs/String.h"
#include "MbotRosSerial.h"

//test send value
double testSend1=5555.0;
double testSend2=2222.0;
unsigned char testSend3=0x07;

//test receive value
double testRece1=0.0;
double testRece2=0.0;
double testRece3=0.0;
unsigned char testRece4=0x00;

int main(int argc,char **argv)
{
	ros::init(argc,argv,"serial_test");//节点初始化
	ros::NodeHandle n;//创建节点句柄
	
	ros::Rate loop_rate(10);
	
	//串口初始化
	Serial_Init();
	
	while(ros::ok())
	{
		//发送数据
		SendSTM32(testSend1,testSend2,testSend3);
		//接收数据
		ReceiveSTM32(testRece1,testRece2,testRece3,testRece4);
		//打印数据
		ROS_INFO("Receive Data is: %f,%f,%f,%d\n",testRece1,testRece2,testRece3,testRece4);
		
		ros::spinOnce();
		loop_rate.sleep();
	}
	return 0;
}

 前面就是一些头文件的包含和编写ros节点需要的固定格式,在while循环里就是简单的进行了数据的收发,然后对cmakelist文件进行修改。

主要在这几个地方进行了修改

cmake_minimum_required(VERSION 3.0.2)
project(mbot)

find_package(catkin REQUIRED COMPONENTS
  geometry_msgs
  roscpp
  rospy
  serial
)

catkin_package(
  INCLUDE_DIRS include
#  LIBRARIES mbot
#  CATKIN_DEPENDS geometry_msgs roscpp rospy serial
#  DEPENDS system_lib
)

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
  include
  ${catkin_INCLUDE_DIRS}
)


add_executable(serial_test src/serial_test.cpp
			   src/MbotRosSerial.cpp)
add_dependencies(serial_test ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(serial_test ${catkin_LIBRARIES})

总结

使用serial进行串口通讯的测试程序在此,需要boost::asio程序可以私信或者评论获取。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【ROS】ROS上位机使用Serial库和boost::asio库与STM32进行USART通讯 的相关文章

  • 使用 ctypes 从 python 访问 boost::进程间共享内存块

    我在 Windows 上运行的 C 程序中有一个结构 我想使用 ctypes 通过 Python 中的共享内存来访问该结构 例如 define MAX ENTITIES 30 struct State double x double y d
  • Qt 在信号/槽中使用 boost::shared_ptr

    是否可能 如果可以 如何在 Qt 中创建一个对共享指针常量引用的信号 槽 我想要一个如下所示的信号 void signal shared ptr
  • 增强元组+变换

    是否可以进行以下操作 假设我的 boost 元组有
  • Xcode 找不到 cstddef

    由于某种原因 Xcode iOS 无法找到我正在使用的库 Boost 的 cstddef 有谁知道如何解决这一问题 我正在 Mac OS X 10 8 下使用 Xcode 4 6 进行编译 你应该让你的项目全部为 Objective C 将
  • 当端点和 PMA 地址均更改时,CubeMX 生成的 USB HID 设备发送错误数据

    我正在调试我正在创建的复合设备的问题 并在新生成的仅 CubeMX 代码中重新创建了该问题 以使其更容易解决 我添加了少量代码main 让我发送 USB HID 鼠标点击 并在按下蓝色按钮时使 LED 闪烁 uint8 t click re
  • 如何使用 boost::serialization 序列化 std::vector ?

    class workflow private friend class boost serialization access template
  • 使用Boost获取成员函数的数量和参数类型? (升压::function_traits)

    对于普通的普通函数来说 它工作得很好 下面的代码工作得很好 它只打印应该的内容 int cdecl int char 2 int char include
  • 在 C++ 中传递参数到 boost odeint

    This https stackoverflow com questions 33856910 passing runtime parameters to odeint integrator 答案很有帮助 但我想知道如何将不同类型的多个参数
  • C++ Boost.asio Ping

    我正在尝试编写一个程序来列出网络上设备的所有 IP 地址 其主要组成部分之一是能够对设备执行 ping 操作 这个程序必须在Linux Windows和Mac上运行 所以我选择了Boost库 我设法在文档中找到这个示例 http www b
  • 将升级锁排除在 N3568 提案之外的原因是什么

    我对此进行了一些谷歌搜索 但只找到了很少的信息 N3568 http www open std org jtc1 sc22 wg21 docs papers 2013 n3568 html Wording包括升级锁概念的规范 但升级部件当时
  • 移动数组中的元素

    我需要一点帮助 我想将数组中的元素向上移动一个元素 以便新位置 1 包含位置 1 中的旧值 new 2 包含 old 1 依此类推 旧的最后一个值被丢弃 第一个位置的新值是我每秒给出的新值 我使用大小为 10 的数组 uint32 t TE
  • boost::property_map 在 boost 中是如何实现的以及如何更改它

    我想知道属性映射是如何在提升图中实现的 例如 我的顶点和边属性定义如下 vertex property gt struct NodeInfo int a b c actual bundled property struct NodeInfo
  • cmake 找不到 boost 库,因为它查找错误的文件名

    我根据文档在 Windows 8 1 机器上构建了 boost 1 56 库 作为共享库和静态库 他们全部出现在BOOST ROOT stage lib目录 文件名格式如下 boost thread vc120 mt 1 56 dll bo
  • 在类中使用静态互斥体

    我有一个可以有很多实例的类 它在内部创建并初始化来自第三方库 使用一些全局变量 的一些成员 并且不是线程安全的 我考虑过使用 static boost mutex 它将被锁定在我的类构造函数和析构函数中 因此 在我的线程中创建和销毁实例对于
  • [现代] C++ 中 N 个变量的范围/循环

    遍历 N 个任意类型的变量来执行操作的简洁方法是什么 假设我有变量a b c d e并想要对他们所有人进行一些操作 使用 Boost Hana 和通用 lambda include
  • Xcode 4 上的 Boost 库静态链接

    我在 OS X 上使用 Xcode 使用 Boost 库 Boost 使用 macports 安装在我的系统上 通过将我需要的 3 个 boost 库 例如 libboost thread mt a 添加到 Targets Link Bin
  • 安装 ROS 时 Cmake 未检测到 boost-python

    我一直在尝试在我的 Mac 上安装 ROS 并根据不同版本的 boost 使用不同的库解决了错误 然而 似乎有一个库甚至没有检测到 boost python 这是我得到的错误 CMake Error at usr local share c
  • 在 boost 元组、zip_iterator 等上使用 std::get 和 std::tie

    我有哪些使用选择std get lt gt and std tie lt gt 与增强结构一起 例子 我想使用基于范围的 for 循环在多个容器上进行迭代 我可以实施zip函数 它使用boost zip iterator include
  • 信号与信号2

    我的应用程序可能会受益于使用 boost 的信号库之一而不是本土解决方案 该应用程序是多线程的 但执行信号处理的部分是单线程的 如果多线程不是问题 是否有任何理由更喜欢 Boost Signals2 而不是 Boost Signal Boo
  • 如何查找boost运行时版本

    我正在编写一个使用 boost 的 C 库 在这个库中 我想包含有关用于编译我的库的二进制版本的 boost 版本的信息 我可以使用宏BOOST VERSION这很好 我还想确定哪个是 boost 的运行时版本 以便我可以与用于编译我的库的

随机推荐

  • php导出word文件,打开损坏或者乱码

    下载Word文件 fileinfo 61 pathinfo fullname ob end clean header 39 Content type application x 39 fileinfo 39 extension 39 hea
  • FreeRTOS操作系统优先级翻转问题(八)

    FreeRTOS总结 文章目录 前言一 浅浅了解优先级翻转二 模拟 优先级翻转实验1 代码 总结 前言 在使用二值信号量的时候会遇到很常见的一个问题 优先级翻转 xff0c 优先级翻转在可剥夺 内核中是非常常见的 xff0c 在实时系统中不
  • 伽马分布,指数分布,卡方分布三者关系

    1 伽马分布是一个连续概率分布 xff0c 具有两个参数 alpha 和 lambda xff0c 记为
  • 数据结构 马踏棋盘 栈应用 C++

    include lt iostream gt 包含其它头文件 using namespace std const int StackInitSize 61 10 const int StackInc 61 10 typedef int SE
  • STM32智能小车------红外遥控

    文章目录 一 原理讲解1 实物图2 工作原理 xff1a 3 接线 xff1a 二 软件驱动代码1 驱动函数2 获取键值 总结最终效果 大家好哇 xff01 我是小光 xff0c 嵌入式爱好者 xff0c 一个想要成为系统架构师的普通大学生
  • UCOS学习(一)——前后台系统、RTOS系统

    大家好哇 xff01 我是小光 xff0c 嵌入式爱好者 xff0c 一个想要成为系统架构师的大二学生 最近开始学习UCOS操作系统 xff0c 后面会更新一些关于UCOS学习笔记 今天了解了UCOS操作系统 xff0c 总结一下知识点 感
  • UCOS学习(二)——UCOS-II、UCOS-III移植到STM32F103

    大家好哇 xff01 我是小光 xff0c 嵌入式爱好者 xff0c 一个想要成为系统架构师的大二学生 最近开始学习UCOS操作系统 xff0c 后面会更新一些关于UCOS学习笔记 今天学习了如何将UCOS II和UCOS III移植到ST
  • UCOS学习(三)——任务管理基础

    大家好哇 xff01 我是小光 xff0c 嵌入式爱好者 xff0c 一个想要成为系统架构师的大二学生 最近开始学习UCOS操作系统 xff0c 后面会更新一些关于UCOS学习笔记 今天学习了任务管理基础知识 感谢你的阅读 xff0c 不对
  • UCOS学习(七)——信号量详解

    信号量 信号量简介信号量保护共享资源举个栗子 xff1a 如果不使用信号量信号量解决公共资源问题创建信号量 xff1a 信号量实现任务同步总结 信号量简介 信号量像是一种上锁机制 xff0c 代码必须获得对应的钥匙才能继续执行 xff0c
  • Altium Designer(AD)的简易使用

    一 绘制原理图 原理图库 首先来说明原理图的概念 根据百度百科 xff0c 原理图 xff0c 顾名思义就是表示电路板上各器件之间连接原理的图表 也就是表示芯片上的引脚连接什么元件 xff0c 各个元件谁和谁相连 xff0c 电源电压的大小
  • STM32CubeIDE---HAL库PWM使用速记

    一 如何计算 理论分析 xff1a HAL库函数之呼吸灯 PWM波 简书 jianshu com 预分频系数 PSC 自动重装载值 ARR 捕获 比较寄存器值 CCR 频率计算 xff1a 定时器频率 PSC 43 1 ARR 43 1 占
  • mac常用命令

    mac清除电脑DNS缓存 sudo dscacheutil flushcache
  • IMU初介绍及里程计相关补充

    IMU原理 xff1a 以牛顿力学定律为基础 xff0c 通过测量载体在惯性参考系的加速度 xff0c 将它对时间进行积分 xff0c 且把它变换到导航坐标系中 xff0c 就能够得到在导航坐标系中的速度 偏航角和位置等信息 IMU xff
  • C语言变量的定义与声明,为什么全局变量不能赋值

    文章目录 一 对C语言程序的一些补充二 定义域声明2 1 什么是变量2 2 如何定义变量2 3 为什么要定义变量2 4 定义变量的本质2 5 变量声明的本质2 6 定义和声明的区别 三 全局变量无法赋值 一 对C语言程序的一些补充 对于一个
  • 野火PID上位机通信移植

    野火PID上位机通信移植 一 简介 在调试pid参数的时候 xff0c 需要用到上位机 xff0c 这里选用 野火多功能调试助手 使用调试助手 xff0c 需要下位机与上位机之间的通信协议 xff0c 下载野火关于电机的相关例程 xff0c
  • 实验报告数字图像的基本操作

    一 实验目的 了解Matlab的基本功能及操作方法练习图像读写和显示函数的使用方法掌握如何利用MATLAB来获取图像的大小 颜色 高度 宽度等等相关信息熟悉常用的图像文件格式与格式转换 xff1b 二 实验环境 PC计算机MatLab软件
  • 【meArm机械臂】第二篇·Arduino控制程序

    系列文章目录 meArm机械臂 第一篇 结构设计及搭建 meArm机械臂 第二篇 Arduino控制程序 文章目录 系列文章目录前言一 测试程序1 单个电机测试程序2 四舵机控制测试程序3 极限位置测量 二 基本控制程序三 最终控制程序总结
  • 【树莓派4B】安装Ubuntu Mate20.04+ROS Noetic+使用电脑自带的xrdp和VNC进行PC端远程控制

    目录 前言 一 烧录Ubuntu Mate20 04 1 下载Ubuntu Mate 20 04 2 格式化SD卡并烧录系统 3 打开SSH功能 二 配置Ubuntu环境 1 初次开机进行简单的配置 2 更换国内源 3 更新软件列表和软件
  • 【STM32】STM32F103C8T6+L298N通过PWM控制直流电机转速

    系列文章目录 STM32 新建工程模板及配置 STM32 STM32与PC端 HC 06 ROS进行USART串口通信 ROS ROS上位机使用Serial库和boost asio库与STM32进行USART通讯 STM32 STM32F1
  • 【ROS】ROS上位机使用Serial库和boost::asio库与STM32进行USART通讯

    系列文章目录 STM32 新建工程模板及配置 STM32 STM32与PC端 HC 06 ROS进行USART串口通信 ROS ROS上位机使用Serial库和boost asio库与STM32进行USART通讯 STM32 STM32F1