ODrive0.5.5源码分析(4) 编码器补偿校准(encoder_offset_calibration)

编者:沉尸 ([email protected])

针对Odrive中编码器补偿校准的分析,目前网络上可以搜索到相关的几篇文章,比如:
https://blog.csdn.net/ledros/article/details/126475069
但是在细节上还有值得补充的地方,在这里尽我所能再补充一下。
这里采取v0.5.5代码,用增量式旋编的例子进行说明。虽然v0.5.5和v0.5.1相比,源代码看起来改动看起来有点大,但其实质和原理没有啥区别。
现在来看源代码:

// @brief Turns the motor in one direction for a bit and then in the other
// direction in order to find the offset between the electrical phase 0
// and the encoder state 0.
bool Encoder::run_offset_calibration() {
    
    

上面重点是看注释:函数的目的是找到电子0相位和旋编状态0之间的映射关系(这里翻译成映射关系可能更好)
其作用就是,只要我知道目前的旋编计数值,就能推导出目前的电子相位。
既然如此,那直接让电机回到0相,然后读出目前旋编的当前计数值,是不是也行?我虽然没有试验过,但是绝对可以跑,精度肯定会比现在的差一点。
但是除了上面这个目的,本校准函数还兼顾测试:
1)电机旋转方向和编码器值变化方向的关系确定
2)旋编CPR值设置是否正确
这两个问题!

看代码:

bool Encoder::run_offset_calibration() {
    
    
    const float start_lock_duration = 1.0f;

    // Require index found if enabled
    if (config_.use_index && !index_found_) {
    
    
        set_error(ERROR_INDEX_NOT_FOUND_YET);
        return false;
    }

    if (config_.mode == MODE_HALL && !config_.hall_polarity_calibrated) {
    
    
        set_error(ERROR_HALL_NOT_CALIBRATED_YET);
        return false;
    }

如果旋编用index,那么在调用本函数之前需要先找到index
如果是用Hall,那需要先校正极性
在这里插入图片描述
line34:
先给shadow_count_ 赋值,我自己认为将让它放在回到0相后再来赋值更加合理,不过关系不大!
line246 ~ Line374
即将控制正反转的方式采取开环,于是设置一些相关的参数: 最大电流、最大电压等
在这里插入图片描述
Line379 ~ Line388
开始让转子回到0相,总共时间是“start_lock_duration ”秒钟,等待过程中每隔1ms检测一下错误。
在这里插入图片描述

准备开始正转
Line407 ~ Line408
设定正的速度值,也就是“正转”
累计位置清零
Line411 ~ Line420
开始检测是否正转结束,通过比较变量“total_distance_”是否大于“calib_scan_distance”
Line423 ~ Line434
设置旋编变化的方向和电机转动的方向是否一致(电机正转时旋编计数增加表示一致)
在这里插入图片描述
Line437 ~ Line444
根据设定的CPR值计算走了“calib_scan_distance”距离,获得的旋编值 与实际测量出来的旋编增量值之间的误差不能超过“calib_range”范围
在这里插入图片描述
我这里设置的值为0.02(缺省值),也就是说不能超过2%的偏差
在这里插入图片描述
Line447
设定反转速度(负数)
Line451 ~ Line459
等待反转回到原始出发点
Line468
计算出偏移的整数部分
Line470
计算出偏移的小数部分

上面将整个函数的流程说了一遍,相对很很容理解,哗啦啦又是粘贴又是讲述,说了这么多,其实都不是我想说的要点,下面才是:
1)“calib_scan_distance”值的设定,其缺省值为16*PI:
在这里插入图片描述
下面文档“odrive-interface.yaml”中明确指出:config.calib_scan_distance 要设置成4的倍数
在这里插入图片描述
为什么设定为4的倍数?我这里先把这个问题提出来,在后面一个问题中它会迎刃而解。
这里要注意,设定的这个“16PI”,是指电子角度,比如电机是7对极,那么正转的圈数就是:
(16
PI) / (2PI) / 7 = 1.14(圈)
所以有些文档中,说在旋编offset校正的时候,会正转1圈,再反转1圈,这个并不是普遍的,只是刚好碰上了接近一圈;换一个电机,比如我现在调试的电机是5对极,它就会转动: (16/2)/5 = 1.6(圈)
2)“encvaluesum”变量的理解
在正反转控制循环的代码中:
在这里插入图片描述
上图红框中的代码,在正转中也有这样的累加,“shadow_count_”是旋编计数器的值,可以理解成机械位置点的值,这个值是一直累加的,不会向CPR值取余数。这里在正反两个循环下,每隔1ms将位置点的记录值累加起来,最后再除以“num_steps”就成了offset值,是不是好像有点难以理解?
以缺省值为例:
在这里插入图片描述
正反转分别用时:calib_scan_distance / calib_scan_omega = 16 / 4 = 4(秒)
也就是正转用时4秒,反转用时4秒
如果1ms记录一次,那么正转过程中会有4000次,如果把这4000次每次记录的位置累加后再除以4000,如果转动的速度很匀速的话,平均后,它应该很接近在2000次这个时间节点的位置值,也就是中间时间点,如果这个中间时间点从理论上刚好走到了一个整圈的倍数,那么就可以用这个值作为offset。
【因为是开环控制,包括电机的启动和停止阶段的特殊性,所以上面的用时和循环次数和理论值,都会有少少偏差】
为了更加准确,于是来一次正转,再来一次反转,整体累加做除法。
现在回到前面提出的第1个问题:为什么“calib_scan_distance”要设置成PI的4倍数,也就是说一整圈(2
PI)的2倍 ?
这个问题现在就不难理解了:中间位置转动的电角度为“calib_scan_distance / 2”,设置成PI的4倍,是要保证中间位置是2PI的整数倍
现在继续进一步用一个实例说明:
比如我目前实验用的旋编是2500线,那么设置CPR=10000,用的电机为5对极。那么每一圈电角度对应着机械角度的1/5,也就是2000个旋编值,于是对于电角度的校正参数来说,offset=x 与 offset=(2000
N)+x,它对获取目前电角度的实际相位的影响是一致的。“calib_scan_distance”缺省采取16PI,中间点位置是电子角度转动8PI,也就是4圈。
因为我目前的CPR=10000,电机5对极,所以校正出来的“phase_offset”对应的机械角度为:4/5圈,也就是8000个旋编值左右,我们来看实际校正结果:
在这里插入图片描述
理论与实际极其吻合!

猜你喜欢

转载自blog.csdn.net/danger/article/details/128112098