ODrive学习——添加485编码器支持

news2024/9/19 10:49:50

系列文章目录


文章目录

  • 系列文章目录
  • 前言
  • 一、端口处理
  • 二、在Encoder中引入新的类型
    • 1.增加485类型
    • 2.增加串口的初始化操作
    • 3.数据处理
  • 总结


前言

尝试在ODrive中添加485型的编码器的支持


一、端口处理

计划使用PA2及PA3作为485通信的端口。这样首先要把外部温度传感器的I/O口给改掉。
找到外部温度传感器配置初始化的地方改掉,改成GPIO5,也就是PC4。

class OffboardThermistorCurrentLimiter : public ThermistorCurrentLimiter, public ODriveIntf::OffboardThermistorCurrentLimiterIntf {
public:
    static const size_t num_coeffs_ = 4;

    struct Config_t {
        float thermistor_poly_coeffs[num_coeffs_];

        //0716 Change GPIO PIN TO 5  PC4
#if HW_VERSION_MAJOR == 3
        //uint16_t gpio_pin = 4;
        uint16_t gpio_pin = 5;
#elif HW_VERSION_MAJOR == 4
        uint16_t gpio_pin = 2;
#endif

串口2 默认打开配置

            case ODriveIntf::GPIO_MODE_UART_B: {
                GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
                GPIO_InitStruct.Pull = (i == 0) ? GPIO_PULLDOWN : GPIO_PULLUP; // this is probably swapped but imitates old behavior
                GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
                //if (!odrv.config_.enable_uart_b) {
                    odrv.misconfigured_ = true;
               // }

此外还需要进行I/O的配置,485使用串口的配置。如果想保持原风格的话,需要添加对应枚举类型,在原有的初始化硬件体系下进行。也可以自己定义一个I/O及外设初始化的函数,在所有外设初始化完成以后调用。

二、在Encoder中引入新的类型

1.增加485类型

Encoder的类型是工程通过Odrive-interface.yaml生成的。包括其他的一些枚举类型,所以从工程里直接去链接类型定义是找不到的。


  ODrive.Encoder.Mode:
    values:
      INCREMENTAL:
      HALL:
      SINCOS:
      SPI_ABS_CUI:
        value: 0x100
        doc: Compatible with CUI AMT23xx
      SPI_ABS_AMS:
        value: 0x101
        doc: Compatible with AMS AS5047P, AS5048A/AS5048B (no daisy chain support)
      SPI_ABS_AEAT:
        value: 0x102
        doc: Supports AEAT-8800
      SPI_ABS_RLS:
        value: 0x103
        doc: Supports RLS Orbis Encoders
      SPI_ABS_MA732:
        value: 0x104
        doc: MagAlpha MA732 magnetic encoder
      U485_SRMA34:
        value: 0x400
        doc: SRMA34-M16S17Bit-SY-C-5V encoder

这里增加一个U485_SRMA34的类型,注意开头不要数字开头,编译会有错误。

class Encoder : public ODriveIntf::EncoderIntf {
public:
    static constexpr uint32_t MODE_FLAG_ABS = 0x100;
    // 0717
    static constexpr uint32_t MODE_FLAG_SRMA = 1024;


    static constexpr std::array<float, 6> hall_edge_defaults = 
        {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f};

    struct Config_t {
        //0717 
        Mode mode = MODE_U485_SRMA34; 
        //Mode mode = MODE_INCREMENTAL;

在Encoder类型中,把对应的编码器类型给修改一下。

2.增加串口的初始化操作

这部分可以从系统串口初始化那边扒下来,直接启用串口2。
但是0.5.6版本不支持双串口同时使用,所以不能直接在odrive_main.h中启用uart_b。
所以还是再重新定义一个新的变量和新的处理任务。
这样的话永远不要再用原来的使能来启用uart_b了。

UART_HandleTypeDef* uart_a = &huart4;
UART_HandleTypeDef* uart_b = &huart2; // TODO: this could be supported in ODrive v3.6 (or similar) using STM32's USART2
UART_HandleTypeDef* uart_c = nullptr;
UART_HandleTypeDef* uart_485_a = &huart2; // TODO: this could be supported in ODrive v3.6 (or similar) using STM32's USART2


struct BoardConfig_t {
    ODriveIntf::GpioMode gpio_modes[GPIO_COUNT] = {
        DEFAULT_GPIO_MODES
    };

    bool enable_uart_a = true;
    bool enable_uart_b = false;
    bool enable_uart_c = false;

    bool enable_uart_485_a = true;
    uint32_t uart_485_a_baudrate = 115200;

    uint32_t uart_a_baudrate = 115200;
    uint32_t uart_b_baudrate = 115200;
    uint32_t uart_c_baudrate = 115200;

做戏也做全套,新增一个uart_485_a的变量,也指向huart2。这样后面不再引用uart_b的变量了。
在 boardInit里面增加初始化操作

    //0717
    if (odrv.config_.enable_uart_485_a) {
        uart_485_a->Init.BaudRate = odrv.config_.uart_485_a_baudrate;
        MX_USART2_UART_Init();
    }

当然这样只是初始化完成了外设。还需要把数据处理和数据关联加上。

波特率根据自己用的编码器外设来配置哦。

3.数据处理

在对应的头文件中,添加这些接口的说明。

在main函数的inti_communication函数中,调用此函数。

void init_communication(void) {
    //printf("hi!\r\n");

    // Dual UART operation not supported yet
    if (odrv.config_.enable_uart_a && odrv.config_.enable_uart_b) {
        odrv.misconfigured_ = true;
    }

    if (odrv.config_.enable_uart_a && uart_a) {
        start_uart_server(uart_a);
    } else if (odrv.config_.enable_uart_b && uart_b) {
        start_uart_server(uart_b);
    }
    // 0903 start 485 data handle
    if (odrv.config_.enable_uart_485_a && uart_485_a) {
        start_u485_server(uart_485_a);
    }

之后我们再完善 这个处理数据的任务。先进入到编码器定时采集的接口,sample_now,添加上我们的485编码器类别,。
获取数据的方式还是用DMA的方式,在回调中处理数据到相应的变量。
试了几种方法都不太行,不知道是不是HAL库内部配置的太多了。这样倒是也省了一些额外的任务开支。

        case MODE_U485_SRMA34:
        {
            // Send 485 order to Encoder
              // Send 485 order to Encoder 0912
            get_gpio(6).write(true);
            HAL_UART_AbortReceive(&huart2);
            HAL_UART_Receive_DMA(&huart2, u485_rx_buffer, 6);
            ucTemp = 0x02;
            HAL_UART_Transmit(&huart2, &ucTemp, 1, 10);
            get_gpio(6).write(false);
        }
        break;

再来回想一下,SPI类型的编码器的处理,在其回调中得到一个位置的绝对值,并传递给pos_abs_参数。
数据的处理,可以放到Task任务中去,结合串口中断来实现。
所以直接在Update中来继续剩下的部分。

        case MODE_U485_SRMA34:{

            abs_485_pos_updated_ = false;
            delta_enc = pos_abs_latched - count_in_cpr_; //LATCH
            delta_enc = mod(delta_enc, config_.cpr);
            if (delta_enc > config_.cpr/2) {
                delta_enc -= config_.cpr;
            }
        } break;

关于这套计算的逻辑,需要参考SPI 编码器的参数进行参考。

临时先弄这些。目前只是获取到了编码器的数值,这一套到底能不能运行起来待测试。


总结

提示:这里对文章进行总结:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2146120.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IOS 26 实现歌单详情(UITableView)列表 ③

歌单详情完整效果 歌单列表分组头部效果 本节是在文章 IOS 25 实现歌单详情&#xff08;UITableView&#xff09;列表② 的基础上&#xff0c;实现歌单列表分组头部View。当歌单列表滑动头部View至顶部时&#xff0c;头部View不会因列表滑动而消失&#xff0c;会一直显示在顶部…

2024.9.18

1.已知网址www.hqyj.com截取出网址的每一个部分 菜单栏中 ----> 虚拟机 -----> 设置 -----> 网络适配器 选择桥接模式 菜单栏中 ----> 编辑 -----> 虚拟网络编辑器 更改设置 将桥接改成自动 如果桥接连不上网 尝试还原默认设置后&#xff0c;在重新连接桥接…

微信小程序的学生选课系统--论文源码调试讲解

第二章 开发技术介绍 此次管理系统的关键技术和架构由B/S结构、java和mysql数据库&#xff0c;是本系统的关键开发技术&#xff0c;对系统的整体、数据库、功能模块、系统页面以及系统程序等设计进行了详细的研究与规划。 2.1 系统开发平台 在该在线微信小程序的学生选课系统…

动手学习RAG: 大模型向量模型微调 intfloat/e5-mistral-7b-instruct

动手学习RAG: 向量模型动手学习RAG: moka-ai/m3e 模型微调deepspeed与对比学习动手学习RAG&#xff1a;rerank模型微调实践 bge-reranker-v2-m3动手学习RAG&#xff1a;迟交互模型colbert微调实践 bge-m3动手学习RAG: 大模型向量模型微调 intfloat/e5-mistral-7b-instruct动手学…

JavaScript高级——内存溢出和内存泄漏

1、闭包的缺点与解决方法 &#xff08;1&#xff09;缺点&#xff1a;函数执行完后&#xff0c;函数内的局部变量没有释放&#xff0c;占用内存时间会变长。 容易造成内存泄漏。 &#xff08;2&#xff09;解决&#xff1a;能不用闭包就不用。 及时释放。 2、内存溢出 ① 一…

Linux进阶 查看系统进程

操作系统中进程的生命周期是: 创建进程,(服务启动或软件的启动)进行运行状态进程等待状态进行唤醒进程结束一般主要关注是进行中间的三种状态,三种状态之间装换关系如下: 1、就绪状态:表示进程已经做好了运行的准备状态,只要获得内存空间,就可以立即执行。 2、阻塞状态:…

Maya---机械模型制作

材质效果&#xff08;4&#xff09;_哔哩哔哩_bilibili 三角面 四边面 多边面 *游戏允许出现三角面和四边面 游戏中一般是低模&#xff08;几千个面&#xff09; 动漫及影视是高模 机械由单独零件组合而成&#xff0c;需独立制作 低面模型到高面模型 卡线是为了将模型保…

电脑怎么设置开机密码?3个方法迅速搞定!

电脑已经成为了我们日常办公与学习的重要工具&#xff0c;其中保存有很多重要且需保密的资料&#xff0c;为电脑设置开机密码则是保护资料安全的第一步。那么&#xff0c;电脑怎么设置开机密码呢&#xff1f;今天&#xff0c;小编就为大家介绍3个设置电脑开机密码的方法&#x…

深度学习对抗海洋赤潮危机!浙大GIS实验室提出ChloroFormer模型,可提前预警海洋藻类爆发

2014 年 8 月&#xff0c;美国俄亥俄州托莱多市超 50 万名居民突然收到市政府的一则紧急通知——不得擅自饮用自来水&#xff01; 水是人类生存的基本供给&#xff0c;此通告关系重大&#xff0c;发出后也引起了不小的恐慌。究其原因&#xff0c;其实是美国伊利湖爆发了大规模…

油烟机制造5G智能工厂物联数字孪生平台,推进制造业数字化转型

油烟机制造5G智能工厂物联数字孪生平台&#xff0c;是智能制造与信息技术的深度融合产物。数字孪生工业互联平台通过部署在工厂各个环节的传感器和设备&#xff0c;实时采集、分析和处理生产过程中的海量数据&#xff0c;构建出高度逼真的数字孪生模型。这一模型不仅能够真实反…

基于树莓派ubuntu20.04的ros-noetic小车

目录 一、小车的架构 1.1 总体的概述 1.2 驱动系统 1.3 控制系统 二、驱动系统开发 2.1 PC端Ubuntu20.04安装 2.2 树莓派Ubuntu20.04安装 2.3 PC端虚拟机设置静态IP 2.4 树莓派设置静态IP 2.5 树莓派启动ssh进行远程开发 2.5 arduino ide 开发环境搭建 2.5.1 PC…

深入探索Docker核心原理:从Libcontainer到runC的演化与实现

随着容器技术的发展&#xff0c;Docker从早期的Libcontainer逐步演化到runC&#xff0c;推动了容器运行时的标准化进程。Libcontainer是Docker容器的核心管理工具&#xff0c;而runC则在此基础上发展成为符合OCI&#xff08;Open Container Initiative&#xff09;标准的轻量级…

Vue常用PC端和移动端组件库、Element UI的基本使用(完整引入和按需引入)

目录 1. Vue常用PC端和移动端组件库2. Element UI的基本使用2.1 完整引入2.2 按需引入 1. Vue常用PC端和移动端组件库 提供常用的布局、按钮、输入框、下拉框等UI布局&#xff0c;以组件的形式提供。使用这些组件&#xff0c;结构、样式、交互就都有了 移动端常用UI组件库 Van…

windows10 修改默认输入法

右键桌面&#xff0c;选择个性化 左侧搜索 语言 选择编辑语言和键盘选项 点击键盘 默认替代输入法 选择你想要设置的。重启电脑。如下图

C语言18--头文件

头文件的作用 通常&#xff0c;一个常规的C语言程序会包含多个源码文件&#xff08;.c&#xff09;&#xff0c;当某些公共资源需要在各个源码文件中使用时&#xff0c;为了避免多次编写相同的代码&#xff0c;一般的做法是将这些大家都需要用到的公共资源放入头文件&#xff…

光学超表面在成像和传感中的应用

光学超表面已成为解决笨重光学元件所带来的限制&#xff0c;极具前景的解决方案。与传统的折射传播技术相比&#xff0c;它们提供了一种紧凑、高效的光操纵方法&#xff0c;可对相位、偏振和发射进行先进的控制。本文概述了光学超表面、它们在成像和传感技术中的各种应用以及这…

Broadcast:Android中实现组件与进程间通信

目录 一&#xff0c;Broadcast和BroadcastReceiver 1&#xff0c;简介 2&#xff0c;广播使用 二&#xff0c;静态注册和动态注册 三&#xff0c;无序广播和有序广播 1&#xff0c;有序广播的使用 2&#xff0c;有序广播的截断 3&#xff0c;有序广播的信息传递 四&am…

力扣(LeetCode)每日一题 1184. 公交站间的距离

题目链接https://leetcode.cn/problems/distance-between-bus-stops/description/?envTypedaily-question&envId2024-09-16 环形公交路线上有 n 个站&#xff0c;按次序从 0 到 n - 1 进行编号。我们已知每一对相邻公交站之间的距离&#xff0c;distance[i] 表示编号为 i …

Python燃烧废气排放推断算法模型

&#x1f3af;要点 宏观能耗场景模型参数化输入数据&#xff0c;分析可视化输出结果&#xff0c;使用场景时间序列数据模型及定量和定性指标使用线图和箱线图、饼图、散点图、堆积条形图、桑基图等可视化模型输出结果根据气体排放过程得出其时间序列关系&#xff0c;使用推断模…

nginx基础篇(一)

文章目录 学习链接概图一、Nginx简介1.1 背景介绍名词解释 1.2 常见服务器对比IISTomcatApacheLighttpd其他的服务器 1.3 Nginx的优点(1)速度更快、并发更高(2)配置简单&#xff0c;扩展性强(3)高可靠性(4)热部署(5)成本低、BSD许可证 1.4 Nginx的功能特性及常用功能基本HTTP服…