154 lines
4.5 KiB
C
154 lines
4.5 KiB
C
|
#include "Config.h"
|
|||
|
#include "foc.h"
|
|||
|
#include "foc_math.h"
|
|||
|
#include "foc_tim.h"
|
|||
|
|
|||
|
#define SECTOR_1 0u
|
|||
|
#define SECTOR_2 1u
|
|||
|
#define SECTOR_3 2u
|
|||
|
#define SECTOR_4 3u
|
|||
|
#define SECTOR_5 4u
|
|||
|
#define SECTOR_6 5u
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 根据v_alpha_beta计算svpwm
|
|||
|
*/
|
|||
|
void svpwm_calc(alphabeta_t v_alpha_beta)
|
|||
|
{
|
|||
|
int32_t w_x, w_y, w_z, w_u_alpha, w_u_beta, w_time_ph_a, w_time_ph_b, w_time_ph_c;
|
|||
|
|
|||
|
uint8_t sector;
|
|||
|
|
|||
|
w_u_alpha = v_alpha_beta.alpha * (int32_t)hT_Sqrt3;
|
|||
|
w_u_beta = -(v_alpha_beta.beta * ( int32_t )(PWM_PERIOD_CYCLES) ) * 2;
|
|||
|
|
|||
|
w_x = w_u_beta;
|
|||
|
w_y = ( w_u_beta + w_u_alpha ) / 2;
|
|||
|
w_z = ( w_u_beta - w_u_alpha ) / 2;
|
|||
|
|
|||
|
/* Sector calculation from w_x, w_y, w_z */
|
|||
|
if (w_y < 0) {
|
|||
|
if (w_z < 0) {
|
|||
|
sector = SECTOR_2;
|
|||
|
w_time_ph_a = ( int32_t )( PWM_PERIOD_CYCLES ) / 4 + ( ( w_y - w_z ) / ( int32_t )262144 );
|
|||
|
w_time_ph_b = w_time_ph_a + w_z / 131072;
|
|||
|
w_time_ph_c = w_time_ph_a - w_y / 131072;
|
|||
|
//pSetADCSamplingPoint = pHandle->pFctSetADCSampPointSect2;
|
|||
|
} else if (w_x <= 0) { /* w_z >= 0 */
|
|||
|
sector = SECTOR_4;
|
|||
|
w_time_ph_a = ( int32_t )( PWM_PERIOD_CYCLES ) / 4 + ( ( w_x - w_z ) / ( int32_t )262144 );
|
|||
|
w_time_ph_b = w_time_ph_a + w_z / 131072;
|
|||
|
w_time_ph_c = w_time_ph_b - w_x / 131072;
|
|||
|
//pSetADCSamplingPoint = pHandle->pFctSetADCSampPointSect4;
|
|||
|
} else { // w_x > 0
|
|||
|
sector = SECTOR_3;
|
|||
|
w_time_ph_a = ( int32_t )( PWM_PERIOD_CYCLES ) / 4 + ( ( w_y - w_x ) / ( int32_t )262144 );
|
|||
|
w_time_ph_c = w_time_ph_a - w_y / 131072;
|
|||
|
w_time_ph_b = w_time_ph_c + w_x / 131072;
|
|||
|
//pSetADCSamplingPoint = pHandle->pFctSetADCSampPointSect3;
|
|||
|
}
|
|||
|
} else { // w_y > 0
|
|||
|
if ( w_z >= 0 )
|
|||
|
{
|
|||
|
sector = SECTOR_5;
|
|||
|
w_time_ph_a = ( int32_t )( PWM_PERIOD_CYCLES ) / 4 + ( ( w_y - w_z ) / ( int32_t )262144 );
|
|||
|
w_time_ph_b = w_time_ph_a + w_z / 131072;
|
|||
|
w_time_ph_c = w_time_ph_a - w_y / 131072;
|
|||
|
//pSetADCSamplingPoint = pHandle->pFctSetADCSampPointSect5;
|
|||
|
}
|
|||
|
else /* w_z < 0 */
|
|||
|
if ( w_x <= 0 )
|
|||
|
{
|
|||
|
sector = SECTOR_6;
|
|||
|
w_time_ph_a = ( int32_t )( PWM_PERIOD_CYCLES ) / 4 + ( ( w_y - w_x ) / ( int32_t )262144 );
|
|||
|
w_time_ph_c = w_time_ph_a - w_y / 131072;
|
|||
|
w_time_ph_b = w_time_ph_c + w_x / 131072;
|
|||
|
//pSetADCSamplingPoint = pHandle->pFctSetADCSampPointSect6;
|
|||
|
}
|
|||
|
else /* w_x > 0 */
|
|||
|
{
|
|||
|
sector = SECTOR_1;
|
|||
|
w_time_ph_a = ( int32_t )( PWM_PERIOD_CYCLES ) / 4 + ( ( w_x - w_z ) / ( int32_t )262144 );
|
|||
|
w_time_ph_b = w_time_ph_a + w_z / 131072;
|
|||
|
w_time_ph_c = w_time_ph_b - w_x / 131072;
|
|||
|
//pSetADCSamplingPoint = pHandle->pFctSetADCSampPointSect1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
MOTOR_TIM->CCR1 = ( uint16_t )w_time_ph_a;
|
|||
|
MOTOR_TIM->CCR2 = ( uint16_t )w_time_ph_b;
|
|||
|
MOTOR_TIM->CCR3 = ( uint16_t )w_time_ph_c;
|
|||
|
//myprintf("%d %d %d\n\r",MOTOR_TIM->CCR1,MOTOR_TIM->CCR2,MOTOR_TIM->CCR3);
|
|||
|
}
|
|||
|
|
|||
|
qd_t v_qd_set;
|
|||
|
|
|||
|
void foc_v_qd_set(qd_t set)
|
|||
|
{
|
|||
|
v_qd_set.q = set.q;
|
|||
|
v_qd_set.d = set.d;
|
|||
|
}
|
|||
|
|
|||
|
static int16_t encoder_elec_test = ANGLE_0;
|
|||
|
|
|||
|
mc_flag_t mc_flag = {
|
|||
|
.ctrl_loop_mode = MC_OPEN_MODE,
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 此函数每次定时器1中断执行一次,主要根据v_qd_set计算v_alpha_beta
|
|||
|
*/
|
|||
|
void foc_update(void)
|
|||
|
{
|
|||
|
qd_t v_qd;
|
|||
|
alphabeta_t v_alpha_beta;
|
|||
|
|
|||
|
int16_t Eangle;
|
|||
|
// 读取电角度
|
|||
|
Eangle = Get_Electrical_Angle();
|
|||
|
if (mc_flag.ctrl_loop_mode == MC_OPEN_MODE) {
|
|||
|
/*
|
|||
|
当电机处于开环模式,直接设置vq=3000,vd=0。让电机缓慢转动,
|
|||
|
此模式可用于测量电机本体或者驱动芯片是否正常
|
|||
|
*/
|
|||
|
encoder_elec_test += 300;
|
|||
|
qd_t volt;
|
|||
|
volt.q = 7000;
|
|||
|
volt.d = 0;
|
|||
|
|
|||
|
v_qd = circle_limitation(volt); // 空间电压矢量限幅,防止超过六边形内接圆
|
|||
|
v_alpha_beta = mc_rev_park(v_qd, encoder_elec_test);
|
|||
|
//myprintf("o:%d\n\r",encoder_elec_test);
|
|||
|
} else if (mc_flag.ctrl_loop_mode == MC_ELEC_CALIB_MODE) { // 电角度校准
|
|||
|
/*
|
|||
|
当电机处于电角度校准模式,将电角度固定为-90度。电角度校准详情请参考文档
|
|||
|
*/
|
|||
|
|
|||
|
v_qd = circle_limitation(v_qd_set);
|
|||
|
v_alpha_beta = mc_rev_park(v_qd, -ANGLE_90);
|
|||
|
|
|||
|
} else {
|
|||
|
// 当电机处于速度闭环模式,位置闭环模式,或者测试模式进入此分支
|
|||
|
|
|||
|
if (mc_flag.ctrl_loop_mode == MC_TEST_MODE) {
|
|||
|
/*
|
|||
|
当电机处于测试模式,由CMDLINE设置目标速度
|
|||
|
*/
|
|||
|
}
|
|||
|
|
|||
|
// 对设置的v_qd进行限幅,得到可正常输出的v_qd
|
|||
|
v_qd = circle_limitation(v_qd_set);
|
|||
|
|
|||
|
// 反park变换,得到v_alpha_beta
|
|||
|
v_alpha_beta = mc_rev_park(v_qd, Eangle);
|
|||
|
}
|
|||
|
|
|||
|
// 根据v_alpha_beta输出svpwm波,驱动电机运动
|
|||
|
svpwm_calc(v_alpha_beta);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|