ODrive移植keil(八)—— 闭环控制



ODrive、VESC和SimpleFOC 教程链接汇总:请点击

一、硬件接线

用编码器的SPI接口,可以跳过上电检测。ABZ接口必须每次上电校准,

在这里插入图片描述

二、官方代码操作

用官方代码操作,验证控制效果,获取配置参数,
本小节演示用v0.5.1版本固件,因为v0.5.1的教程最丰富。当然也可以用v0.5.6版本。
在这里插入图片描述

2.1、力矩模式

在这里插入图片描述

odrv0.axis0.controller.config.vel_limit 限制最大速度,当超过最大速度时力矩变小,电机速度在限速附近波动会导致电动振动。

//力矩模式
odrv0.erase_configuration()
odrv0.config.dc_max_positive_current = 30
odrv0.config.dc_max_negative_current = -5.0
odrv0.axis0.motor.config.motor_type = MOTOR_TYPE_HIGH_CURRENT
odrv0.axis0.motor.config.pole_pairs = 7
odrv0.axis0.motor.config.calibration_current = 5
odrv0.axis0.encoder.config.mode = ENCODER_MODE_SPI_ABS_AMS
odrv0.axis0.encoder.config.abs_spi_cs_gpio_pin = 1
odrv0.axis0.encoder.config.cpr = 2**14
odrv0.axis0.controller.config.control_mode = CONTROL_MODE_TORQUE_CONTROL
odrv0.axis0.controller.config.vel_limit = 20    //超过限制速度,力矩变小
odrv0.axis0.controller.config.input_mode = INPUT_MODE_TORQUE_RAMP
odrv0.axis0.controller.config.torque_ramp_rate = 0.1
odrv0.save_configuration()     //v0.5.6保存后重启,不用再 reboot
odrv0.reboot()

odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE
odrv0.axis0.error
odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL

odrv0.axis0.controller.input_torque = 0.1

2.2、速度模式

在这里插入图片描述

//速度模式
odrv0.erase_configuration()
odrv0.config.dc_max_positive_current = 30
odrv0.config.dc_max_negative_current = -5.0
odrv0.axis0.motor.config.motor_type = MOTOR_TYPE_HIGH_CURRENT
odrv0.axis0.motor.config.pole_pairs = 7
odrv0.axis0.motor.config.calibration_current = 5
odrv0.axis0.encoder.config.mode = ENCODER_MODE_SPI_ABS_AMS
odrv0.axis0.encoder.config.abs_spi_cs_gpio_pin = 1
odrv0.axis0.encoder.config.cpr = 2**14
odrv0.axis0.controller.config.control_mode = CONTROL_MODE_VELOCITY_CONTROL
odrv0.axis0.controller.config.vel_gain = 0.02
odrv0.axis0.controller.config.vel_integrator_gain = 0.2
odrv0.axis0.controller.config.vel_limit = 50   //12V电源,5008电机的最大转速大概50
odrv0.axis0.controller.config.input_mode = INPUT_MODE_VEL_RAMP
odrv0.axis0.controller.config.vel_ramp_rate = 50
odrv0.save_configuration()     //v0.5.6保存后重启,不用再 reboot
odrv0.reboot()

odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE
odrv0.axis0.error
odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL

odrv0.axis0.controller.input_vel = 5

2.3、位置模式

在这里插入图片描述

如果电机停止的位置刚好是磁阻最大,会被齿槽力拉到磁阻最小位置,然后PID算法又把它转到磁阻最大位置,如此反复拉扯。
这个问题需要在下一节抗齿槽算法来解决,

//位置模式
odrv0.erase_configuration()
odrv0.config.dc_max_positive_current = 30
odrv0.config.dc_max_negative_current = -5.0
odrv0.axis0.motor.config.motor_type = MOTOR_TYPE_HIGH_CURRENT
odrv0.axis0.motor.config.pole_pairs = 7
odrv0.axis0.motor.config.calibration_current = 5
odrv0.axis0.encoder.config.mode = ENCODER_MODE_SPI_ABS_AMS
odrv0.axis0.encoder.config.abs_spi_cs_gpio_pin = 1
odrv0.axis0.encoder.config.cpr = 2**14
odrv0.axis0.controller.config.control_mode = CONTROL_MODE_POSITION_CONTROL
odrv0.axis0.controller.config.vel_limit = 50
odrv0.axis0.controller.config.pos_gain = 20
odrv0.axis0.controller.config.vel_gain = 0.04     //位置模式下的速度环PI参数比速度模式下的要大一点
odrv0.axis0.controller.config.vel_integrator_gain = 0.5
odrv0.axis0.controller.config.input_mode = INPUT_MODE_TRAP_TRAJ
odrv0.axis0.trap_traj.config.vel_limit = 10
odrv0.axis0.trap_traj.config.accel_limit = 10
odrv0.axis0.trap_traj.config.decel_limit = 10
odrv0.save_configuration()
odrv0.reboot()

odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE
odrv0.axis0.error
odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL

odrv0.axis0.controller.input_pos = 0
odrv0.axis0.controller.input_pos = 1

三、移植后的代码操作

使用本节提供的第一个代码,下图:

在这里插入图片描述

3.1、力矩模式

  • 在MyProject.h文件中设置参数,下图:
    在这里插入图片描述
    如果有更多参数需要设置,请进入初始化阶段的几个 init()函数,下图:
    在这里插入图片描述

  • 编译烧写,

  • 发送指令“C”,3秒钟后电机“嘀”一声,然后正转8个电角度,反转8个电角度,同时串口打印校准参数。

  • 再发送指令“G”,电机闭环,

  • 再发送指令“S0.1”,电机开始转动,如果空载电机会达到最大转速。如果限速,电机只能达到限制转速。
    在这里插入图片描述

视频:https://www.bilibili.com/video/BV1XG411v7hM/?vd_source=33c70ef3713ea86e5385ac1e62223bcf

3.2、速度模式

  • 在MyProject.h文件中设置参数,下图:
    在这里插入图片描述

  • 编译烧写,

  • 发送指令“C”,3秒钟后电机“嘀”一声,然后正转8个电角度,反转8个电角度,同时串口打印校准参数。

  • 再发送指令“G”,电机闭环,

  • 再发送指令“T10”,电机转动。读取实时速度,指令为“V”。
    在这里插入图片描述

视频:https://www.bilibili.com/video/BV1XG411v7hM/?vd_source=33c70ef3713ea86e5385ac1e62223bcf

3.3、位置模式

  • 在MyProject.h文件中设置参数,下图:
    在这里插入图片描述

  • 编译烧写,

  • 发送指令“C”,3秒钟后电机“嘀”一声,然后正转8个电角度,反转8个电角度,同时串口打印校准参数。

  • 再发送指令“G”,电机闭环,

  • 再发送指令“K1”,电机转到指定位置。读取当前位置指令为“P”。
    在这里插入图片描述

视频:https://www.bilibili.com/video/BV1XG411v7hM/?vd_source=33c70ef3713ea86e5385ac1e62223bcf

3.4、跳过上电校准

  • 官方ODrive每次上电都要校准一下才能进入闭环,否则会报错(只有无感模式可以直接进入闭环),据说在代码中配置也可以跳过校准,我没找到配置的方法。

  • SimpleFOC中,把校准参数写入代码可以跳过检测,我按照SimpleFOC的方法做了类似设计:

3.4.1、手动输入参数

1、第一次设置为0,编译烧下载,下图:
在这里插入图片描述
2、发送指令“C”校准电机,获取校准参数,下图:
在这里插入图片描述
电机起始位置不同,校准的偏置角度可能不一样,填写其中任一次的校准值即可(原理在上一篇教程中讲过了)。

3、把获取的五个参数写入代码,编译下载,下图:
在这里插入图片描述

4、重新上电,可以不用再校准,直接发送指令“G”进入闭环。

ABZ编码器为增量编码器,每次上电都需要校准,不能跳过。

3.4.2、flash保存参数

手动输入参数比较麻烦,功能升级,增加了flash保存功能,并且可以开机进入闭环,请看第二个代码,
在这里插入图片描述

1、上电后发送指令“C”校准电机,
在这里插入图片描述

2、发送指令“A1”配置已经校准,相当于官方指令:odrv0.axis0.motor.config.pre_calibrated = True,
在这里插入图片描述

3、如果需要开机进入闭环,发送指令“B1”,相当于官方指令:odrv0.axis0.config.startup_closed_loop_control = True,
4、发送指令“F”保存参数到flash,
5、发送指令“R”重启。
6、初始化时设置好目标值,闭环后可直接运行到设定值。
在这里插入图片描述


保存在flash的参数,重新烧写代码不会被删除,代码更新时记得发送指令删除,以免影响新代码的执行。

ABZ编码器为增量编码器,每次上电都需要校准,不能跳过。

3.5、测试云台电机

ODrive也可以控制云台电机,因为有梯形轨迹算法,所以位置模式的效果比SimpleFOC好,

1、硬件接线,下图:
在这里插入图片描述

2、在MyProject.h文件中设置参数,下图:
在这里插入图片描述

3、操作与上面的相同,不再赘述,
在这里插入图片描述

4、ODrive的位置模式+梯形轨迹,可以又快又稳的转到指定位置,

在这里插入图片描述

四、代码说明

以这个代码为例,简单捋下流程:
在这里插入图片描述

1、while(1) 的工作量很小,下图

在这里插入图片描述

2、定时器更新中断是核心,下图:

在这里插入图片描述

