参考帖子:
“最便宜的 车规-FOC,24万转@STC32G12K128-24A车规,STC-FOC 新算法库,11/30更新”
https://www.stcaimcu.com/thread-19545-1-1.html
最初见到这个电路时,对于只使用4只电阻的过零检测感觉很神奇,但是核心代码是LIB库,
用起来多少会有点不方便,所以想要研究一下原理;
经示波器测试,相线之间的电压波形确实是正弦波,但线电流(以及总线电流)却有周期性的“断点”,
所以猜想其原理就是在UV相的交叉点附近关闭6只MOS管,通过比较器检测“过零”;
基于这种猜想,自己写代码验证了一下,确实可行;只是目前的代码还比较粗糙。
申明:
本程序仅用于研究学习,功能尚未完善,可能有BUG。
此程序仅在1806(KV2280)电机上试过,供电电压5V。
本程序根据帖子中的附件“STC_FAN_FOC库-2025年11月30日 16点46分”修改而来,未使用“STC_FAN_FOC.LIB”库。
产生三相SPWM,在固定相位区间关闭PWM(关断6只MOS管,令三相悬空)便于检测反电势过零点
(U、V相的交叉点,约位于电周期的150度),调节速度mot_speed使过零点的相位达到设定值。
当前配置:
PWM为边沿对齐模式;
PWM频率约23kHz;
PWM占空比最大255,便于用1字节来控制;
SPWM采用查表方式,周期为256;
源代码:
FOC-lcw.rar
(57.3 KB, 下载次数: 14)
过零检测时机:
参考原理图:“SCH-STC-FOC-24万转-小功率-V1.6-20250910.pdf”
运行环境:
部分核心代码:
- //pwm更新中断,约23kHz
- void pwma_sr(void) interrupt 26
- {
- static U8 div=0;
- static U8 zp=0,twait=0,zstate=0;
- U16 v1,v2,v3,v;
- S16 p1,p2,e;
- U8 p,c;
- PWMA_SR1=0;//清标志
- //PTEST^=1;
- //----------产生三相SPWM
- mot_vp+=mot_speed;
- p=mot_vp>>8;//0~255
- v1=(U16)SINTAB[p]*set_duty/256+20;
- v2=(U16)SINTAB[(p-256/3)&0xFF]*set_duty/256+20;//移相120度
- v3=(U16)SINTAB[(p-512/3)&0xFF]*set_duty/256+20;
- Foc_Pwm_Swx(v1,v2,v3);
- //----------产生三相SPWM
- if(mot_state==0)//停止状态
- {
- pwm_off();
- mot_speed=SPEED_START1;
- }
- else if(mot_state==1)//开环启动
- {
- pwm_on();
- zstate=0;
- div++;
- if(div>=230)//10ms
- {
- div=0;
- if(mot_speed<SPEED_START2)
- {
- mot_speed++;
- }
- else if(p<20)//达到指定速度且在初始相位附近
- {
- mot_state++;
- }
- }
- }
- else if(mot_state==2)//闭环检测
- {//在固定的相位区间里关PWM检测反电势并调速
- if(zstate==0)//等待达到指定相位关PWM
- {
- if(p>(256L*(DEGSET-20)/360))//提前20度
- {
- PTEST=1;
- zstate++;
- pwm_off();//关PWM,关断6只MOS,
- }
- }
- else if(zstate==1)//等待过零(比较器输出0)
- {
- c=CMPCR1&1;//比较器输出
- if(c==0)//过零
- {
- PTEST=0;
- pwm_on();
- zstate++;
- //跟据相位差调整电周期,改变速度
- v=65536/mot_speed;//电周期,
- p1=p;
- p2=256L*(DEGSET)/360;
- e=p1-p2;//当前相位与目标相位相差
-
- if(e>20)e=20;
- if(e<-20)e=-20;
- v+=e/2;
- //mot_speed=65536/v;
- mot_speed-=e;
-
- mot_vp=65536L*DEGSET/360;
- }
- if(p>=256L*(DEGSET+60)/360)//未等到过零
- {
- zstate=0;
- mot_state=0;
- }
- }
- else if(zstate==2)//等待下一周期
- {
- if(p<(256L*(DEGSET-10)/360))
- zstate=0;
- }
- }
- }
- void main(void)
- {
- ......
- while(1)
- {
- if(mot_state==0)//自动重启
- {
- delayms(1000);
- mot_state=1;
- }
-
- }
- }
复制代码
|