/* * Copyright (c) 2021 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * */ #include "hpm_common.h" #include "hpm_bldc_define.h" #include "hpm_foc.h" #include "hpm_smc.h" void hpm_mcl_nullcallback_func(void) { while (1) { ; } } /* * * * #include * #include * #define NUM 501 * #define PRECISION 0.18 * #define PI 3.14159265 * int main() * { * short i; * printf("staitc const float bldc_foc_sintable[%d] =\r",NUM); * printf("{\r"); * for(i=0;ispeedtheta - par->speedlasttheta; if (delta > HPM_MOTOR_MATH_FL_MDF(180)) {/*-speed*/ delta = -par->speedlasttheta - (HPM_MOTOR_MATH_FL_MDF(360) - par->speedtheta); } else if (delta < HPM_MOTOR_MATH_FL_MDF(-180)) {/*+speed*/ delta = HPM_MOTOR_MATH_FL_MDF(360) + par->speedtheta - par->speedlasttheta; } par->speedthetalastn += delta; par->speedlasttheta = par->speedtheta; par->num++; if (par->i_speedacq == par->num) { par->num = 0; par->o_speedout = HPM_MOTOR_MATH_DIV(par->speedthetalastn, HPM_MOTOR_MATH_MUL(HPM_MOTOR_MATH_MUL(par->i_speedlooptime_s, HPM_MOTOR_MATH_FL_MDF(par->i_motorpar->i_poles_n)), HPM_MOTOR_MATH_FL_MDF(360))); par->o_speedout_filter = par->o_speedout_filter + HPM_MOTOR_MATH_MUL(par->i_speedfilter, (par->o_speedout - par->o_speedout_filter)); par->speedthetalastn = 0; } } static void bldc_foc_sin_cos(HPM_MOTOR_MATH_TYPE angle, HPM_MOTOR_MATH_TYPE angle_precision, HPM_MOTOR_MATH_TYPE *sin_angle, HPM_MOTOR_MATH_TYPE *cos_angle) { int16_t transfer = 0; uint16_t angle_int = HPM_MOTOR_MATH_MDF_FL(angle); if (angle_int < HPM_MOTOR_MATH_FL_MDF(90)) { transfer = HPM_MOTOR_MATH_MDF_FL(HPM_MOTOR_MATH_DIV(angle, angle_precision)); *sin_angle = HPM_MOTOR_MATH_FL_MDF(bldc_foc_sintable[transfer]); *cos_angle = HPM_MOTOR_MATH_FL_MDF(bldc_foc_sintable[SIN_TABLE_INDEX_MAX - transfer]); } else if (angle_int < HPM_MOTOR_MATH_FL_MDF(180)) { transfer = HPM_MOTOR_MATH_MDF_FL(HPM_MOTOR_MATH_DIV((HPM_MOTOR_MATH_FL_MDF(180) - angle), angle_precision)); *sin_angle = HPM_MOTOR_MATH_FL_MDF(bldc_foc_sintable[transfer]); *cos_angle = HPM_MOTOR_MATH_FL_MDF(-bldc_foc_sintable[SIN_TABLE_INDEX_MAX - transfer]); } else if (angle_int < HPM_MOTOR_MATH_FL_MDF(270)) { transfer = HPM_MOTOR_MATH_MDF_FL(HPM_MOTOR_MATH_DIV((angle - HPM_MOTOR_MATH_FL_MDF(180)), angle_precision)); *sin_angle = HPM_MOTOR_MATH_FL_MDF(-bldc_foc_sintable[transfer]); *cos_angle = HPM_MOTOR_MATH_FL_MDF(-bldc_foc_sintable[SIN_TABLE_INDEX_MAX - transfer]); } else if (angle_int <= HPM_MOTOR_MATH_FL_MDF(360)) { transfer = HPM_MOTOR_MATH_MDF_FL(HPM_MOTOR_MATH_DIV((HPM_MOTOR_MATH_FL_MDF(360)-angle), angle_precision)); *sin_angle = HPM_MOTOR_MATH_FL_MDF(-bldc_foc_sintable[transfer]); *cos_angle = HPM_MOTOR_MATH_FL_MDF(bldc_foc_sintable[SIN_TABLE_INDEX_MAX - transfer]); } } void hpm_mcl_bldc_foc_inv_park(HPM_MOTOR_MATH_TYPE ud, HPM_MOTOR_MATH_TYPE uq, HPM_MOTOR_MATH_TYPE *ualpha, HPM_MOTOR_MATH_TYPE *ubeta, HPM_MOTOR_MATH_TYPE sin_angle, HPM_MOTOR_MATH_TYPE cos_angle) { *ualpha = HPM_MOTOR_MATH_MUL(cos_angle, ud) + HPM_MOTOR_MATH_MUL(-sin_angle, uq); *ubeta = HPM_MOTOR_MATH_MUL(sin_angle, ud) + HPM_MOTOR_MATH_MUL(cos_angle, uq); } void hpm_mcl_bldc_foc_svpwm(BLDC_CONTROL_PWM_PARA *par) { int32_t ualpha_60, ubeta_30; uint32_t pwm_reload; int32_t uref1, uref2, uref3; int32_t tx, ty, t0; int32_t tuon, tvon, twon = 0; int8_t sector = 0; uref1 = HPM_MOTOR_MATH_MDF_FL(par->target_beta); ualpha_60 = HPM_MOTOR_MATH_MDF_FL(par->target_alpha); ubeta_30 = HPM_MOTOR_MATH_MDF_FL(par->target_beta); ualpha_60 = (ualpha_60 * 14189) >> 14; ubeta_30 = ubeta_30 >> 1; uref2 = HPM_MOTOR_MATH_MDF_FL(ualpha_60 - ubeta_30); uref3 = HPM_MOTOR_MATH_MDF_FL(-ualpha_60 - ubeta_30); pwm_reload = par->pwmout.i_pwm_reload; if (uref1 >= 0) sector = 1; if (uref2 >= 0) sector = sector + 2; if (uref3 >= 0) sector = sector + 4; switch (sector) { case 1: /* sector2 000 010 110 111 110 010 000 */ tx = -uref2; ty = -uref3; t0 = pwm_reload - tx - ty; /* tx + ty > T */ if (t0 < 0) { tx = ((float)tx / (tx + ty)) * pwm_reload; ty = pwm_reload - tx; t0 = 0; } twon = t0 >> 1; tuon = ty + twon; tvon = tx + tuon; break; case 2: /* sector6 000 100 101 111 101 100 000 */ tx = -uref3; ty = -uref1; t0 = pwm_reload - tx - ty; if (t0 < 0) { tx = ((float)tx / (tx + ty)) * pwm_reload; ty = pwm_reload - tx; t0 = 0; } tvon = t0 >> 1; twon = ty + tvon; tuon = tx + twon; break; case 3: /* sector1 000 100 110 111 110 100 000 */ tx = uref2; ty = uref1; t0 = pwm_reload - tx - ty; if (t0 < 0) { tx = ((float)tx / (tx + ty)) * pwm_reload; ty = pwm_reload - tx; t0 = 0; } twon = t0 >> 1; tvon = ty + twon; tuon = tx + tvon; break; case 4: /* sector4 000 001 011 111 011 001 000 */ tx = -uref1; ty = -uref2; t0 = pwm_reload - tx - ty; if (t0 < 0) { tx = ((float)tx / (tx + ty)) * pwm_reload; ty = pwm_reload - tx; t0 = 0; } tuon = t0 >> 1; tvon = ty + tuon; twon = tx + tvon; break; case 5: /* sector5 000 010 011 111 011 010 000 */ tx = uref1; ty = uref3; t0 = pwm_reload - tx - ty; if (t0 < 0) { tx = ((float)tx / (tx + ty)) * pwm_reload; ty = pwm_reload - tx; t0 = 0; } tuon = t0 >> 1; twon = ty + tuon; tvon = tx + twon; break; case 6: /* sector6 000 001 101 111 101 001 000 */ tx = uref3; ty = uref2; t0 = pwm_reload - tx - ty; if (t0 < 0) { tx = ((float)tx / (tx + ty)) * pwm_reload; ty = pwm_reload - tx; t0 = 0; } tvon = t0 >> 1; tuon = ty + tvon; twon = tx + tuon; break; default: tuon = (int)(pwm_reload/2); tvon = (int)(pwm_reload/2); twon = (int)(pwm_reload/2); } par->sector = sector; if (tuon < 0) tuon = 0; if (tuon < 0) tvon = 0; if (tuon < 0) twon = 0; par->pwmout.pwm_u = tuon; par->pwmout.pwm_v = tvon; par->pwmout.pwm_w = twon; } void hpm_mcl_bldc_foc_clarke(HPM_MOTOR_MATH_TYPE currentu, HPM_MOTOR_MATH_TYPE currentv, HPM_MOTOR_MATH_TYPE currentw, HPM_MOTOR_MATH_TYPE *currentalpha, HPM_MOTOR_MATH_TYPE *currentbeta) { int32_t curbeta; (void)currentw; *currentalpha = currentu; curbeta = (((int)(9370 * HPM_MOTOR_MATH_MDF_FL(currentu))) + ((int)(18918 * HPM_MOTOR_MATH_MDF_FL(currentv))))>>14; *currentbeta = HPM_MOTOR_MATH_FL_MDF(curbeta); } void hpm_mcl_bldc_foc_park(HPM_MOTOR_MATH_TYPE currentalpha, HPM_MOTOR_MATH_TYPE currentbeta, HPM_MOTOR_MATH_TYPE *currentd, HPM_MOTOR_MATH_TYPE *currentq, HPM_MOTOR_MATH_TYPE sin_angle, HPM_MOTOR_MATH_TYPE cos_angle) { *currentd = HPM_MOTOR_MATH_MUL(cos_angle, currentalpha) + HPM_MOTOR_MATH_MUL(sin_angle, currentbeta); *currentq = HPM_MOTOR_MATH_MUL(-sin_angle, currentalpha) + HPM_MOTOR_MATH_MUL(cos_angle, currentbeta); } void hpm_mcl_bldc_foc_current_cal(BLDC_CONTROL_CURRENT_PARA *par) { par->cal_u = HPM_MOTOR_MATH_FL_MDF(par->adc_u_middle - par->adc_u); par->cal_v = HPM_MOTOR_MATH_FL_MDF(par->adc_v_middle - par->adc_v); par->cal_w = HPM_MOTOR_MATH_FL_MDF(-(par->cal_u + par->cal_v)); } void hpm_mcl_bldc_foc_pi_contrl(BLDC_CONTRL_PID_PARA *par) { HPM_MOTOR_MATH_TYPE result = 0; HPM_MOTOR_MATH_TYPE curerr = 0; HPM_MOTOR_MATH_TYPE portion_asp = 0; HPM_MOTOR_MATH_TYPE portion_asi = 0; curerr = par->target - par->cur; portion_asp = HPM_MOTOR_MATH_MUL(curerr, (par->i_kp)); portion_asi = HPM_MOTOR_MATH_MUL(curerr, (par->i_ki)) + par->mem; result = portion_asi + portion_asp; if (result < (-par->i_max)) { result = -par->i_max; } else if (result > par->i_max) { result = par->i_max; } else { par->mem = portion_asi; } par->outval = result; } void hpm_mcl_bldc_foc_ctrl_dq_to_pwm(BLDC_CONTROL_FOC_PARA *par) { HPM_MOTOR_MATH_TYPE sin_angle = 0; HPM_MOTOR_MATH_TYPE cos_angle = 0; par->samplcurpar.func_sampl(&par->samplcurpar); hpm_mcl_bldc_foc_clarke(par->samplcurpar.cal_u, par->samplcurpar.cal_v, par->samplcurpar.cal_w, &par->ialpha, &par->ibeta); bldc_foc_sin_cos(par->electric_angle, PRECISION, &sin_angle, &cos_angle); hpm_mcl_bldc_foc_park(par->ialpha, par->ibeta, &par->currentdpipar.cur, &par->currentqpipar.cur, sin_angle, cos_angle); par->currentdpipar.func_pid(&par->currentdpipar); par->currentqpipar.func_pid(&par->currentqpipar); hpm_mcl_bldc_foc_inv_park(par->currentdpipar.outval, par->currentqpipar.outval, &par->ualpha, &par->ubeta, sin_angle, cos_angle); par->pwmpar.target_alpha = par->ualpha; par->pwmpar.target_beta = par->ubeta; par->pwmpar.func_spwm(&par->pwmpar); }