3、大部分功能处理在 上图的control_loop_cb() 函数中,

4、在axis.c文件中进入闭环,下图:

在这里插入图片描述

5、在controller.c文件中根据输出模式,处理位置、速度和力矩变量,

在这里插入图片描述

然后是位置环PID和速度环PID运算,下图:

在这里插入图片描述

所有的输入模式,运算后最终生成这个输出,下图:


6、在motor,c中生成 Id/Iq,下图:

在这里插入图片描述

7、接下来就是你们喜欢的FOC变换,主要由 pwm_update_cb() 函数实现,

在这里插入图片描述

代码流程就是这样,别问细节,成年人点到为止!

五、定点运算和浮点运算

  • 定点运算,通过放大程序运行中的变量的方式,把浮点数转化为定点数,提高了计算效率,使得低性能的单片机也可以实现高性能的算法。

  • 定点运算早就存在,是ST采用定点运算配合它的电机库,极大的推广了这一技术,我觉得目前市面上只要是定点运算的电机驱动器,应该都会受到ST的影响,或者直接就师承ST。

  • 定点运算的标幺化太过复杂,繁琐,既要防止溢出又怕精度不够,对于新手非常不友好。
    浮点运算则简单、直观、高精度,除了单片机成本高,但是随着国产单片机的崛起,成本门槛已经不存在了。

  • 并且随着ODrive和VESC等开源技术影响的逐渐扩大,浮点运算一定会成为主流。

  • 看到一些国产单片机厂家在推定点运算的驱动器,我觉得这些厂家应该是没把握住技术发展方向,要么就是技术不够成熟。请大家根据自己的能力和需要选择技术路线。



店铺:图锐科技


欢迎加入技术交流群:923734429 (群已满,注意提示;入群申请写:优快云)




(完)

