电机IF启动
1.代码
含矫正的
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc) { int32_t ADCDataReg[4]; HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin); MOTOR_vars.ISRCount++; ADCDataReg[0] = hadc1.Instance->JDR1; //ia ADCDataReg[1] = hadc2.Instance->JDR1; //ib ADCDataReg[2] = hadc1.Instance->JDR2; //ic ADCDataReg[3]= hadc2.Instance->JDR2; //ia /* Disable ADC trigger source */ /* LL_TIM_CC_DisableChannel(TIMx, LL_TIM_CHANNEL_CH4) */ LL_TIM_SetTriggerOutput(TIM1, LL_TIM_TRGO_RESET); RCM_Conv(); if(MOTOR_vars.offset_complete == 0) { if(MOTOR_vars.offset_I_ad_cnt ==0) { AdcData.offset_I_ad_sum.value[0] = 0; AdcData.offset_I_ad_sum.value[1] = 0; AdcData.offset_I_ad_sum.value[2] = 0; } AdcData.offset_I_ad_sum.value[0] +=ADCDataReg[0]; AdcData.offset_I_ad_sum.value[1] +=ADCDataReg[1]; AdcData.offset_I_ad_sum.value[2] +=ADCDataReg[2]; MOTOR_vars.offset_I_ad_cnt ++; if(MOTOR_vars.offset_I_ad_cnt >= 256) { MOTOR_vars.offset_I_ad_cnt =0; AdcData.offset_I_ad.value[0] =AdcData.offset_I_ad_sum.value[0]>>8; AdcData.offset_I_ad.value[1] =AdcData.offset_I_ad_sum.value[1]>>8; AdcData.offset_I_ad.value[2] =AdcData.offset_I_ad_sum.value[2]>>8; AdcData.offset_I_ad_sum.value[0] =0; AdcData.offset_I_ad_sum.value[1] =0; AdcData.offset_I_ad_sum.value[2] =0; MOTOR_vars.offset_complete =1; } } else { AdcData.I_A.value[0] = ((ADCDataReg[0]-AdcData.offset_I_ad.value[0])*USER_M1_ADC_FULL_SCALE_CURRENT_A) >>15; AdcData.I_A.value[1] = ((ADCDataReg[1]-AdcData.offset_I_ad.value[1])*USER_M1_ADC_FULL_SCALE_CURRENT_A) >>15; AdcData.I_A.value[2] = ((ADCDataReg[2]-AdcData.offset_I_ad.value[2])*USER_M1_ADC_FULL_SCALE_CURRENT_A) >>15; //MOTOR_vars.speed_int_Hz =100; ANGLE_GEN_run(MOTOR_vars.speed_int_Hz); // Speed reference value, Hz MOTOR_vars.angleGen_rad = MOTOR_vars.angle_rad; // the rotor angle from Generator modules // Trig_Components Local_Vector_Components; // 3 sinwave // Local_Vector_Components = MCM_Trig_Functions(MOTOR_vars.angleGen_rad); // AdcData.I_A.value[0] =Local_Vector_Components.hSin; // Local_Vector_Components = MCM_Trig_Functions(MOTOR_vars.angleGen_rad-21845); //120degree // AdcData.I_A.value[1] =Local_Vector_Components.hSin; // Local_Vector_Components = MCM_Trig_Functions(MOTOR_vars.angleGen_rad+21845); //240degree // AdcData.I_A.value[2] =Local_Vector_Components.hSin; CLARKE_run(&AdcData.I_A, &MOTOR_vars.Iab_A); MOTOR_vars.counterTrajSpeed++; if(MOTOR_vars.counterTrajSpeed >= 1) { // clear counter MOTOR_vars.counterTrajSpeed = 0; MOTOR_vars.trajHandle_spd.targetValue = MOTOR_vars.speedForce_Hz * MOTOR_vars.direction; // run a trajectory for speed reference, // so the reference changes with a ramp instead of a step TRAJ_run(MOTOR_vars.trajHandle_spd.targetValue); } MOTOR_vars.speed_int_Hz = MOTOR_vars.trajHandle_spd.intValueq15 >>15; MOTOR_vars.oneOverDcBus_invq15 = 32767/ AdcData.VdcBus_V; //q15 MOTOR_vars.hElAngle = MOTOR_vars.angleGen_rad; // MOTOR_vars.hElAngle += 100; PARK_run(&MOTOR_vars.Iab_A,&MOTOR_vars.Idq_in_A,MOTOR_vars.hElAngle); // I/f Profile open-loop in build level 3 MOTOR_vars.IdqRef_A.value[0] = MOTOR_vars.Idq_set_A.value[0]; MOTOR_vars.IdqRef_A.value[1] = MOTOR_vars.Idq_set_A.value[1]; // Maximum voltage output //MOTOR_vars.VsMax_V = MOTOR_vars.maxVsMag_pu * AdcData.VdcBus_V; MOTOR_vars.VsMax_V = MOTOR_vars.maxVsMag_pu; MOTOR_vars.piHandle_Id.outMin = -MOTOR_vars.VsMax_V; MOTOR_vars.piHandle_Id.outMax = MOTOR_vars.VsMax_V; // MOTOR_vars.piHandle_Id.outMin = -MOTOR_vars.VsFreqHandle.Vdq_gainq15.value[0]; // MOTOR_vars.piHandle_Id.outMax = MOTOR_vars.VsFreqHandle.Vdq_gainq15.value[0]; // run the Id controller PI_run_series(&MOTOR_vars.piHandle_Id,MOTOR_vars.IdqRef_A.value[0], MOTOR_vars.Idq_in_A.value[0],0,(int32_t*)&MOTOR_vars.Vdq_out_V.value[0]); // calculate Iq controller limits int32_t outMax_V= MCM_Sqrt(MOTOR_vars.VsMax_V * MOTOR_vars.VsMax_V-\ MOTOR_vars.Vdq_out_V.value[0] * MOTOR_vars.Vdq_out_V.value[0]); MOTOR_vars.piHandle_Iq.outMin = -outMax_V; MOTOR_vars.piHandle_Iq.outMax = outMax_V; // MOTOR_vars.piHandle_Iq.outMin = -MOTOR_vars.VsFreqHandle.Vdq_gainq15.value[1]; // MOTOR_vars.piHandle_Iq.outMax = MOTOR_vars.VsFreqHandle.Vdq_gainq15.value[1]; // run the Iq controller PI_run_series(&MOTOR_vars.piHandle_Iq,MOTOR_vars.IdqRef_A.value[1], MOTOR_vars.Idq_in_A.value[1],0,(int32_t*)&MOTOR_vars.Vdq_out_V.value[1]); MOTOR_vars.Vdq_out_V.value[0] = (MOTOR_vars.Vdq_out_V.value[0]*AdcData.VdcBus_V)>>15; MOTOR_vars.Vdq_out_V.value[1] = (MOTOR_vars.Vdq_out_V.value[1]*AdcData.VdcBus_V)>>15; // // V/f Profile open-loop in build level 2 // VS_FREQ_run(MOTOR_vars.speed_int_Hz); // MOTOR_vars.Vdq_out_V.value[0] = MOTOR_vars.VsFreqHandle.Vdq_out.value[0]; // MOTOR_vars.Vdq_out_V.value[1] = MOTOR_vars.VsFreqHandle.Vdq_out.value[1]; // run the inverse Park module IPARK_run(&MOTOR_vars.Vdq_out_V, &MOTOR_vars.Vab_out_V,MOTOR_vars.hElAngle); SVGEN_run(&MOTOR_vars.Vab_out_V,&PwmData.Vabc_pu); // output 50% // PwmData.Vabc_pu.value[0] = 0; // PwmData.Vabc_pu.value[1] = 0; // PwmData.Vabc_pu.value[2] = 0; HAL_writePWMData(&PwmData); }//end of if(MOTOR_vars.offset_complete == 0) //---------------------------------------------------------------------- //Data_scope(MOTOR_vars.hElAngle,PwmData.cmpValue[0],PwmData.cmpValue[1],PwmData.cmpValue[2]); //Data_scope(MOTOR_vars.hElAngle,AdcData.I_A.value[0],AdcData.I_A.value[1],AdcData.I_A.value[2]); Data_scope(MOTOR_vars.Iab_A.value[0],MOTOR_vars.Iab_A.value[1],MOTOR_vars.Idq_in_A.value[1],MOTOR_vars.Idq_in_A.value[0]); }除去矫正的
电流目标值
MOTOR_vars.Idq_set_A.value[0] = 0; MOTOR_vars.Idq_set_A.value[1] = 20;函数定义
else // 电流偏移校准已完成,进入闭环控制模式(I/f 电流闭环) { // 读取 ADC 三相电流采样值,减去零漂偏移后,乘以满量程系数,右移 15 位得到实际电流 Q15 值 AdcData.I_A.value[0] = ((ADCDataReg[0] - AdcData.offset_I_ad.value[0]) * USER_M1_ADC_FULL_SCALE_CURRENT_A) >> 15; AdcData.I_A.value[1] = ((ADCDataReg[1] - AdcData.offset_I_ad.value[1]) * USER_M1_ADC_FULL_SCALE_CURRENT_A) >> 15; AdcData.I_A.value[2] = ((ADCDataReg[2] - AdcData.offset_I_ad.value[2]) * USER_M1_ADC_FULL_SCALE_CURRENT_A) >> 15; // 运行角度发生器,输出当前开环电角度(用于定向) ANGLE_GEN_run(MOTOR_vars.speed_int_Hz); // 输入速度参考值(Hz) MOTOR_vars.angleGen_rad = MOTOR_vars.angle_rad; // 获取生成的角度值 // Clarke 变换:三相电流 -> 两相静止坐标系 (Iα, Iβ) CLARKE_run(&AdcData.I_A, &MOTOR_vars.Iab_A); // 速度轨迹计数器,用于降频更新速度参考(此处 >=1 即每个中断周期均更新) MOTOR_vars.counterTrajSpeed++; if(MOTOR_vars.counterTrajSpeed >= 1) { MOTOR_vars.counterTrajSpeed = 0; // 设置目标速度(带方向),然后运行速度轨迹斜坡生成器 MOTOR_vars.trajHandle_spd.targetValue = MOTOR_vars.speedForce_Hz * MOTOR_vars.direction; TRAJ_run(MOTOR_vars.trajHandle_spd.targetValue); } // 从轨迹生成器获取当前速度参考值(Q15),右移15位转换为 Hz MOTOR_vars.speed_int_Hz = MOTOR_vars.trajHandle_spd.intValueq15 >> 15; // 计算直流母线电压的倒数(Q15 格式,用于前馈或调制比计算) MOTOR_vars.oneOverDcBus_invq15 = 32767 / AdcData.VdcBus_V; // 设置当前电角度为角度发生器的输出(开环定向) MOTOR_vars.hElAngle = MOTOR_vars.angleGen_rad; // MOTOR_vars.hElAngle += 100; // 可手动加相位偏移 // Park 变换:静止坐标系电流 (Iα, Iβ) -> 旋转坐标系电流 (Id, Iq) PARK_run(&MOTOR_vars.Iab_A, &MOTOR_vars.Idq_in_A, MOTOR_vars.hElAngle); // ---------- I/f 电流闭环控制 ---------- // 设置 d、q 轴电流参考值(来自预设或上位机给定) MOTOR_vars.IdqRef_A.value[0] = MOTOR_vars.Idq_set_A.value[0]; MOTOR_vars.IdqRef_A.value[1] = MOTOR_vars.Idq_set_A.value[1]; // 计算电压矢量最大幅值限制 MOTOR_vars.VsMax_V = MOTOR_vars.maxVsMag_pu; // 最大电压标幺值(Q15) // 设置 d 轴 PI 控制器输出限幅为 ±VsMax_V MOTOR_vars.piHandle_Id.outMin = -MOTOR_vars.VsMax_V; MOTOR_vars.piHandle_Id.outMax = MOTOR_vars.VsMax_V; // 运行 d 轴 PI 控制器,输出 d 轴电压 Vd PI_run_series(&MOTOR_vars.piHandle_Id, MOTOR_vars.IdqRef_A.value[0], MOTOR_vars.Idq_in_A.value[0], 0, (int32_t*)&MOTOR_vars.Vdq_out_V.value[0]); // 根据总电压限制和 d 轴电压,计算 q 轴电压的最大允许值 (√(VsMax² - Vd²)) int32_t outMax_V = MCM_Sqrt(MOTOR_vars.VsMax_V * MOTOR_vars.VsMax_V - MOTOR_vars.Vdq_out_V.value[0] * MOTOR_vars.Vdq_out_V.value[0]); // 设置 q 轴 PI 控制器的输出限幅 MOTOR_vars.piHandle_Iq.outMin = -outMax_V; MOTOR_vars.piHandle_Iq.outMax = outMax_V; // 运行 q 轴 PI 控制器,输出 q 轴电压 Vq PI_run_series(&MOTOR_vars.piHandle_Iq, MOTOR_vars.IdqRef_A.value[1], MOTOR_vars.Idq_in_A.value[1], 0, (int32_t*)&MOTOR_vars.Vdq_out_V.value[1]); // 将 dq 电压标幺值乘以母线电压,转换为实际电压值的 Q15 表示(用于 PWM 调制) MOTOR_vars.Vdq_out_V.value[0] = (MOTOR_vars.Vdq_out_V.value[0] * AdcData.VdcBus_V) >> 15; MOTOR_vars.Vdq_out_V.value[1] = (MOTOR_vars.Vdq_out_V.value[1] * AdcData.VdcBus_V) >> 15; // 逆 Park 变换:旋转坐标系电压 -> 静止坐标系电压 (Vα, Vβ) IPARK_run(&MOTOR_vars.Vdq_out_V, &MOTOR_vars.Vab_out_V, MOTOR_vars.hElAngle); // SVPWM 生成:静止坐标系电压 -> 三相 PWM 占空比 (标幺值) SVGEN_run(&MOTOR_vars.Vab_out_V, &PwmData.Vabc_pu); // 将占空比写入定时器比较寄存器,更新 PWM 输出 HAL_writePWMData(&PwmData); } // end of if(MOTOR_vars.offset_complete == 0)