完成速度、电流闭环

This commit is contained in:
2024-05-17 00:43:58 +08:00
parent d531b7cc09
commit f404369a32
11 changed files with 507 additions and 174 deletions

View File

@@ -5,25 +5,238 @@
#include <stdbool.h>
#include "Controller.h"
#include "SVPWM/SVPWM.h"
#include "Communication.h"
#include "Angle.h"
#define UTILS_LP_FAST(value, sample, filter_constant) (value -= (filter_constant) * ((value) - (sample)))
tFOC FOC;
float uAlpha1;
float uBeta1;
bool Generate(float ud, float uq, float Theta) {
#define PWM_FREQUENCY 24000
#define CURRENT_MEASURE_HZ PWM_FREQUENCY
#define CURRENT_MEASURE_PERIOD (float) (1.0f / (float) CURRENT_MEASURE_HZ)
inversePark(ud, uq, Theta, &uAlpha1, &uBeta1);
#define TIMER0_CLK_MHz 168
#define PWM_PERIOD_CYCLES (uint16_t)((TIMER0_CLK_MHz * (uint32_t) 1000000u / ((uint32_t) (PWM_FREQUENCY))) & 0xFFFE)
#define HALF_PWM_PERIOD_CYCLES (uint16_t)(PWM_PERIOD_CYCLES / 2U)
float current1, current2, current3;
if (0 == SVPWM(uAlpha1, uBeta1, &FOC.dtc_a, &FOC.dtc_b, &FOC.dtc_c)) {
// set_a_duty((uint16_t)(Foc.dtc_a * (float) HALF_PWM_PERIOD_CYCLES));
// set_b_duty((uint16_t)(Foc.dtc_b * (float) HALF_PWM_PERIOD_CYCLES));
// set_c_duty((uint16_t)(Foc.dtc_c * (float) HALF_PWM_PERIOD_CYCLES));
// TIM1->CCR1 = (uint16_t) FOC.dtc_a;
// TIM1->CCR2 = (uint16_t) FOC.dtc_b;
// TIM1->CCR3 = (uint16_t) FOC.dtc_c;
}
float32_t id_curr_pi_kp = 0.001f;
float32_t id_curr_pi_ki = 0.000001f;
return FOC.dtc_a;
float32_t id_curr_pi_target = 0.0f;
float32_t id_curr_pi_value;
float32_t id_curr_pi_error;
float32_t id_curr_pi_errMin = 0.0f;
float32_t id_curr_pi_errSum;
float32_t id_curr_pi_errSumMax = 5.0f;
float32_t id_curr_pi_result;
float32_t iq_curr_pi_kp = 0.001f;
float32_t iq_curr_pi_ki = 0.000001f;
float32_t iq_curr_pi_target = 1.0f;
float32_t iq_curr_pi_value;
float32_t iq_curr_pi_error;
float32_t iq_curr_pi_errMin = 0.0f;
float32_t iq_curr_pi_errSum;
float32_t iq_curr_pi_errSumMax = 5.0f;
float32_t iq_curr_pi_result;
float32_t Speed_target = 0.0f;
float32_t Speedpid_error;
float32_t Speedpid_errSum;
float32_t Speedpid_kp = 1.0f;
float32_t Speedpid_ki = 0.1f;
float32_t Speedpid_kd = 1.0f;
float32_t Speedpid_errSumMax = 5.0f;
float32_t Speedpid_lastErr;
float32_t Speedpid_errDt;
float32_t Speedpid_result;
float32_t u_d, u_q;
static void Current_PI_Cal_Id(float32_t resultMax) {
//curr_pi_target = target;
id_curr_pi_error = id_curr_pi_target - id_curr_pi_value;
// if(curr_pi_error > PI_Control->errMin || curr_pi_error < -PI_Control->errMin)
id_curr_pi_errSum += id_curr_pi_error * id_curr_pi_ki;
if (id_curr_pi_errSum > id_curr_pi_errSumMax)
id_curr_pi_errSum = id_curr_pi_errSumMax;
else if (id_curr_pi_errSum < -id_curr_pi_errSumMax)
id_curr_pi_errSum = -id_curr_pi_errSumMax;
id_curr_pi_result = id_curr_pi_kp * id_curr_pi_error + id_curr_pi_errSum;
if (id_curr_pi_result > resultMax)
id_curr_pi_result = resultMax;
else if (id_curr_pi_result < -resultMax)
id_curr_pi_result = -resultMax;
}
static void Current_PI_Cal_Iq(float32_t resultMax) {
//curr_pi_target = target;
iq_curr_pi_error = iq_curr_pi_target - iq_curr_pi_value;
// if(curr_pi_error > PI_Control->errMin || curr_pi_error < -PI_Control->errMin)
iq_curr_pi_errSum += iq_curr_pi_error * iq_curr_pi_ki;
if (iq_curr_pi_errSum > iq_curr_pi_errSumMax)
iq_curr_pi_errSum = iq_curr_pi_errSumMax;
else if (iq_curr_pi_errSum < -iq_curr_pi_errSumMax)
iq_curr_pi_errSum = -iq_curr_pi_errSumMax;
iq_curr_pi_result = iq_curr_pi_kp * iq_curr_pi_error + iq_curr_pi_errSum;
if (iq_curr_pi_result > resultMax)
iq_curr_pi_result = resultMax;
else if (iq_curr_pi_result < -resultMax)
iq_curr_pi_result = -resultMax;
}
static float32_t PIDGetResult(float32_t Speedpid_value, float32_t valMax, float32_t errMin) {
Speedpid_error = Speed_target - Speedpid_value;
if (Speedpid_error > errMin || Speedpid_error < -errMin)
Speedpid_errSum += Speedpid_error * Speedpid_ki;
if (Speedpid_errSum > Speedpid_errSumMax)
Speedpid_errSum = Speedpid_errSumMax;
else if (Speedpid_errSum < -Speedpid_errSumMax)
Speedpid_errSum = -Speedpid_errSumMax;
Speedpid_errDt = Speedpid_error - Speedpid_lastErr;
Speedpid_lastErr = Speedpid_error;
Speedpid_result = Speedpid_kp * Speedpid_error + Speedpid_errSum + Speedpid_kd * Speedpid_errDt;
if (Speedpid_result > valMax)
Speedpid_result = valMax;
else if (Speedpid_result < -valMax)
Speedpid_result = -valMax;
return Speedpid_result;
}
void SpeedControl(float32_t target,float32_t angleVal) {
Speed_target = target;
float32_t motorControl_speedValue = GetSpeed(angleVal);
SendCurrent_Vofa(motorControl_speedValue, target, 0);
// speedPID_value = motorControl_speedValue;
iq_curr_pi_target = PIDGetResult(motorControl_speedValue, angleVal, 0.0f);
}
//bool Generate_SVM(float ud, float uq, float Theta) {
bool FOC_current(float Id_set, float Iq_set, float Theta, float bw) {
if (id_curr_pi_target>Id_set){id_curr_pi_target=Id_set;}
if (iq_curr_pi_target>Iq_set){iq_curr_pi_target=Iq_set;}
// id_curr_pi_target = Id_set;
// iq_curr_pi_target = Iq_set;
current1 = ADC1->JDR2;
current2 = ADC2->JDR1;
current3 = ADC1->JDR1;
current1 = (current1 - 2048) * ((3.3f / 4095.0f) / 0.005f / 7.333333f) + 0.23;
current2 = (current2 - 2048) * ((3.3f / 4095.0f) / 0.005f / 7.333333f);
current3 = (current3 - 2048) * ((3.3f / 4095.0f) / 0.005f / 7.333333f) - 0.4;
// SendCurrent_Vofa(current1, current2, current3);
// Clarke transform
float i_alpha, i_beta;
clarke_transform(current1, current2, current3, &i_alpha, &i_beta);
// Park transform
float i_d, i_q;
park_transform(i_alpha, i_beta, Theta, &i_d, &i_q);
id_curr_pi_value = i_d;
iq_curr_pi_value = i_q;
Current_PI_Cal_Id(1.0f);
Current_PI_Cal_Iq(1.0f);
u_d = id_curr_pi_result;
u_q = iq_curr_pi_result;
// float mod_to_V = FOC.v_bus_filt * 2.0f / 3.0f;
// float V_to_mod = 1.0f / mod_to_V;
float mod_to_V = 1.2f * 2.0f / 3.0f;
float V_to_mod = 1.0f / mod_to_V;
float bandwidth = MIN(bw, 0.25f * PWM_FREQUENCY);
// Apply PI control
float Ierr_d = Id_set - i_d;
float Ierr_q = Iq_set - i_q;
// FOC.current_ctrl_p_gain = 5.0f * bandwidth;
// FOC.current_ctrl_i_gain = 0.000002f * bandwidth;
FOC.current_ctrl_p_gain = 0.001f;
FOC.current_ctrl_i_gain = 0.00001f;
FOC.current_ctrl_integral_d = 0;
FOC.current_ctrl_integral_q = 0;
float mod_d = V_to_mod * (FOC.current_ctrl_integral_d + Ierr_d * FOC.current_ctrl_p_gain);
float mod_q = V_to_mod * (FOC.current_ctrl_integral_q + Ierr_q * FOC.current_ctrl_p_gain);
// Vector modulation saturation, lock integrator if saturated
float mod_scalefactor = 0.9f * SQRT3_BY_2 / sqrtf(SQ(mod_d) + SQ(mod_q));
if (mod_scalefactor < 1.0f) {
mod_d *= mod_scalefactor;
mod_q *= mod_scalefactor;
FOC.current_ctrl_integral_d *= 0.99f;
FOC.current_ctrl_integral_q *= 0.99f;
} else {
FOC.current_ctrl_integral_d += Ierr_d * (FOC.current_ctrl_i_gain * CURRENT_MEASURE_PERIOD);
FOC.current_ctrl_integral_q += Ierr_q * (FOC.current_ctrl_i_gain * CURRENT_MEASURE_PERIOD);
}
float pwm_phase = Theta + Theta * M_2PI * 20 * CURRENT_MEASURE_PERIOD;
inversePark(u_d, u_q, Theta, &uAlpha1, &uBeta1);
FOC.i_q = i_q;
UTILS_LP_FAST(FOC.i_q_filt, FOC.i_q, 0.01f);
FOC.i_d = i_d;
UTILS_LP_FAST(FOC.i_d_filt, FOC.i_d, 0.01f);
FOC.i_bus = (mod_d * i_d + mod_q * i_q);
UTILS_LP_FAST(FOC.i_bus_filt, FOC.i_bus, 0.01f);
FOC.power_filt = FOC.v_bus_filt * FOC.i_bus_filt;
SVPWM(uAlpha1, uBeta1, &FOC.dtc_a, &FOC.dtc_b, &FOC.dtc_c);
// FOC.dtc_a = FOC.dtc_a * 0.01;
// FOC.dtc_b = FOC.dtc_b * 0.01;
// FOC.dtc_c = FOC.dtc_c * 0.01;
// SendCurrent_Vofa(mod_d, mod_q, current1);
TIM1->CCR1 = (uint16_t) (FOC.dtc_c * (float) HALF_PWM_PERIOD_CYCLES);
TIM1->CCR2 = (uint16_t) (FOC.dtc_b * (float) HALF_PWM_PERIOD_CYCLES);
TIM1->CCR3 = (uint16_t) (FOC.dtc_a * (float) HALF_PWM_PERIOD_CYCLES);
// TIM1->CCR1 = (uint16_t) FOC.dtc_a;
// TIM1->CCR2 = (uint16_t) FOC.dtc_b;
// TIM1->CCR3 = (uint16_t) FOC.dtc_c;
return 0;
}

View File

@@ -5,6 +5,8 @@
#ifndef BOOOOMFOC_STSPIN32G4_EVB_CONTROLLER_H
#define BOOOOMFOC_STSPIN32G4_EVB_CONTROLLER_H
#include "arm_math.h"
typedef struct sFOC
{
bool is_armed;
@@ -20,7 +22,9 @@ typedef struct sFOC
extern tFOC FOC;
extern bool Generate(float ud, float uq, float Theta);
extern void SpeedControl(float32_t target,float32_t angleVal);
extern bool FOC_current(float Id_set, float Iq_set, float Theta, float bw);
#endif //BOOOOMFOC_STSPIN32G4_EVB_CONTROLLER_H

View File

@@ -5,11 +5,10 @@
#include "PreDrive.h"
uint8_t PreDrive_Init_Buffur[2] = {0x00, 0x00};
bool PreDrive_Init(void){
bool PreDrive_Init(void) {
while (HAL_I2C_Mem_Write(&hi2c3, 0x8e, 0x0c, I2C_MEMADD_SIZE_8BIT, PreDrive_Init_Buffur, 1, 1000) != HAL_OK) {}
PreDrive_Init_Buffur[0] = 0x00;
while (HAL_I2C_Mem_Write(&hi2c3, 0x8e, 0x0c, I2C_MEMADD_SIZE_8BIT, PreDrive_Init_Buffur, 1, 1000) != HAL_OK) {}

View File

@@ -12,144 +12,38 @@ extern uint16_t cycleNum;
#define SQRT3 1.732050808f
#define LIMIT (float32_t)(0.9f / SQRT3)
#define LIMIT_UDC 16.0f
#define TS 3400
#define TS 3300
#define SQRT3_MULT_TS (float32_t)((float32_t)TS * SQRT3)
uint8_t sectionMap[7] = {0, 2, 6, 1, 4, 3, 5};
float32_t uAlpha, uBeta;
float32_t ud, uq;
uint16_t channel1, channel2, channel3,udc=12;
float channel1, channel2, channel3, udc = 12;
float uAlpha, uBeta;
float32_t iAlpha, iBeta;
float32_t id, iq;
inline void clarke_transform(float Ia, float Ib, float Ic, float *Ialpha, float *Ibeta) {
*Ialpha = Ia;
*Ibeta = (Ib - Ic) * ONE_BY_SQRT3;
}
inline void park_transform(float Ialpha, float Ibeta, float Theta, float *Id, float *Iq) {
float s = sinf(Theta / 57.29577951326093f);
float c = cosf(Theta / 57.29577951326093f);
*Id = Ialpha * c + Ibeta * s;
*Iq = -Ialpha * s + Ibeta * c;
}
inline void inversePark(float ud, float uq, float Theta, float *uAlpha, float *uBeta) {
float s = sinf(Theta / 57.2958f);
float c = cosf(Theta / 57.2958f);
float s = sinf(Theta / 57.29577951326093f);
float c = cosf(Theta / 57.29577951326093f);
*uAlpha = ud * c - uq * s;
*uBeta = ud * s + uq * c;
}
#ifdef false
inline int SVPWM(float uAlpha, float uBeta, float *tA, float *tB, float *tC) {
float U1, U2, U3;
uint8_t a, b, c, n = 0;
U1 = uBeta;
U2 = (SQRT3 * uAlpha - uBeta) / 2;
U3 = (-SQRT3 * uAlpha - uBeta) / 2;
if (U1 > 0)
a = 1;
else
a = 0;
if (U2 > 0)
b = 1;
else
b = 0;
if (U3 > 0)
c = 1;
else
c = 0;
n = (c << 2) + (b << 1) + a;
switch (sectionMap[n])
{
case 0:
{
channel1 = TS / 2;
channel2 = TS / 2;
channel3 = TS / 2;
}
break;
case 1:
{
int16_t t4 = SQRT3 * TS * U2 / udc;
int16_t t6 = SQRT3 * TS * U1 / udc;
int16_t t0 = (TS - t4 - t6) / 2;
channel1 = t4 + t6 + t0;
channel2 = t6 + t0;
channel3 = t0;
}
break;
case 2:
{
int16_t t2 = -SQRT3 * TS * U2 / udc;
int16_t t6 = -SQRT3 * TS * U3 / udc;
int16_t t0 = (TS - t2 - t6) / 2;
channel1 = t6 + t0;
channel2 = t2 + t6 + t0;
channel3 = t0;
}
break;
case 3:
{
int16_t t2 = SQRT3 * TS * U1 / udc;
int16_t t3 = SQRT3 * TS * U3 / udc;
int16_t t0 = (TS - t2 - t3) / 2;
channel1 = t0;
channel2 = t2 + t3 + t0;
channel3 = t3 + t0;
}
break;
case 4:
{
int16_t t1 = -SQRT3 * TS * U1 / udc;
int16_t t3 = -SQRT3 * TS * U2 / udc;
int16_t t0 = (TS - t1 - t3) / 2;
channel1 = t0;
channel2 = t3 + t0;
channel3 = t1 + t3 + t0;
}
break;
case 5:
{
int16_t t1 = SQRT3 * TS * U3 / udc;
int16_t t5 = SQRT3 * TS * U2 / udc;
int16_t t0 = (TS - t1 - t5) / 2;
channel1 = t5 + t0;
channel2 = t0;
channel3 = t1 + t5 + t0;
}
break;
case 6:
{
int16_t t4 = -SQRT3 * TS * U3 / udc;
int16_t t5 = -SQRT3 * TS * U1 / udc;
int16_t t0 = (TS - t4 - t5) / 2;
channel1 = t4 + t5 + t0;
channel2 = t0;
channel3 = t5 + t0;
}
break;
default:
break;
}
*tA = channel1;
*tB = channel2;
*tC = channel3;
return 0;
}
#else
inline int SVPWM(float uAlpha, float uBeta, float *tA, float *tB, float *tC) {
int Sextant;
@@ -274,5 +168,3 @@ inline int SVPWM(float uAlpha, float uBeta, float *tA, float *tB, float *tC) {
// TIM1->CCR2 = channelB;
// TIM1->CCR3 = channelC;
}
#endif

View File

@@ -7,7 +7,7 @@
#include "arm_math.h"
#define M_PI (3.14159265358f)
//#define M_PI (3.14159265358f)
#define M_2PI (6.28318530716f)
#define ONE_BY_SQRT3 (0.57735026919f)
#define TWO_BY_SQRT3 (2.0f * 0.57735026919f)
@@ -24,6 +24,10 @@
//
//extern inline void park_transform(float Ialpha, float Ibeta, float Theta, float *Id, float *Iq);
extern void clarke_transform(float Ia, float Ib, float Ic, float *Ialpha, float *Ibeta);
extern void park_transform(float Ialpha, float Ibeta, float Theta, float *Id, float *Iq);
extern void inversePark(float ud, float uq, float Theta, float *uAlpha, float *uBeta);
extern int SVPWM(float uAlpha, float uBeta, float *tA, float *tB, float *tC);