<think> 我们正在处理用户关于将ODrive移植Keil5的环境配置教程的问题。ODrive是一个开源的无刷电机控制器项目,通常运行在STM32微控制器上。Keil MDK-ARM(Keil5)是一个流行的ARM开发环境。 由于ODrive项目通常使用基于Makefile的构建系统(如libopencm3或STM32CubeMX),而Keil使用自己的项目文件(.uvprojx),因此移植需要一些步骤。 我们将按步骤指导用户如何在Keil5中配置ODrive项目: ### 步骤1:准备ODrive源代码 首先,从GitHub获取ODrive的源代码: ```bash git clone https://github.com/odriverobotics/ODrive ``` ### 步骤2:安装必要的软件 确保已安装: - Keil MDK-ARM(Keil5)并已激活 - 对应的STM32器件支持包(例如,如果ODrive使用STM32F4系列,则需安装STM32F4xx_DFP) ### 步骤3:创建新的Keil项目 1. 打开Keil5,选择 Project -> New uVision Project 2. 选择一个目录并命名项目(例如ODrive_Keil) 3. 选择目标MCU:ODrive通常使用STM32F405RGT6(根据具体硬件选择) ### 步骤4:复制源代码到项目目录 将ODrive源代码复制到项目目录下,或者将项目创建在ODrive的源码目录中(但注意Keil会生成一些文件,可能会和原项目冲突,建议新建目录并复制源码)。 ### 步骤5:添加源文件和头文件路径 1. 在Project窗口中,右键点击Target,选择Manage Project Items。 2. 在Groups中添加源文件组(例如:Application, Drivers, Middleware等),然后为每个组添加对应的.c文件。 3. 点击魔术棒按钮(Options for Target),在C/C++选项卡中,添加所有包含头文件的目录。例如: - 源代码中的`./`(当前目录) - `./Drivers/STM32F4xx_HAL_Driver/Inc` - `./Drivers/CMSIS/Include` - 其他ODrive项目中的头文件目录 注意:ODrive项目可能使用了HAL库或libopencm3,这里假设使用HAL库(因为ODrive早期版本使用libopencm3,但后来可能迁移到HAL,具体看版本)。如果使用libopencm3,则需要先编译libopencm3库,并将其作为库文件加入。 ### 步骤6:配置目标选项 - 在Target选项卡中,设置正确的晶振频率(ODrive通常使用8MHz外部晶振)。 - 在Output选项卡中,选择生成HEX文件。 - 在Debug选项卡中,选择使用的调试器(如ST-Link)。 ### 步骤7:修改启动文件 确保项目包含正确的启动文件(startup_stm32f405xx.s或其他对应型号的启动文件)。这个文件通常位于CMSIS设备库中。 ### 步骤8:修改链接脚本 Keil使用分散加载文件(.sct)而不是传统的链接脚本。需要根据原项目的链接脚本(例如STM32F405xG.ld)来创建或修改Keil的分散加载文件。可以在Linker选项卡中取消勾选“Use Memory Layout from Target Dialog”,然后编辑分散加载文件,指定内存区域(FLASH和RAM)和段的位置。 ### 步骤9:处理特定配置 ODrive项目可能有一些特定的宏定义,需要在Keil的C/C++选项卡的预定义符号中添加。例如: - `USE_HAL_DRIVER` - `STM32F405xx` - `HSE_VALUE=8000000` ### 步骤10:解决编译错误 由于ODrive项目最初为Makefile设计,可能会有一些平台特定的代码(如中断处理、系统初始化等)需要调整。特别是: - 检查系统初始化函数(如`SystemInit`)是否与Keil的启动文件兼容。 - 中断向量表可能需要重新映射(在Keil中,启动文件已经处理了向量表,所以需要确保原项目的中断处理函数名称与启动文件中的一致,或者修改启动文件中的中断服务程序名称)。 ### 步骤11:调试 连接调试器,下载程序并调试。注意检查时钟配置是否正确,外设初始化是否正常。 ### 注意事项 - 由于ODrive项目较大,移植过程可能会遇到较多编译错误,需要耐心解决。 - 如果ODrive使用了FreeRTOS,则需要在Keil中安装FreeRTOS支持包,并正确配置。 由于ODrive项目本身并不官方支持Keil,因此移植可能需要较多工作。如果可能,建议使用原项目的构建系统(如使用GCC和Makefile)进行开发。 §§相关问题§§ 1. 如何解决在Keil中编译ODrive时出现的未定义符号错误? 2. 如何配置Keil以使用ST-Link调试ODrive? 3. ODrive项目中的FreeRTOS如何在Keil中配置? </think> ### ODrive移植Keil5的环境配置教程 以下是ODrive固件移植Keil MDK-ARM(Keil5)的详细配置步骤: #### 1. **环境准备** - 安装Keil MDK-ARM(需激活) - 安装对应STM32系列的支持包(如STM32F4xx_DFP) - 获取ODrive源码: ```bash git clone https://github.com/odriverobotics/ODrive ``` #### 2. **创建Keil项目** 1. 打开Keil5 → `Project → New uVision Project` 2. 选择目标MCU型号(例如STM32F405RGT6) 3. 保存到ODrive源码目录(建议新建`/project/keil`子目录) #### 3. **添加源码文件** 在项目管理器中: 1. 创建分组: - `Application`(主程序) - `Drivers`(硬件驱动) - `Middlewares`(协议栈) 2. 添加文件: ```plaintext Application/ |- main.c |- odrive.c Drivers/STM32F4xx_HAL_Driver/ |- Src/stm32f4xx_hal_gpio.c |- Src/stm32f4xx_hal_tim.c Middlewares/FreeRTOS/ |- tasks.c |- queue.c ``` #### 4. **配置头文件路径** 在`Options for Target → C/C++`: ```plaintext Include Paths: ../Drivers/STM32F4xx_HAL_Driver/Inc ../Drivers/CMSIS/Device/ST/STM32F4xx/Include ../Middlewares/FreeRTOS/include ../Application ``` #### 5. **设置预定义宏** 在`C/C++ → Preprocessor Symbols`添加: ```c USE_HAL_DRIVER STM32F405xx HSE_VALUE=8000000 ``` #### 6. **配置时钟与调试** 1. 系统时钟设置: - 使用STM32CubeMX生成`SystemClock_Config()`函数 - 替换默认的时钟初始化代码 2. 调试接口: - `Debug → ST-Link Debugger` - 勾选`Reset and Run` #### 7. **修改链接脚本** 1. 在`Linker`选项卡取消勾选`Use Memory Layout from Target Dialog` 2. 编辑分散加载文件(.sct): ```ld LR_IROM1 0x08000000 0x100000 { ; Flash ER_IROM1 0x08000000 0x100000 { *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x20000000 0x20000 { ; RAM .ANY (+RW +ZI) } } ``` #### 8. **解决常见问题** - **HAL库缺失**:从STM32CubeF4安装包复制HAL库到`Drivers`目录 - **中断冲突**:在`stm32f4xx_it.c`中注释掉未使用的中断处理函数 - **堆栈设置**:在`startup_stm32f405xx.s`中调整: ```assembly Stack_Size EQU 0x2000 ; 增大至8KB Heap_Size EQU 0x1000 ; 增大至4KB ``` #### 9. **编译与烧录** 1. 点击`Build`(F7)编译项目 2. 连接ST-Link → 点击`Load`烧录固件 3. 使用串口调试工具(如Putty)验证输出: ```plaintext ODrive initialized Motor 0: IDLE ``` > **注意事项**: > 1. ODrive默认使用Makefile构建,需手动移植外设驱动 > 2. 实时性要求高的任务(如PWM)需配置为最高优先级 > 3. 推荐使用VSCode+Keil插件获得更好开发体验[^1]
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值