|
@@ -10,8 +10,8 @@
|
|
|
#include "circle_limitation.h"
|
|
#include "circle_limitation.h"
|
|
|
#include "svpwm.h"
|
|
#include "svpwm.h"
|
|
|
|
|
|
|
|
-motor_foc_t mFOC = {
|
|
|
|
|
- .motor_p = {
|
|
|
|
|
|
|
+motor_foc_t g_foc = {
|
|
|
|
|
+ .motor_param = {
|
|
|
.poles = 2,
|
|
.poles = 2,
|
|
|
.ld = 0.578477f,
|
|
.ld = 0.578477f,
|
|
|
.lq = 5.78477f,
|
|
.lq = 5.78477f,
|
|
@@ -19,19 +19,19 @@ motor_foc_t mFOC = {
|
|
|
.inertia = 3.319367f,
|
|
.inertia = 3.319367f,
|
|
|
.b_emf = 4.332566f,
|
|
.b_emf = 4.332566f,
|
|
|
},
|
|
},
|
|
|
- .PI_id = {
|
|
|
|
|
|
|
+ .id_controller = {
|
|
|
.Kp_gain = 9,
|
|
.Kp_gain = 9,
|
|
|
.Ki_gain = 1071,
|
|
.Ki_gain = 1071,
|
|
|
.max_output = MAX_VBUS_VOLTAGE,
|
|
.max_output = MAX_VBUS_VOLTAGE,
|
|
|
.min_output = -MAX_VBUS_VOLTAGE,
|
|
.min_output = -MAX_VBUS_VOLTAGE,
|
|
|
},
|
|
},
|
|
|
- .PI_iq = {
|
|
|
|
|
|
|
+ .iq_controller = {
|
|
|
.Kp_gain = 10,
|
|
.Kp_gain = 10,
|
|
|
.Ki_gain = 1080,
|
|
.Ki_gain = 1080,
|
|
|
.max_output = MAX_VBUS_VOLTAGE,
|
|
.max_output = MAX_VBUS_VOLTAGE,
|
|
|
.min_output = -MAX_VBUS_VOLTAGE,
|
|
.min_output = -MAX_VBUS_VOLTAGE,
|
|
|
},
|
|
},
|
|
|
- .PI_speed = {
|
|
|
|
|
|
|
+ .speed_controller = {
|
|
|
.Kp_gain = 1,
|
|
.Kp_gain = 1,
|
|
|
.Ki_gain = 200,
|
|
.Ki_gain = 200,
|
|
|
.max_output = MAX_CURRENT,
|
|
.max_output = MAX_CURRENT,
|
|
@@ -40,14 +40,8 @@ motor_foc_t mFOC = {
|
|
|
};
|
|
};
|
|
|
#if 1
|
|
#if 1
|
|
|
static void __inline foc_update_theta(motor_foc_t *foc) {
|
|
static void __inline foc_update_theta(motor_foc_t *foc) {
|
|
|
- float angle = 0.0f;
|
|
|
|
|
- if (foc->override.is_theta) {
|
|
|
|
|
- angle = foc->override.theta;
|
|
|
|
|
- }else {
|
|
|
|
|
- angle = hall_sensor_get_theta();
|
|
|
|
|
- }
|
|
|
|
|
- foc->motor_s.angle = angle;
|
|
|
|
|
- foc->motor_s.theta = degree_2_pi(foc->motor_s.angle);
|
|
|
|
|
|
|
+ foc->motor_stat.angle = hall_sensor_get_theta();
|
|
|
|
|
+ foc->motor_stat.theta = degree_2_pi(foc->motor_stat.angle);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
#else
|
|
@@ -70,17 +64,13 @@ static void __inline foc_update_theta(motor_foc_t *foc) {
|
|
|
static void __inline Foc_Calc_Voltage(motor_foc_t *foc, dq_t *sampled, dq_t *ref_out) {
|
|
static void __inline Foc_Calc_Voltage(motor_foc_t *foc, dq_t *sampled, dq_t *ref_out) {
|
|
|
//float vd = pi_control(&foc->PI_id, foc->dq_ref.Id - sampled->Id);
|
|
//float vd = pi_control(&foc->PI_id, foc->dq_ref.Id - sampled->Id);
|
|
|
//float vq = pi_control(&foc->PI_iq, foc->dq_ref.Iq - sampled->Iq);
|
|
//float vq = pi_control(&foc->PI_iq, foc->dq_ref.Iq - sampled->Iq);
|
|
|
- if (foc->mode == FOC_MODE_PI_CURRENT || foc->mode == FOC_MODE_PI_FULL) {
|
|
|
|
|
- ref_out->Vd = pi_control(&foc->PI_id, foc->dq_ref.Id - sampled->Id);
|
|
|
|
|
- ref_out->Vq = pi_control(&foc->PI_iq, foc->dq_ref.Iq - sampled->Iq);
|
|
|
|
|
|
|
+ if (foc->mode == FOC_MODE_CURRENT_LOOP || foc->mode == FOC_MODE_CLOSE_LOOP) {
|
|
|
|
|
+ ref_out->Vd = pi_control(&foc->id_controller, foc->dq_command.Id - sampled->Id);
|
|
|
|
|
+ ref_out->Vq = pi_control(&foc->iq_controller, foc->dq_command.Iq - sampled->Iq);
|
|
|
//printf("vd = %f, vq = %f\n", vd, vq);
|
|
//printf("vd = %f, vq = %f\n", vd, vq);
|
|
|
}else {
|
|
}else {
|
|
|
- ref_out->Vd = foc->dq_ref.Vd;
|
|
|
|
|
- ref_out->Vq = foc->dq_ref.Vq;
|
|
|
|
|
- }
|
|
|
|
|
- if (foc->override.is_vdq) {
|
|
|
|
|
- ref_out->Vd = foc->override.vdq.Vd;
|
|
|
|
|
- ref_out->Vq = foc->override.vdq.Vq;
|
|
|
|
|
|
|
+ ref_out->Vd = foc->dq_command.Vd;
|
|
|
|
|
+ ref_out->Vq = foc->dq_command.Vq;
|
|
|
}
|
|
}
|
|
|
foc->dq_v.Vd = ref_out->Vd;
|
|
foc->dq_v.Vd = ref_out->Vd;
|
|
|
foc->dq_v.Vq = ref_out->Vq;
|
|
foc->dq_v.Vq = ref_out->Vq;
|
|
@@ -160,13 +150,13 @@ void FOC_Fast_Task(motor_foc_t *foc){
|
|
|
/* ABC三相坐标到alpha-beta坐标 */
|
|
/* ABC三相坐标到alpha-beta坐标 */
|
|
|
Clark(c_sample->Ia, c_sample->Ib, c_sample->Ic, &sample_ab);
|
|
Clark(c_sample->Ia, c_sample->Ib, c_sample->Ic, &sample_ab);
|
|
|
/* alpha-beta坐标系到D-Q旋转坐标系 */
|
|
/* alpha-beta坐标系到D-Q旋转坐标系 */
|
|
|
- Park(&sample_ab, foc->motor_s.theta, &sample_dq);
|
|
|
|
|
|
|
+ Park(&sample_ab, foc->motor_stat.theta, &sample_dq);
|
|
|
/* 电流环,输出电压给SVPWM */
|
|
/* 电流环,输出电压给SVPWM */
|
|
|
Foc_Calc_Voltage(foc, &sample_dq, &v_dq);
|
|
Foc_Calc_Voltage(foc, &sample_dq, &v_dq);
|
|
|
/* 确保电压在6个扇区的内切圆中 */
|
|
/* 确保电压在6个扇区的内切圆中 */
|
|
|
CirCle_Limitation_Process(&v_dq, foc->vbus, 0.95f);
|
|
CirCle_Limitation_Process(&v_dq, foc->vbus, 0.95f);
|
|
|
/* d-q坐标系到alpha-beta坐标系,输出给svpwm */
|
|
/* d-q坐标系到alpha-beta坐标系,输出给svpwm */
|
|
|
- Rev_Park(&v_dq, foc->motor_s.theta, &pwm_ab);
|
|
|
|
|
|
|
+ Rev_Park(&v_dq, foc->motor_stat.theta, &pwm_ab);
|
|
|
/* SVPWM,获取三相逆变器的开关时间,用的是pwm1模式,如果是pwm2模式,这个函数需要修改 */
|
|
/* SVPWM,获取三相逆变器的开关时间,用的是pwm1模式,如果是pwm2模式,这个函数需要修改 */
|
|
|
SVM_Get_Phase_Time(&pwm_ab, foc->vbus, FOC_PWM_Half_Period, &phase_time, &foc->sector);
|
|
SVM_Get_Phase_Time(&pwm_ab, foc->vbus, FOC_PWM_Half_Period, &phase_time, &foc->sector);
|
|
|
/* 计算三相电流的采样点 */
|
|
/* 计算三相电流的采样点 */
|
|
@@ -186,29 +176,29 @@ void Foc_Calc_Current_Ref(motor_foc_t *foc) {
|
|
|
static int count = 0;
|
|
static int count = 0;
|
|
|
float speed_ref = ramp_get_target(&foc->speed_ramp);
|
|
float speed_ref = ramp_get_target(&foc->speed_ramp);
|
|
|
float speed_feedback = foc_get_speed();
|
|
float speed_feedback = foc_get_speed();
|
|
|
- float vq_out = pi_control(&foc->PI_speed, speed_ref - speed_feedback);
|
|
|
|
|
- if (foc->mode == FOC_MODE_PI_SPEED || foc->mode == FOC_MODE_PI_FULL){
|
|
|
|
|
- foc->dq_ref.Iq = vq_out;
|
|
|
|
|
- foc->dq_ref.Id = 0.0f; //if MTPA used, d is not 0
|
|
|
|
|
|
|
+ float vq_out = pi_control(&foc->speed_controller, speed_ref - speed_feedback);
|
|
|
|
|
+ if (foc->mode == FOC_MODE_SPEED_LOOP || foc->mode == FOC_MODE_CLOSE_LOOP){
|
|
|
|
|
+ foc->dq_command.Iq = vq_out;
|
|
|
|
|
+ foc->dq_command.Id = 0.0f; //if MTPA used, d is not 0
|
|
|
if (((count) % 10) == 0) {
|
|
if (((count) % 10) == 0) {
|
|
|
printf("vq_out = %f, %f, %f\n", vq_out, speed_ref, speed_feedback);
|
|
printf("vq_out = %f, %f, %f\n", vq_out, speed_ref, speed_feedback);
|
|
|
}
|
|
}
|
|
|
count++;
|
|
count++;
|
|
|
|
|
|
|
|
}else {
|
|
}else {
|
|
|
- foc->dq_ref.Iq = ramp_get_target(&foc->current_ramp);
|
|
|
|
|
- foc->dq_ref.Id = 0.0f; //if MTPA used, d is not 0
|
|
|
|
|
|
|
+ foc->dq_command.Iq = ramp_get_target(&foc->current_ramp);
|
|
|
|
|
+ foc->dq_command.Id = 0.0f; //if MTPA used, d is not 0
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Foc_Speed_Ramp(motor_foc_t *foc){
|
|
void Foc_Speed_Ramp(motor_foc_t *foc){
|
|
|
- if (foc->rpm_ref >= 0 && foc->mode != FOC_MODE_OPEN_LOOP){
|
|
|
|
|
|
|
+ if (foc->speed_command >= 0 && foc->mode != FOC_MODE_OPEN_LOOP){
|
|
|
u16 current_rpm = foc_get_speed();
|
|
u16 current_rpm = foc_get_speed();
|
|
|
- u16 ref_rpm = foc->rpm_ref;
|
|
|
|
|
- foc->rpm_ref = -1;
|
|
|
|
|
|
|
+ u16 ref_rpm = foc->speed_command;
|
|
|
|
|
+ foc->speed_command = -1;
|
|
|
|
|
|
|
|
if (ref_rpm + RPM_FOR_CLOSE_LOOP < current_rpm){
|
|
if (ref_rpm + RPM_FOR_CLOSE_LOOP < current_rpm){
|
|
|
- ramp_set_target(&foc->voltage_ramp, foc->dq_ref.Vq, speed_to_voltage(ref_rpm), SPEED_RAMP_DURATION);
|
|
|
|
|
|
|
+ ramp_set_target(&foc->voltage_ramp, foc->dq_command.Vq, speed_to_voltage(ref_rpm), SPEED_RAMP_DURATION);
|
|
|
ramp_exc(&foc->current_ramp);
|
|
ramp_exc(&foc->current_ramp);
|
|
|
foc->mode = FOC_MODE_OPEN_LOOP;
|
|
foc->mode = FOC_MODE_OPEN_LOOP;
|
|
|
}
|
|
}
|
|
@@ -216,11 +206,11 @@ void Foc_Speed_Ramp(motor_foc_t *foc){
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void foc_brake_handler(void) {
|
|
void foc_brake_handler(void) {
|
|
|
- mFOC.foc_fault = foc_brake_error;
|
|
|
|
|
|
|
+ g_foc.foc_fault = foc_brake_error;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void foc_pwm_up_handler(void){
|
|
void foc_pwm_up_handler(void){
|
|
|
- phase_current_adc_triger(&mFOC.current_samp);
|
|
|
|
|
|
|
+ phase_current_adc_triger(&g_foc.current_samp);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#if defined (CCMRAM)
|
|
#if defined (CCMRAM)
|
|
@@ -232,19 +222,19 @@ __attribute__( ( section ( ".ccmram" ) ) )
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
void current_sample_handler(void) {
|
|
void current_sample_handler(void) {
|
|
|
- if (mFOC.current_samp.is_calibrating) {
|
|
|
|
|
- phase_current_offset(&mFOC.current_samp);
|
|
|
|
|
|
|
+ if (g_foc.current_samp.is_calibrating) {
|
|
|
|
|
+ phase_current_offset(&g_foc.current_samp);
|
|
|
}else {
|
|
}else {
|
|
|
- FOC_Fast_Task(&mFOC);
|
|
|
|
|
|
|
+ FOC_Fast_Task(&g_foc);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void foc_slow_task_handler(void) {
|
|
void foc_slow_task_handler(void) {
|
|
|
- FOC_Normal_Task(&mFOC);
|
|
|
|
|
|
|
+ FOC_Normal_Task(&g_foc);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void foc_pwm_start(bool start) {
|
|
void foc_pwm_start(bool start) {
|
|
|
- if (start == mFOC.mosGate) {
|
|
|
|
|
|
|
+ if (start == g_foc.mosfec_gate) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
if (start) {
|
|
if (start) {
|
|
@@ -252,6 +242,6 @@ void foc_pwm_start(bool start) {
|
|
|
}else {
|
|
}else {
|
|
|
PWM_Stop();
|
|
PWM_Stop();
|
|
|
}
|
|
}
|
|
|
- mFOC.mosGate = start;
|
|
|
|
|
|
|
+ g_foc.mosfec_gate = start;
|
|
|
}
|
|
}
|
|
|
|
|
|