本帖最后由 王昱顺 于 2024-10-31 11:43 编辑
本篇文章致力于对STC-FOC Lite的原版代码进行详尽的原理解释,并且提出更改/移植/裁剪建议,方便大家对这个项目进行更加适配自己的个性化更改。 因为在组装过程中,总是会出现很多的误差,亦或者是需要适应不同的电机。所以,自校准就变得十分重要。不然的话,还需要使用其他的方式来获得参数并且填入电机的固定参数中。虽然这样也不会浪费多少时间,但在电机数量多起来之后,还是会让人感觉麻烦。 所以,给程序加入自动校准功能就显得十分必要,在有感FOC中,需要获得的电机参数无非就是电机的极对数、方向、磁铁安装产生的零点误差,接下来分别解释一下这几个参数。 首先是电机的极对数:无刷电机的极对数定义为电机内部磁极的配对数量,其决定了电机的同步转速。极对数的增加将导致电机同步转速的降低,但同时能提供更大的扭矩输出。反之,较少的极对数使得电机同步转速升高,扭矩输出相对较小。在无刷电机设计中,常见的极对数包括一对、两对(高速应用),7对极(更加常见)。 然后是电机的方向:这里大家可能会问了,电机的方向不是程序主动控制嘛?为什么还需要校准方向呢?这里主要是因为电机驱动线的焊接顺序。因为焊接的时候并没有规定过三根驱动线的焊接顺序。所以只要有任意两根线与我这边调试时的顺序不一致,便有可能导致电机反转。并且,这种反转在电机的控制上是十分致命的,因为这会导致计算电角度的时候产生不正确的计算结果,进而导致电机乱转不受控制。 所以,校准方向就是通过开环的转动来比较我这边的初始定义方向,如果一致就定义为正1,否则就定义为负1,进而完成所有类型线序的正确驱动。 最后一个是电机的零点:在有感磁场定向控制(Field Oriented Control,FOC)电机驱动技术中,转子磁铁零点校准问题显得尤为关键,其目的在于确保电机转子位置与控制器参考坐标系的精确同步。该校准过程对于电机的运行性能和效率具有决定性影响。因为并不能保证每次的磁铁安装跟转子坐标系的零点严格对应,所以便需要将这个偏差找出来,并且通过算法补偿进电角度控制中,进而在接下来的计算中得到正确的电角度。 接下来,看一下实际的代码,并且进行详细的解释。
- // 线程10,自动辨识电机编码器方向-极对数-零点偏差
- Task = 10; // 线程10
- switch (Task_This[Task])
- {
- case 0: // 步骤0
- if (Auto_Look_Moto_Config_Flag) // 进入自动参数辨识
- {
- Run_Flag = 0; // 关闭运行标志,调用手动运行
- Mode = OpenLoop_Mode; // 调整为开环模式
- Dir_Flag = 1; // 设定绝对方向
- simulation_angle = 0; // 设定虚拟角度初始值
- setTorque(0.6, simulation_angle); // 手动运行,200ms时间进行稳定
- Delay(400); // 延时400ms,占用步骤1,非堵塞方式
- }
- break;
- case 2: // 步骤2
- _auto_start = _angle_this_dat; // 稳定后,读取当前单圈绝对角度
- _auto_one_flag = 1; // 设定单圈标志位
- Run_Flag = 1; // 启动运行
- Task_This[Task]++; // 进入下一个环节
- break;
- case 3: // 步骤3
- if (_auto_one_flag == 0)
- {
- Run_Flag = 0; // 关闭运行状态
- _auto_diff = (_angle_this_dat - _auto_start); // 锁存记忆当前位置
- if (_auto_diff < -(Encode_bit_Max / 2))
- _auto_diff += Encode_bit_Max; // 过零补偿
- if (_auto_diff > (Encode_bit_Max / 2))
- _auto_diff -= Encode_bit_Max;
- Task_This[Task]++; // 到达单圈后进行记忆转过的角度
- }
- break;
- case 4: // 步骤4
- if (_auto_diff > 0) // 判断开环转动角度正向自增
- moto_save.dir = 1; // 设定dir为正
- else
- moto_save.dir = -1; // 设定dir为负
- moto_save.pp = (u8)(fabs((float)Encode_bit_Max / (float)_auto_diff) + 0.5);
- // 设定极对数,+0.5,取整
- Task_This[Task]++; // 完成dir和pp参数读取,进行零点校准
- break;
- case 5: // 步骤5
- setTorque(0.7, Zero_Dat); // 手动运行,零点校准
- Delay(1000); // 等待稳定时间
- break;
- case 7: // 步骤7
- moto_save.zero = _normalizeDat(_angle_this_dat * moto_save.dir * moto_save.pp);
- // 写入零点校准值
- Delay(100); // 非堵塞延时
- break;
- case 9: // 步骤9
- setTorque(0, 0); // 松劲
- moto_save.save_ok = 1; // 设置保存标志
- Set_Buffer(&moto_save); // 写入EEPROM缓冲区
- Task_This[Task]++;
- break;
- case 10: // 步骤10
- ICacheOff(); // 关闭高速指令缓存
- Delay(10); // 非堵塞延时,等待关闭完成
- break;
- case 12: // 步骤12
- EEPROM_SectorErase(0); // 清除EEPROM
- EEPROM_write_n(0, (u8 *)moto_save.buffer, 6); // 写入数据
- Auto_Look_Moto_Config_Flag = 0; // 清除标志位
- Mode = Default_Mode; // 恢复运动模式
- IAP_CONTR = 0x20; // 重新复位
- Task_This[Task] = 0; // 完成参数辨识,返回
- break;
- default:
- Get_Delay(); // 空闲步骤时,进行时间到达查询判断,完成非堵塞延时
- break;
- }
复制代码
首先,当_auto_one_flag变量值为0时,程序将执行关闭运行状态标志Run_Flag的操作。随后,计算当前位置与初始位置的差值,并进行过零补偿处理。若差值超出编码器最大值的一半,则执行相应的补偿调整。完成差值计算后,程序将递增任务计数器Task_This,以标记完成了一圈的校准过程。 在步骤4中,程序根据差值的正负判断电机的转动方向,并据此设置moto_save.dir标志。接着,计算极对数并将其赋值给moto_save.pp。任务计数器Task_This递增,以标识dir和pp参数的设置完成。 步骤5涉及执行手动指定位置运行操作,运行到零点,并进行零点校准。程序将等待一段时间以确保转子达到稳定状态。 步骤7中,程序计算并记录零点校准值至moto_save.zero变量。之后,程序执行短暂的非堵塞延时。 在步骤9中,程序停止施加扭矩,设置保存标志moto_save.save_ok,并将数据写入EEPROM缓冲区。任务计数器Task_This递增,以标识保存操作的完成。 步骤10将关闭高速指令缓存,并等待其完成,以方便后续的EEPROM操作。 步骤12中,程序清除EEPROM内容,写入校准数据,清除自动校准标志位Auto_Look_Moto_Config_Flag,恢复默认运动模式,并执行复位操作。最终,任务计数器Task_This被重置为0,以标识校准流程的完成。
在默认情况下,程序执行Get_Delay()函数以实现非堵塞延时,完成空闲步骤的等待。
|