直流无刷电机驱动记录

📅 2026/7/11 12:57:22 👁️ 阅读次数 📝 编程学习
直流无刷电机驱动记录

1、半桥驱动驱动芯片IR2104不好控制电磁刹车力度,因为IR2104的自举升压是靠IN输入端的PWM才能发挥自举作用,如果要做到刹车力度可调,就要把IN端置高电平,这样就没有了自举电压

2、三相电机驱动,可用六步换相法和正弦波控制法。六步换相的核心是BLDC根据霍尔值转动,在某两步之间调占空比,比如在1步停留1毫秒,在2步停留1毫秒,这样在步1和步2之间来回切换,电机角度就会停在1步和2步之间,此刻如果在步1和步2之间断电一段时间,这个时间就会让电机的的力度变弱,但电机仍然会停留在步1和步2之间,通过调节断电时间,就能调节磁场强度,通过调节步1或者步2的停留时间大小,就能调节磁场方向。而正弦控制法就比较复杂,用方波的占空比来尽可能地模拟成正弦波形,由于电机电流不能突变,方波输入一般会形成正弦波,正弦波的相位角就是磁场角度,磁场角度就是转子的目标角度,调节正弦的幅度(PWM占空比)就能调节磁场强度,从而实现磁场强度和磁场方向可调FOC, 正弦波的相位角度等于转子的角度乘以极对数+90度就会产生最大的扭矩,可以根据六步换相法,磁铁的变化范围找出0度变化瞬间所对应的磁铁角度,也可以通让Id≠0,Iq=0,PID算法的PI算法来让转子对齐,然后磁铁角度就是0。

3、用电机电流检测负债比用电机转速检测负载要实时和可靠。电流检测受影响因素:PWM 脉动、电机温升、电源波动、机械摩擦

4、用增量式PID控制电机时,PID的频率周期要固定,1ms周期比较合适,获取速度的周期最好接近PID的周期。获取速度的方式,用计算脉冲时长比较合适,如果用固定周期内计算多少个脉冲的方式来计算速度,速度值不够细分

5、FOC控制,三相输入的电角度相差120°,总共360°,下面是SVPWM的开环FOC代码,Uq是控制磁场强度,radian控制电角度,下面SVPWM自动转换成相差120°,可用于无霍尔的无刷电机,但由于没有闭环获取转子角度和三相各相的单独电流,运行起来容易丢步

void init_foc(FOC_STRUCT *pfoc) { // ---------------------------------- // 开环参数 // ---------------------------------- // 电角速度(每次更新增加多少弧度) pfoc->speed = 0.0f; // 缓慢加速 pfoc->accel = 0.0001f; // 最大速度限制 pfoc->speed_max = 0.01745329252;//0.013962634;//0.00872664626;//sync Uq // 输出电压幅值(0.0 ~ 1.0) // 建议先小一点 pfoc->Uq = 0.12f; pfoc->max_duty = 3600; pfoc->radian = 0; pfoc->radian_limit = RADIAN_MAX_ONCE; } // ---------------------------------- // SVPWM输出 // ---------------------------------- void SVPWM_Update(FOC_STRUCT *pfoc, uint32_t *pccr1, uint32_t *pccr2, uint32_t *pccr3) { //-------------------------------- // 生成旋转矢量 //-------------------------------- double ys = fmod(pfoc->radian, RADIAN_AMX); float Valpha = pfoc->Uq * cosf(ys); float Vbeta = pfoc->Uq * sinf(ys); //-------------------------------- // 三相反Clark变换 //-------------------------------- float Va = Valpha; float Vb = -0.5f * Valpha + 0.8660254f * Vbeta; float Vc = -0.5f * Valpha - 0.8660254f * Vbeta; //-------------------------------- // SVPWM零序注入 //-------------------------------- float Vmax = fmaxf(Va, fmaxf(Vb, Vc)); float Vmin = fminf(Va, fminf(Vb, Vc)); float Voffset = 0.5f * (Vmax + Vmin); Va -= Voffset; Vb -= Voffset; Vc -= Voffset; //-------------------------------- // 限幅保护 //-------------------------------- if(Va > 1.0f) Va = 1.0f; if(Va < -1.0f) Va = -1.0f; if(Vb > 1.0f) Vb = 1.0f; if(Vb < -1.0f) Vb = -1.0f; if(Vc > 1.0f) Vc = 1.0f; if(Vc < -1.0f) Vc = -1.0f; uint32_t max_duty = pfoc->max_duty; //-------------------------------- // 转PWM占空比 //-------------------------------- *pccr1 = (uint32_t)((Va * 0.5f + 0.5f) * max_duty); *pccr2 = (uint32_t)((Vb * 0.5f + 0.5f) * max_duty); *pccr3 = (uint32_t)((Vc * 0.5f + 0.5f) * max_duty); //-------------------------------- // CCR保护 //-------------------------------- if(*pccr1 > max_duty) *pccr1 = max_duty; if(*pccr2 > max_duty) *pccr2 = max_duty; if(*pccr3 > max_duty) *pccr3 = max_duty; }