手搓FOC-AS5600强拖对齐与电零位标定

📅 2026/8/9 4:31:26
手搓FOC-AS5600强拖对齐与电零位标定
STM32 手搓 FOCAS5600 磁编码器强拖对齐与电零位标定实测标签STM32、STM32F103、FOC、AS5600、磁编码器、SPWM、无刷电机、嵌入式仓库https://github.com/kaka12331/stm32-simple-foc-as5600这篇只讲一件事对齐FOC 的文章我写过几篇Clark / Park 变换、SVPWM 扇区判断、马鞍波理论部分那边讲透了深入浅出死磕 FOC 算法从理论到实战全攻略STM32 纯手写 FOC空间变换、SVPWM 与相电流采样这篇一个公式都不重复。只讲一个所有 FOC 教程都会一笔带过、但你不做对电机就绝对不转的步骤编码器读到的角度和电机的电角度零点怎么对上。你把 AS5600 磁铁贴到转子上读回来 0~4095 的数。但这个 0 落在电机的哪一相上编码器数值增大对应电机正转还是反转这两个问题不解决你后面所有的 Park 变换都是在拿错误的角度做运算。先说清定位这是一个理解对齐与开环力矩跟随的教学工程不是带电流环 / 速度环的伺服方案。没有相电流采样抗不了大扰动。想要完整方案看上面两篇。硬件与时基项目配置主控STM32F103三相 PWMTIM1 CH1/2/3 → PA8 / PA9 / PA10复用推挽PWM 频率24 kHzPrescaler 3-1ARR 1000磁编码器AS5600软件 I²C12 bit0~4095控制中断TIM21 msPrescaler 72-1Period 1000-1极对数MOTOR_PP 7#definePWM_PERIOD1000// TIM1 ARR#defineMOTOR_PP7// 电机极对数按你的电机改floattarget_voltage0.4f;// 运行时的开环驱动电压int8_tmotor_direction1;// 1 正转 / -1 反转对齐时自动测出MOTOR_PP必须改成你自己电机的极对数。云台电机常见 7 或 11写错的表现是电机能转但转速和你预期差好几倍或者剧烈抖动。数一下定子槽和磁钢或者查电机手册。一、调制方式这里是 SPWM不是 SVPWM先讲清楚免得和我另一篇混淆。Set_Phase_Voltage()用的是正弦调制SPWMvoidSet_Phase_Voltage(floatangle,floatvoltage){floatU_max12.0f;// 母线电压floatdc_coefficient(voltage/U_max);if(dc_coefficient0.5f)dc_coefficient0.5f;// 安全限幅uint16_tpwm_a(uint16_t)((sinf(angle)1.0f)*0.5f*dc_coefficient*PWM_PERIOD);uint16_tpwm_b(uint16_t)((sinf(angle2.094395f)1.0f)*0.5f*dc_coefficient*PWM_PERIOD);uint16_tpwm_c(uint16_t)((sinf(angle-2.094395f)1.0f)*0.5f*dc_coefficient*PWM_PERIOD);TIM1-CCR1pwm_a;TIM1-CCR2pwm_b;TIM1-CCR3pwm_c;}2.094395就是 2π/3也就是 120° 相位差。(sin 1) * 0.5把 [-1, 1] 映射到 [0, 1] 的占空比。SPWM 比 SVPWM 少榨出约 15% 的母线电压利用率但它的好处是——一眼就能看懂没有扇区判断、没有矢量合成。做对齐验证的时候你要排查的变量越少越好。等对齐这一步跑通了把这个函数换成 SVPWM 是独立的一步不影响前面的标定逻辑。U_max 12.0f是硬编码的母线电压假设你的供电不是 12 V 就要改否则算出来的占空比和实际电压对不上。那句if (dc_coefficient 0.5f) dc_coefficient 0.5f是安全限幅开环状态下没有电流反馈占空比给大了电机就是纯粹的堵转发热。二、强拖对齐四步测出方向和零位偏置核心就是这个函数上电只跑一次voidFOC_Align_Sensor(void){// 步骤 A: 强行拉到电角度 0 度Set_Phase_Voltage(0.0f,2.5f);Delay_ms(800);uint16_tstart_rawAS5600_Read_RawAngle();// 步骤 B: 强行拉到电角度 90 度Set_Phase_Voltage(PI/2.0f,2.5f);Delay_ms(800);uint16_tend_rawAS5600_Read_RawAngle();// 释放电压Set_Phase_Voltage(0.0f,0.0f);// 步骤 C: 判断方向if(end_rawstart_raw){motor_direction1;}else{motor_direction-1;}// 步骤 D: 计算零位偏置floatstart_mech_angle((float)start_raw/4095.0f)*2.0f*PI;zero_angle_offsetstart_mech_angle*MOTOR_PP*motor_direction;}为什么对齐用 2.5 V运行只用 0.4 V这是最容易被忽略、也最关键的一个细节。对齐阶段需要「强拖」——不管转子当前在哪都要用足够大的力矩把它硬拽到指定电角度而且要拽得住、不能被摩擦力和齿槽转矩拖偏。2.5 V 是为了这个。运行阶段只要维持一点保持力矩0.4 V 就够。如果运行也给 2.5 V电机会烫得没法碰。配套的是那两个Delay_ms(800)给转子足够时间转过去并且停稳。太短的话转子还在振荡就去读编码器读到的是振荡中间的某个值零位偏置直接就错了。方向判断的原理从电角度 0° 拉到 90°转子会跟着转过去。如果编码器读数变大end_raw start_raw说明「电角度增加」对应「编码器读数增加」两者同向direction 1反之说明磁铁贴反了或者三相线序反了direction -1有了这个符号后面就不用去物理上换线序了软件里乘个负号就行。零位偏置的含义start_raw是「电角度 0 时编码器的读数」。把它换算成机械角、乘极对数就得到了编码器零点和电角度零点之间的固定偏差。之后每次算电角度减掉它就对齐了elec_anglemech_angle*MOTOR_PP*motor_direction-zero_angle_offset;三、1 ms 中断里的四行核心对齐做完运行期的逻辑短得出奇voidTIM2_IRQHandler(void){if(TIM_GetITStatus(TIM2,TIM_IT_Update)!RESET){// 1. 读机械角encoder_rawAS5600_Read_RawAngle();mech_angle((float)encoder_raw/4095.0f)*2.0f*PI;// 2. 换算电角度用上对齐测出的方向和偏置elec_anglemech_angle*MOTOR_PP*motor_direction-zero_angle_offset;// 3. 驱动角 当前电角度 90°floattarget_driving_angleelec_angle(float)motor_direction*(PI/2.0f);// 4. 输出Set_Phase_Voltage(target_driving_angle,target_voltage);TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}}第 3 步的 90° 就是 FOC 的全部精髓磁场始终超前转子磁极 90° 电角度此时产生的力矩最大。转子转到哪驱动磁场就跟到哪永远保持 90° 领先。注意90°也乘了motor_direction——方向反了的话超前要变成滞后否则就是负力矩电机会往反方向死命顶。这是开环跟随只保证力矩方向对不控制大小。没有电流采样也就没有电流环。手去拧电机能感觉到明显的保持力但抗不了大扰动也没法精确定位。四、主循环刷 OLED 为什么要降到 200 mswhile(1){mech_angle_deg(uint32_t)((float)encoder_raw*360.0f/4095.0f);OLED_ShowNum(2,5,encoder_raw,4);// Raw0~4095 原始值uint32_tshow_elec(uint32_t)((elec_angle/(2.0f*PI))*360.0f)%360;OLED_ShowNum(3,6,show_elec,3);// Elec电角度OLED_ShowNum(4,6,mech_angle_deg,3);// Phys物理机械角Delay_ms(200);// 降低刷新频率防止干扰主 CPU 效率}OLED 走软件 I²C刷一次要好几毫秒。而 TIM2 中断每 1 ms 就要来一次中断优先级又是 0最高。如果主循环拼命刷屏CPU 大部分时间耗在 I²C 上中断虽然能抢占但整体余量被吃光。200 ms 刷一次人眼完全够看CPU 也留出了余量。调试时看这三个数就够了Raw转动电机应该在 0~4095 之间平滑变化跳变说明磁铁没对准编码器中心或者距离太远Elec应该转一圈机械角变化 7 圈极对数 7Phys就是实打实的物理角度复现与安全Keil 打开Project.uvprojx芯片STM32F103先改MOTOR_PP为你电机的极对数改U_max为你的实际母线电压确认 AS5600 的 I²C 引脚、三相 PWM 引脚与你的硬件一致把target_voltage先调到 0.2f 甚至更低手扶牢电机再上电上电后 OLED 显示FOC Calibrating能看到电机被拽两下然后进入FOC Loop Open!电机应该有轻微的保持力矩出问题怎么查现象检查电机剧烈抖动 / 高频啸叫MOTOR_PP是否正确电机反着顶对齐时转子被卡住没转动方向测错了——松开手重新上电完全不转、只发烫三相线序、驱动板 EN 使能、母线电压Raw值跳变磁铁与 AS5600 的距离和同心度一般 0.5~3 mm对齐后零位每次都不一样Delay_ms(800)太短转子还没停稳驱动板的使能和电流限制务必接好开环状态下一旦三相直通MOS 管几秒就报废。这个工程的边界说清楚它不能干什么比吹它能干什么有用没有电流环力矩大小不可控只能控方向没有速度环 / 位置环不能做精确定位开环抗扰差大惯量负载会失步SPWM 而非 SVPWM母线电压利用率低约 15%它的价值在于把「对齐」这一步单独拎出来跑通、看得见。OLED 上那三个数会告诉你编码器、电角度、机械角三者的关系。这一步踩实了再往上加电流环才有意义——不然电流环调不出来你都不知道是环的问题还是角度就是错的。相关文章FOC 理论全景深入浅出死磕 FOC 算法SVPWM 与相电流采样STM32 纯手写 FOC电流采样的盲区问题FOC 低侧采样与在线采样的「共模地狱」仓库地址https://github.com/kaka12331/stm32-simple-foc-as5600标准外设库遵循其原协议。