当前位置: 首页 > wzjs >正文

外贸免费自助建站平台seo免费外链工具

外贸免费自助建站平台,seo免费外链工具,昆明企业做网站,网站如何做关键词Odrive源码分析(七) Park逆变换 Odrive中FOC部分代码分散在各个对象中,并不是集中在某一块,所以试图在某一段代码就能得到FOC全貌是不现实的。 先看下FOC的整个流程: 控制变量到三相电流输出的关键部分分为Park逆变换和SVPWM。本文主要讨论…

Odrive源码分析(七) Park逆变换

Odrive中FOC部分代码分散在各个对象中,并不是集中在某一块,所以试图在某一段代码就能得到FOC全貌是不现实的。

先看下FOC的整个流程:
FOC控制流程图

控制变量到三相电流输出的关键部分分为Park逆变换和SVPWM。本文主要讨论逆park变换在odrive中的代码实现。、

代码主要在FieldOrientedController::get_alpha_beta_output函数中。

ODriveIntf::MotorIntf::Error FieldOrientedController::get_alpha_beta_output(uint32_t output_timestamp, std::optional<float2D>* mod_alpha_beta,std::optional<float>* ibus) {if (!vbus_voltage_measured_.has_value() || !Ialpha_beta_measured_.has_value()) {// FOC didn't receive a current measurement yet.return Motor::ERROR_CONTROLLER_INITIALIZING;} else if (abs((int32_t)(i_timestamp_ - ctrl_timestamp_)) > MAX_CONTROL_LOOP_UPDATE_TO_CURRENT_UPDATE_DELTA) {// Data from control loop and current measurement are too far apart.return Motor::ERROR_BAD_TIMING;}// TODO: improve efficiency in case PWM updates are requested at a higher// rate than current sensor updates. In this case we can reuse mod_d and// mod_q from a previous iteration.if (!Vdq_setpoint_.has_value()) {return Motor::ERROR_UNKNOWN_VOLTAGE_COMMAND;} else if (!phase_.has_value() || !phase_vel_.has_value()) {return Motor::ERROR_UNKNOWN_PHASE_ESTIMATE;} else if (!vbus_voltage_measured_.has_value()) {return Motor::ERROR_UNKNOWN_VBUS_VOLTAGE;}auto [Vd, Vq] = *Vdq_setpoint_;float phase = *phase_;float phase_vel = *phase_vel_;float vbus_voltage = *vbus_voltage_measured_;std::optional<float2D> Idq;// Park transformif (Ialpha_beta_measured_.has_value()) {auto [Ialpha, Ibeta] = *Ialpha_beta_measured_;float I_phase = phase + phase_vel * ((float)(int32_t)(i_timestamp_ - ctrl_timestamp_) / (float)TIM_1_8_CLOCK_HZ);float c_I = our_arm_cos_f32(I_phase);float s_I = our_arm_sin_f32(I_phase);Idq = {c_I * Ialpha + s_I * Ibeta,c_I * Ibeta - s_I * Ialpha};Id_measured_ += I_measured_report_filter_k_ * (Idq->first - Id_measured_);Iq_measured_ += I_measured_report_filter_k_ * (Idq->second - Iq_measured_);} else {Id_measured_ = 0.0f;Iq_measured_ = 0.0f;}float mod_to_V = (2.0f / 3.0f) * vbus_voltage;float V_to_mod = 1.0f / mod_to_V;float mod_d;float mod_q;if (enable_current_control_) {// Current control modeif (!pi_gains_.has_value()) {return Motor::ERROR_UNKNOWN_GAINS;} else if (!Idq.has_value()) {return Motor::ERROR_UNKNOWN_CURRENT_MEASUREMENT;} else if (!Idq_setpoint_.has_value()) {return Motor::ERROR_UNKNOWN_CURRENT_COMMAND;}auto [p_gain, i_gain] = *pi_gains_;auto [Id, Iq] = *Idq;auto [Id_setpoint, Iq_setpoint] = *Idq_setpoint_;float Ierr_d = Id_setpoint - Id;float Ierr_q = Iq_setpoint - Iq;// Apply PI control (V{d,q}_setpoint act as feed-forward terms in this mode)mod_d = V_to_mod * (Vd + v_current_control_integral_d_ + Ierr_d * p_gain);mod_q = V_to_mod * (Vq + v_current_control_integral_q_ + Ierr_q * p_gain);// Vector modulation saturation, lock integrator if saturated// TODO make maximum modulation configurablefloat mod_scalefactor = 0.80f * sqrt3_by_2 * 1.0f / std::sqrt(mod_d * mod_d + mod_q * mod_q);if (mod_scalefactor < 1.0f) {mod_d *= mod_scalefactor;mod_q *= mod_scalefactor;// TODO make decayfactor configurablev_current_control_integral_d_ *= 0.99f;v_current_control_integral_q_ *= 0.99f;} else {v_current_control_integral_d_ += Ierr_d * (i_gain * current_meas_period);v_current_control_integral_q_ += Ierr_q * (i_gain * current_meas_period);}} else {// Voltage control modemod_d = V_to_mod * Vd;mod_q = V_to_mod * Vq;}// Inverse park transformfloat pwm_phase = phase + phase_vel * ((float)(int32_t)(output_timestamp - ctrl_timestamp_) / (float)TIM_1_8_CLOCK_HZ);float c_p = our_arm_cos_f32(pwm_phase);float s_p = our_arm_sin_f32(pwm_phase);float mod_alpha = c_p * mod_d - s_p * mod_q;float mod_beta = c_p * mod_q + s_p * mod_d;// Report final applied voltage in stationary frame (for sensorless estimator)final_v_alpha_ = mod_to_V * mod_alpha;final_v_beta_ = mod_to_V * mod_beta;*mod_alpha_beta = {mod_alpha, mod_beta};if (Idq.has_value()) {auto [Id, Iq] = *Idq;*ibus = mod_d * Id + mod_q * Iq;power_ = vbus_voltage * (*ibus).value();}return Motor::ERROR_NONE;
}

下面主要分析上述函数的具体实现:

step1 在进入本函数计算之前,必须已经完成线电压的测量和相电流的测量,同时要保证时效性,如下所示:

//本函数调用前,在ControlLoop_IRQHandler函数中已经完成了测量。所以本条件必然满足。
if (!vbus_voltage_measured_.has_value() || !Ialpha_beta_measured_.has_value()) {// FOC didn't receive a current measurement yet.return Motor::ERROR_CONTROLLER_INITIALIZING;
} 
//i_timestamp_和ctrl_timestamp_实际上是同一个值,因为都是外部传进来的
else if (abs((int32_t)(i_timestamp_ - ctrl_timestamp_)) > MAX_CONTROL_LOOP_UPDATE_TO_CURRENT_UPDATE_DELTA) {// Data from control loop and current measurement are too far apart.return Motor::ERROR_BAD_TIMING;
}

step2 相关控制数据检查,如下所示:

//判断是否已经计算出Vdq_setpoint(motor.cpp已通过PID计算得出)
if (!Vdq_setpoint_.has_value()) {return Motor::ERROR_UNKNOWN_VOLTAGE_COMMAND;
} 
//判断是否已经得到电角度和电角速度(已经通过encode.cpp计算得出)
else if (!phase_.has_value() || !phase_vel_.has_value()) {return Motor::ERROR_UNKNOWN_PHASE_ESTIMATE;
} 
//这里其实重复判断了...
else if (!vbus_voltage_measured_.has_value()) {return Motor::ERROR_UNKNOWN_VBUS_VOLTAGE;
}//变量提取
auto [Vd, Vq] = *Vdq_setpoint_;
float phase = *phase_;
float phase_vel = *phase_vel_;
float vbus_voltage = *vbus_voltage_measured_;

step3 通过测量到的电流进行Park变换转换到观察到的DQ,如下所示:

// 检查AB空间数据有效性,Ialpha_beta_measured_是通过FieldOrientedController父类 AlphaBetaFrameController::on_measurement计算得出。
if (Ialpha_beta_measured_.has_value()) {auto [Ialpha, Ibeta] = *Ialpha_beta_measured_;//这里得到电流测量时刻的电角度,这里很严谨,虽然i_timestamp_和 ctrl_timestamp_其实是相等的值,但是软件保留了拓展能力。float I_phase = phase + phase_vel * ((float)(int32_t)(i_timestamp_ - ctrl_timestamp_) / (float)TIM_1_8_CLOCK_HZ);//计算Park变换得到测量的DQ值用于后面的电流环闭环float c_I = our_arm_cos_f32(I_phase);float s_I = our_arm_sin_f32(I_phase);Idq = {c_I * Ialpha + s_I * Ibeta,c_I * Ibeta - s_I * Ialpha};Id_measured_ += I_measured_report_filter_k_ * (Idq->first - Id_measured_);Iq_measured_ += I_measured_report_filter_k_ * (Idq->second - Iq_measured_);
} else {Id_measured_ = 0.0f;Iq_measured_ = 0.0f;
}//相关中间变量计算
//这里mod_to_V是线电压的2/3.实际上这是相电压能达到的最大值,这里可以理解为SVPWM扇区的内接圆半径。
float mod_to_V = (2.0f / 3.0f) * vbus_voltage;
float V_to_mod = 1.0f / mod_to_V;
float mod_d;
float mod_q;

step4 电流环控制,如下所示:

//只有在开启了电流闭环控制时以下代码才会生效
//当motor_.config_.motor_type 为 Motor::MOTOR_TYPE_GIMBA 云台电机时,不使用电流控制模式而采用电压控制模式。
if (enable_current_control_) {//检查是否配置了PI参数if (!pi_gains_.has_value()) {return Motor::ERROR_UNKNOWN_GAINS;} //电流环控制必须已经得到了Idq(上面计算已经得出)else if (!Idq.has_value()) {return Motor::ERROR_UNKNOWN_CURRENT_MEASUREMENT;} //是否存在控制量Idq_setpoint_(该变量已经由motor.cpp中计算得出)else if (!Idq_setpoint_.has_value()) {return Motor::ERROR_UNKNOWN_CURRENT_COMMAND;}//语法糖auto [p_gain, i_gain] = *pi_gains_;auto [Id, Iq] = *Idq;auto [Id_setpoint, Iq_setpoint] = *Idq_setpoint_;//使用PI控制计算得出mod_q,mod_d,这里mod_q和mod_d可以理解为mod_to_V的倍数。float Ierr_d = Id_setpoint - Id;float Ierr_q = Iq_setpoint - Iq;//Vd/Vq作为前馈量加入到电流环PI控制中mod_d = V_to_mod * (Vd + v_current_control_integral_d_ + Ierr_d * p_gain);mod_q = V_to_mod * (Vq + v_current_control_integral_q_ + Ierr_q * p_gain);// Vector modulation saturation, lock integrator if saturated// TODO make maximum modulation configurablefloat mod_scalefactor = 0.80f * sqrt3_by_2 * 1.0f / std::sqrt(mod_d * mod_d + mod_q * mod_q);if (mod_scalefactor < 1.0f) {mod_d *= mod_scalefactor;mod_q *= mod_scalefactor;// TODO make decayfactor configurablev_current_control_integral_d_ *= 0.99f;v_current_control_integral_q_ *= 0.99f;} else {v_current_control_integral_d_ += Ierr_d * (i_gain * current_meas_period);v_current_control_integral_q_ += Ierr_q * (i_gain * current_meas_period);}} else {//直接使用Vd/Vq 电压控制,得到控制量为mod_to_V的倍数。mod_d = V_to_mod * Vd;mod_q = V_to_mod * Vq;
}

step5 正式完成park逆变换,如下所示:

//这里得到电角度,这里output_timestamp的时间会大于ctrl_timestamp_(理论上真好会大于一个控制周期),此时的电角度比测量电流时的电角度是不同的。
float pwm_phase = phase + phase_vel * ((float)(int32_t)(output_timestamp - ctrl_timestamp_) / (float)TIM_1_8_CLOCK_HZ);
float c_p = our_arm_cos_f32(pwm_phase);
float s_p = our_arm_sin_f32(pwm_phase);
float mod_alpha = c_p * mod_d - s_p * mod_q;
float mod_beta = c_p * mod_q + s_p * mod_d;// Report final applied voltage in stationary frame (for sensorless estimator)
final_v_alpha_ = mod_to_V * mod_alpha;
final_v_beta_ = mod_to_V * mod_beta;//得到最终计算出的AB控制量(后面会输入到SVPWM模块逆变出三相电流)
*mod_alpha_beta = {mod_alpha, mod_beta};//计算出相关数据
if (Idq.has_value()) {auto [Id, Iq] = *Idq;//计算出线电流*ibus = mod_d * Id + mod_q * Iq;//计算功率(电压和电流乘积)power_ = vbus_voltage * (*ibus).value();
}

完成Park逆变换后,下一步就直接送入了SVPWM模块了。

http://www.dtcms.com/wzjs/59455.html

相关文章:

  • wordpress 获取用户角色百度排名优化咨询电话
  • 公安局内网网站建设的现状贵港seo关键词整站优化
  • 铭做网站建设网络建站
  • 网站认证怎么做html网站模板免费
  • 开淘宝店和自己做购物网站哪个好百度搜索引擎入口
  • 做的网站图片不显示网络推广费用高吗
  • 公司做网站提供产品加盟费2023年8月份新冠病毒
  • 云主机做网站免费数据统计网站
  • 高埗做网站游戏推广可以做吗
  • php开发网站后台销售管理软件
  • 做网站即墨宁波seo网络优化公司
  • 做展馆的公司有哪些武汉标兵seo
  • 企业网站后台管理系统模板各城市首轮感染高峰期预测
  • 企业做网站哪家好企业网络营销推广
  • 购物类网站开发蜘蛛搜索
  • 404 wordpress青岛seo关键词排名
  • 给素材网站做签约设计不想做了品牌形象推广
  • 机械外贸网站seo技术员
  • 自己做的网站怎么上传到网络英文seo是什么意思
  • 做网站用boot百度推广图片
  • 图书馆门户网站建设方案广东广州网点快速网站建设
  • 深圳大型论坛网站建设广州网络科技有限公司
  • css的作用新余seo
  • 惠州网站建设 熊掌号重庆整站seo
  • 网站如何添加二维码小网站搜什么关键词好
  • 小学做试卷的网站应用市场
  • 绍兴网站建设设计上海网络seo优化公司
  • 网站背景图片怎么做怎么做网站宣传
  • 2018做网站还是app指数搜索
  • 企业网站后台管理软件网络广告投放