怀化网站设计,网站死链接怎么处理,网页设计尺寸厘米,买购网官方网站dsp28335 PMSM三相永磁同步电机矢量控制源代码#xff0c;包含clarke变换#xff0c;park变换#xff0c;svpwm#xff0c;pi控制等#xff0c;同时包含adc,eeprom,can,i2c,spi,定时器等驱动代码#xff0c;已在实际项目中运用最近在搞三相永磁同步电机#xff08;PMSM float32 Bs; float32 Cs; } ABC_Input; void clarke_transform(ABC_Input *input, float32 *alpha, float32 *beta) { *alpha input-As; *beta (input-As 2*input-Bs)/SQRT3; // SQRT3用查表更快 }代码里SQRT3换成查表法能省下0.5us计算时间这对20kHz的控制频率来说就是救命稻草。注意这里没做归一化处理因为后级PI控制器参数已经按实际量程整定了。Park变换有个坑得重点说说。角度输入必须用DSP的QEP模块实时获取我们项目里发现编码器信号受干扰时角度跳变会导致park变换输出发癫。解决办法是加了个角度变化率限制// 角度预处理函数 float32 angle_sanity_check(float32 theta) { static float32 last_theta 0.0; float32 delta theta - last_theta; if(fabs(delta) 0.1) { // 超过0.1rad/周期就限幅 theta last_theta SIGN(delta)*0.1; } last_theta theta; return theta; }这个限幅值0.1是根据电机最大机械转速换算来的别拍脑袋随便设。实测能有效避免编码器丢脉冲引发的系统崩溃。SVPWM生成部分最刺激直接关系到IGBT的死活。我们方案里用EPWM模块的AQ子模块实现关键在死区时间的配置void EPWM_Config(void) { EPwm1Regs.CMPA.half.CMPA 500; // 初始占空比 EPwm1Regs.DBCTL.bit.OUT_MODE 0x3; // 双边延时模式 EPwm1Regs.DBRED 80; // 上升沿延时 1.6us EPwm1Regs.DBFED 80; // 下降沿延时 EPwm1Regs.AQCTLA.bit.CAU 0x1; // 比较匹配时拉高 }死区时间计算要考虑IGBT开关特性的实测数据我们项目用的英飞凌模块手册标注1.2us但实测要留1.5us余量。这里寄存器值80对应系统时钟150MHz的分频设置别直接用理论值。dsp28335 PMSM三相永磁同步电机矢量控制源代码包含clarke变换park变换svpwmpi控制等同时包含adc,eeprom,can,i2c,spi,定时器等驱动代码已在实际项目中运用PI控制器才是真正的玄学现场。代码里搞了个抗积分饱和的变体typedef struct { float32 Kp; float32 Ki; float32 max_output; float32 integral; } PI_Controller; float32 pi_update(PI_Controller *pi, float32 error) { pi-integral error * Ki; // 抗饱和处理 if(fabs(pi-integral) pi-max_output * 2) { pi-integral SIGN(pi-integral) * pi-max_output * 2; } float32 output error * Kp pi-integral; return CLAMP(output, -pi-max_output, pi-max_output); }重点在积分项限制是最大输出的2倍这个魔法数字是调了三天三夜试出来的。实测比常规的积分限幅响应速度快30%特别是在突加负载时转矩跌落明显改善。外设驱动里ADC校准最要命DSP内部基准电压会随温度漂移。我们搞了个开机自校准套路void ADC_SelfCalibrate(void) { AdcRegs.ADCCTL1.bit.ADCBGPWD 1; // 开启带隙电源 DELAY_US(100); // 等电压稳定 AdcRegs.ADCCTL1.bit.ADCREFSEL 1; // 切换内部参考 AdcRegs.ADCSOC0CTL.bit.CHSEL 0x0D; // 采样通道13(内部基准) while(!AdcRegs.ADCINTFLG.bit.ADCINT0); // 等待转换完成 int32 calib_value AdcResult.ADCRESULT0; AdcOffset 2048 - calib_value; // 计算偏移量 }这个校准要在每次上电时执行能把零漂控制在±5LSB以内。注意带隙电源稳定时间不能省有一次偷懒改成10us结果导致批量产品全部电流采样不准。CAN通信搞了个双缓冲机制避免实时控制被通信中断拖垮#pragma DATA_SECTION(CAN_Queue, DMARAM); volatile CAN_Msg CAN_Queue[32]; volatile uint16_t CAN_Head 0; volatile uint16_t CAN_Tail 0; interrupt void CAN_ISR(void) { while(CanaRegs.CANRMP.bit.RMP31 0) { CAN_Queue[CAN_Head] *(volatile CAN_Msg*)0x6000; CAN_Head (CAN_Head 1) 0x1F; CanaRegs.CANRMP.bit.RMP31 1; // 清标志 } }用DMA区域做缓冲队列配合位带操作直接访问寄存器实测中断响应时间控制在2us以内。注意队列长度32不是随便定的要根据CAN总线最大负载率计算我们项目实测20%负载时32深度刚好不会溢出。最后说说EEPROM存储参数的老大难问题。频繁写入会导致寿命耗尽我们搞了个写延迟策略#define EEPROM_SAVE_DELAY 60000 // 1分钟 uint32_t last_save_time 0; void parameter_save_check(void) { if(sys_tick - last_save_time EEPROM_SAVE_DELAY) { if(parameter_dirty_flag) { write_eeprom_page(0x1000, ¶m_pool, sizeof(param_pool)); last_save_time sys_tick; parameter_dirty_flag 0; } } }配合片内EEPROM的磨损均衡算法把写操作分散到不同物理地址。实测在每天300次参数修改的场景下五年没出现存储故障。整个方案最深刻的教训是仿真完美不等于实际能用。有一次SVPWM代码在示波器上看波形完美但一接电机就炸管最后发现是PWM输出极性配反了。所以现在调试必加三级保护软件限幅、硬件比较器、快速熔断器三保险缺一不可。