servo/firmware/Lib/foc/foc.c
vanyabeat bd7f049b75 ADD: dummy foc
SIMPLE

CLEAN: cleanup code and add printf handler

FIX: counters

ADD: motor

ENH: temporary disable can

ADD: dummy foc, but creepy work
2024-02-22 16:38:48 +00:00

188 lines
No EOL
5.7 KiB
C

#include "foc.h"
#include <stdio.h>
#include "pid.h"
foc_motor_t Motor_6208;
float _SIN(float theta) {
return sin(theta);
}
float _COS(float theta) {
return cos(theta);
}
#define SQRT_3 1.73205080757f
void get_Angle(foc_motor_t *__obj, float AbsoulteAngle) {
__obj->machine_angle = AbsoulteAngle - __obj->Encoder_ZeroPoint;
if (__obj->machine_angle < 0) {
__obj->machine_angle += (2 * PI);
}
__obj->electron_angle = __obj->polar_pair * __obj->machine_angle;
}
// Feedback Part
void Current_Sample(foc_motor_t *__obj) {}
void Clark_Trans(foc_motor_t *__obj) {}
void Park_Trans(foc_motor_t *__obj) {}
void Inv_Park_Trans(foc_motor_t *__obj) {
float theta = __obj->electron_angle;
__obj->inv_park_U_alpha = _COS(theta) * __obj->current_loop_Ud - _SIN(theta) * __obj->current_loop_Uq;
__obj->inv_park_U_beta = _SIN(theta) * __obj->current_loop_Ud + _COS(theta) * __obj->current_loop_Uq;
}
/// @brief Функция преобразования вектора напряжения в ШИМ сигнал для управления мотором
/// @param __obj
/// @param htim
void SVPWM_Trans(foc_motor_t *__obj, TIM_HandleTypeDef *htim) {
// float Udc = sqrtf(powf(__obj->inv_park_U_alpha, 2) + powf(__obj->inv_park_U_beta, 2)); // 总电压向量模值,即输出电压大小
float Udc = __obj->Udc;
float Ual = __obj->inv_park_U_alpha, Ubt = __obj->inv_park_U_beta;
float Ts = 2399.0f;
float X, Y, Z;
uint8_t A, B, C, N; // нужно ли оценивать сектор в котором находится вектор
float Ta, Tb, Tc, t1, t2; // промежутки времени для каждого сектора
X = SQRT_3 * Ts * Ubt / Udc;
Y = SQRT_3 * Ts * (SQRT_3 * Ual + Ubt) / Udc / 2;
Z = SQRT_3 * Ts * (-SQRT_3 * Ual + Ubt) / Udc / 2;
if (Ubt < -SQRT_3 * Ual) A = 1; else A = 0;
if (Ubt < SQRT_3 * Ual) B = 1; else B = 0;
if (Ubt > 0) C = 1; else C = 0;
N = 4 * A + 2 * B + C;
if (N == 3) {
t1 = -Z;
t2 = X;
Ta = 0.5f * (Ts - t1 - t2);
Tb = Ta + t1;
Tc = Tb + t2;
__obj->svpwm_Ua = (uint16_t) (Ts - Ta);
__obj->svpwm_Ub = (uint16_t) (Ts - Tb);
__obj->svpwm_Uc = (uint16_t) (Ts - Tc);
} else if (N == 1) {
t1 = Z;
t2 = Y;
Ta = 0.5f * (Ts - t1 - t2);
Tb = Ta + t1;
Tc = Tb + t2;
__obj->svpwm_Ua = (uint16_t) (Ts - Tb);
__obj->svpwm_Ub = (uint16_t) (Ts - Ta);
__obj->svpwm_Uc = (uint16_t) (Ts - Tc);
} else if (N == 5) {
t1 = X;
t2 = -Y;
Ta = 0.5f * (Ts - t1 - t2);
Tb = Ta + t1;
Tc = Tb + t2;
__obj->svpwm_Ua = (uint16_t) (Ts - Tc);
__obj->svpwm_Ub = (uint16_t) (Ts - Ta);
__obj->svpwm_Uc = (uint16_t) (Ts - Tb);
} else if (N == 4) {
t1 = -X;
t2 = Z;
Ta = 0.5f * (Ts - t1 - t2);
Tb = Ta + t1;
Tc = Tb + t2;
__obj->svpwm_Ua = (uint16_t) (Ts - Tc);
__obj->svpwm_Ub = (uint16_t) (Ts - Tb);
__obj->svpwm_Uc = (uint16_t) (Ts - Ta);
} else if (N == 6) {
t1 = -Y;
t2 = -Z;
Ta = 0.5f * (Ts - t1 - t2);
Tb = Ta + t1;
Tc = Tb + t2;
__obj->svpwm_Ua = (uint16_t) (Ts - Tb);
__obj->svpwm_Ub = (uint16_t) (Ts - Tc);
__obj->svpwm_Uc = (uint16_t) (Ts - Ta);
} else {
t1 = Y;
t2 = -X;
Ta = 0.5f * (Ts - t1 - t2);
Tb = Ta + t1;
Tc = Tb + t2;
__obj->svpwm_Ua = (uint16_t) (Ts - Ta);
__obj->svpwm_Ub = (uint16_t) (Ts - Tc);
__obj->svpwm_Uc = (uint16_t) (Ts - Tb);
}
__obj->set_pwm(htim, __obj->svpwm_Ua, __obj->svpwm_Ub, __obj->svpwm_Uc);
}
void set_torque(foc_motor_t *__obj, float Uq) {
__obj->current_loop_Ud = 0;
__obj->current_loop_Uq = Uq;
}
/// @brief Функция обработки границы для углов и токов
/// @param ref
/// @param exp
/// @param max
/// @return
float boundary_process(float ref, float exp, float max) {
if (ref - exp >= (max / 2)) {
return ref - max;
} else if (ref - exp <= -max / 2) {
return ref + max;
} else {
return ref;
}
}
pid_type_t position_loop;
void foc_init(foc_motor_t *__obj, float polar_pair, float Encoder_ZP, float Udc, set_pwm_handler set_pwm, get_raw_angle raw_angle) {
__obj->polar_pair = polar_pair;
__obj->machine_angle = 0;
__obj->electron_angle = 0;
__obj->Encoder_ZeroPoint = Encoder_ZP;
__obj->Udc = Udc;
__obj->set_pwm = set_pwm;
__obj->raw_angle = raw_angle;
pid_init(&position_loop, PID_POSITION, 5, 3, 3, __obj->Udc, __obj->Udc * 0.8f);
}
void foc_run(foc_motor_t *__obj, TIM_HandleTypeDef *htim, SPI_HandleTypeDef *hspi) {
get_Angle(__obj, 2.0f * PI * __obj->raw_angle(hspi, NULL) / 1024);
static float T_count = 0;
T_count += 0.07;
// static float target_angle = 1.5*_SIN(T_count) * _SIN(0.05*T_count);//expf(-0.01*T_count);
static float target_angle = 0;//expf(-0.01*T_count);
target_angle = 2.0f * PI * _SIN(T_count);
float angle_bias = boundary_process(__obj->machine_angle, target_angle, 2 * PI);
float torque = pid_calc(&position_loop, angle_bias, target_angle);
set_torque(__obj, torque);
// printf("%.2f, %.2f, %.2f\n", 180 / PI * __obj->Encoder_ZeroPoint, 180 / PI * __obj->machine_angle, target_angle);
// printf("%.2f, %.2f, %.2f\n", angle_bias, target_angle, torque);
Inv_Park_Trans(__obj);
SVPWM_Trans(__obj, htim);
// target_angle += PI / 3;
// printf("%d,%d,%d\n", __obj->svpwm_Ua, __obj->svpwm_Ub, __obj->svpwm_Uc);
printf("Machine Angle: %.2f, Target Angle: %.2f, Torque: %.2f\n", 180 / PI * __obj->machine_angle, 180 / PI * target_angle, torque);
// target_angle += 10;
}