Files
Gamble/Gambal/User/main.c
2023-12-19 10:15:15 +08:00

560 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include "usart1.h"
#include "pwm.h"
#include "delay.h"
#include "as5600.h"
#include "foc_math.h"
#include "led.h"
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
float voltage_power_supply = 13.6; //V电源电压
int pole_pairs = 14; //电机极数对
float voltage_limit = 7.8; //V,最大值要小于12/1.732=6.9
float velocity_limit = 80; //rad/s 速度限制
//0.6
/******************************************************************************/
//函数声明
float sensor_offset=0;
float zero_electric_angle;
float shaftVelocity(void);
float electricalAngle(void);
float shaftAngle(void);
float y_vel_prev=0;
float LPF_velocity(float x);
u8 get_mpu6050(float *p);
void close_loop(float x);
void commander_run(void);
//PID 参数
float pid_vel_P, pid_ang_P;
float pid_vel_I, pid_ang_D;
float integral_vel_prev;
float error_vel_prev, error_ang_prev;
float output_vel_ramp;
float output_vel_prev;
unsigned long pid_vel_timestamp, pid_ang_timestamp;
void PID_init(void);
float PID_angle(float error);
float PID_velocity(float error);
//
/******************************************************************************/
void Motor_initFOC(void);
float target=0;
//float error;
long sensor_direction = 1;
unsigned long open_loop_timestamp;
int alignSensor(void);
float shaft_angle;
float electrical_angle;
float shaft_velocity;
float current_sp;
float shaft_velocity_sp;
float shaft_angle_sp;
void setPhaseVoltage(float Uq, float Ud, float angle_el);
void speed_close_loop(float new_target); //速度闭环控制
void angle_close_loop(float new_target); //角度闭环控制
void speed_open_loop(float new_target); //速度开环控制
float error_zt_prev;
void PID_ZT(float error);
float y_ZT_prev=0;
float LPF_ZT(float x);
/******************************************************************************/
int main()
{
led_init();
led = 1;
usart1_Init(2000000);
delay_ms(100);
TX_485;
delay_ms(1000); //等待单片机稳定
delay_ms(1000);
delay_ms(1000);
led = 1;
I2C_Init_();
TIM2_PWM_Init();
TIM4_1ms_Init();
MagneticSensor_Init();
M_Enable;
Motor_initFOC();
PID_init();
systick_CountMode();
RX_485;
target =0;
time1_cntr = 0;
time2_cntr = 0;
USART_RX_STA=0;
memset(USART_RX_BUF,0,64);
// while(time1_cntr < 13000)
// {
//// PID_ZT(0);
// speed_close_loop(3.8);
//// angle_close_loop(6.0);
//// angle_close_loop(2.4);
// commander_run();
// }
while(1)
{
// setPhaseVoltage(6,0,0);
PID_ZT(target);
// target =atof((const char *)(G_RX_Xerror));
target = 0 - atof((const char *)(G_RX_Yerror));
// target =LPF_ZT(target);
// angle_close_loop(3.8);
// close_loop(target);
// commander_run();
// speed_close_loop(_PI);
// i++;
// shaft_angle = shaftAngle();
// printf("A%.3f",shaft_angle);
}
}
void PID_init(void)
{
// ///xxxxxxxxxxxxxx
// pid_vel_P=0.01; //0.1
// pid_vel_I=0.12; //2
// output_vel_ramp=100;
// integral_vel_prev=0;
// error_vel_prev=0;
// output_vel_prev=0;
// pid_vel_timestamp=SysTick->VAL;
// pid_ang_P = 120;
// pid_ang_D = 10;
// error_ang_prev= 0;
// pid_ang_timestamp=SysTick->VAL;
// ////////yyyyyyyyyyyy
pid_vel_P=0.8; //0.1
pid_vel_I=0.1; //2
output_vel_ramp=100;
integral_vel_prev=0;
error_vel_prev=0;
output_vel_prev=0;
pid_vel_timestamp=SysTick->VAL;
pid_ang_P = 10;
pid_ang_D =5;
error_ang_prev= 0;
pid_ang_timestamp=SysTick->VAL;
}
/******************************************************************************/
float shaftAngle(void)
{
return sensor_direction*getAngle() - sensor_offset;
}
float shaftVelocity(void)
{
return sensor_direction*LPF_velocity(getVelocity());
}
/******************************************************************************/
float electricalAngle(void)
{
return _normalizeAngle((shaft_angle + sensor_offset) * pole_pairs - zero_electric_angle);
}
float LPF_ZT(float x)
{
float y = 0.01*y_vel_prev + 0.99*x;
y_ZT_prev=y;
return y;
}
float LPF_velocity(float x)
{
float y = 0.9*y_vel_prev + 0.1*x;
y_vel_prev=y;
return y;
}
/******************************************************************************/
float PID_velocity(float error)
{
unsigned long now_us;
float Ts;
float proportional,integral,output;
float output_rate;
now_us = SysTick->VAL;
if(now_us<pid_vel_timestamp)Ts = (float)(pid_vel_timestamp - now_us)/9*1e-6f;
else
Ts = (float)(0xFFFFFF - now_us + pid_vel_timestamp)/9*1e-6f;
pid_vel_timestamp = now_us;
if(Ts == 0 || Ts > 0.5) Ts = 1e-3f;
proportional = pid_vel_P * error;
integral = integral_vel_prev + pid_vel_I*Ts*0.5*(error + error_vel_prev);
integral = _constrain(integral, -voltage_limit, voltage_limit);
output = proportional + integral;
output = _constrain(output, -voltage_limit, voltage_limit);
output_rate = (output - output_vel_prev)/Ts;
if(output_rate > output_vel_ramp)output = output_vel_prev + output_vel_ramp*Ts;
else if(output_rate < -output_vel_ramp)output = output_vel_prev - output_vel_ramp*Ts;
output = _constrain(output, -voltage_limit, voltage_limit);
integral_vel_prev = integral;
output_vel_prev = output;
error_vel_prev = error;
return output;
}
float PID_angle(float error)
{
unsigned long now_us;
float Ts;
float proportional,derivative,output;
now_us = SysTick->VAL;
if(now_us<pid_ang_timestamp)Ts = (float)(pid_ang_timestamp - now_us)/9*1e-6f;
else
Ts = (float)(0xFFFFFF - now_us + pid_ang_timestamp)/9*1e-6f;
pid_ang_timestamp = now_us;
if(Ts == 0 || Ts > 0.5) Ts = 1e-3f;
proportional = pid_ang_P * error;
derivative = pid_ang_D*(error - error_ang_prev)/Ts;
output = proportional + derivative;
output = _constrain(output, -velocity_limit, velocity_limit);
error_ang_prev = error;
return output;
}
void Motor_initFOC(void)
{
// alignSensor();
angle_prev=getAngle();
delay_ms(5);
shaft_velocity = shaftVelocity();
delay_ms(5);
shaft_angle = shaftAngle();
delay_ms(200);
}
int alignSensor(void)
{
// long i;
// float angle;
// float mid_angle,end_angle;
// float moved;
//
//// printf("MOT: Align sensor.\r\n");
//
// setPhaseVoltage(2.5, 0, _3PI_2 );
// delay_ms(100);
// mid_angle=getAngle();
// for(i=0; i<=500; i++)
// {
// angle = _3PI_2 + _2PI * i / 500.0;
// setPhaseVoltage(2.5, 0, angle);
// delay_ms(2);
// }
// end_angle=getAngle();
//
// for(i=500; i>=0; i--)
// {
// angle = _3PI_2 + _2PI * i / 500.0 ;
// setPhaseVoltage(2.5, 0, angle);
// delay_ms(2);
// }
// setPhaseVoltage(0, 0, 0);
// delay_ms(200);
//
//// printf("mid_angle=%.4f\n",mid_angle);
//// printf("end_angle=%.4f\n",end_angle);
//
// moved = fabs(end_angle - mid_angle);
// if((mid_angle == end_angle)||(moved < 0.02))
// {
//// printf("Moto Failed Init.\n");
// M_Disable;
// return 0;
// }
// else if(mid_angle < end_angle)
// {
//// printf("Moto sensor_direction== 1\n");
// sensor_direction=1;
// }
// else
// {
//// printf("Moto sensor_direction== -1\n");
// sensor_direction= -1;
// }
//
// printf("MOT: PP check:\n ");
// if( fabs(moved*pole_pairs - _2PI) > 0.5 )
// {
// printf("fail - estimated pp:");
// pole_pairs =_2PI/moved+0.5;
// printf("%d\n",pole_pairs);
// }
// else
// printf("OK!\n");
setPhaseVoltage(3, 0, _3PI_2);
delay_ms(700);
// zero_electric_angle = 0;
zero_electric_angle = _normalizeAngle(_electricalAngle(sensor_direction*getAngle(), pole_pairs));
delay_ms(20);
// printf("MOT: Zero elec. angle:");
// printf("%.4f\r\n",zero_electric_angle);
// zero_electric_angle = 0;
setPhaseVoltage(0, 0, 0);
delay_ms(100);
return 1;
}
void setPhaseVoltage(float Uq, float Ud, float angle_el)
{
float Uout;
uint32_t sector;
float T0,T1,T2;
float Ta,Tb,Tc;
if(Ud)
{
Uout = _sqrt(Ud*Ud + Uq*Uq) / voltage_power_supply;
angle_el = _normalizeAngle(angle_el + atan2(Uq, Ud));
}
else
{
Uout = Uq / voltage_power_supply;
angle_el = _normalizeAngle(angle_el + _PI_2);
}
if(Uout> 0.577)Uout= 0.577;
if(Uout<-0.577)Uout=-0.577;
sector = (angle_el / _PI_3) + 1;
T1 = _SQRT3*_sin(sector*_PI_3 - angle_el) * Uout;
T2 = _SQRT3*_sin(angle_el - (sector-1.0)*_PI_3) * Uout;
T0 = 1 - T1 - T2;
switch(sector)
{
case 1:
Ta = T1 + T2 + T0/2;
Tb = T2 + T0/2;
Tc = T0/2;
break;
case 2:
Ta = T1 + T0/2;
Tb = T1 + T2 + T0/2;
Tc = T0/2;
break;
case 3:
Ta = T0/2;
Tb = T1 + T2 + T0/2;
Tc = T2 + T0/2;
break;
case 4:
Ta = T0/2;
Tb = T1+ T0/2;
Tc = T1 + T2 + T0/2;
break;
case 5:
Ta = T2 + T0/2;
Tb = T0/2;
Tc = T1 + T2 + T0/2;
break;
case 6:
Ta = T1 + T2 + T0/2;
Tb = T0/2;
Tc = T1 + T0/2;
break;
default:
Ta = 0;
Tb = 0;
Tc = 0;
}
TIM_SetCompare1(TIM2,Ta*1440);
TIM_SetCompare2(TIM2,Tb*1440);
TIM_SetCompare3(TIM2,Tc*1440);
}
void speed_close_loop(float new_target)
{
float Uq,Ud,electrical_angle;
shaft_velocity = shaftVelocity();
shaft_velocity_sp = new_target;
current_sp = PID_velocity(shaft_velocity_sp - shaft_velocity);
Uq = current_sp;
Ud = 0;
shaft_angle = shaftAngle();
electrical_angle = electricalAngle();
setPhaseVoltage(Uq, Ud, electrical_angle);
}
void angle_close_loop(float new_target)
{
float Uq,Ud,electrical_angle;
shaft_velocity = shaftVelocity();
shaft_angle_sp = new_target;
//
shaft_angle = shaftAngle();
//
shaft_velocity_sp = PID_angle(shaft_angle_sp - shaft_angle);
current_sp = PID_velocity(shaft_velocity_sp - shaft_velocity);
Uq = current_sp;
Ud = 0;
// shaft_angle = shaftAngle();
electrical_angle = electricalAngle();
setPhaseVoltage(Uq, Ud, electrical_angle);
}
void speed_open_loop(float new_target)
{
float Uq = new_target;
Uq =_constrain(Uq,-5,5);
for(float electrical_angle = 0;electrical_angle < _2PI;electrical_angle = electrical_angle + 0.1)
{
setPhaseVoltage(Uq, 0, electrical_angle);
}
}
void close_loop(float e)
{
float Uq,Ud,electrical_angle;
shaft_velocity = shaftVelocity();
shaft_velocity_sp = PID_angle(e);
current_sp = PID_velocity(shaft_velocity_sp - shaft_velocity);
Uq = current_sp;
Ud = 0;
shaft_angle = shaftAngle();
electrical_angle = electricalAngle();
setPhaseVoltage(Uq, Ud, electrical_angle);
}
void PID_ZT(float error)
{
unsigned long now_us;
float Ts;
float proportional,integral,output;
float output_rate;
now_us = SysTick->VAL;
if(now_us<pid_vel_timestamp)Ts = (float)(pid_vel_timestamp - now_us)/9*1e-6f;
else
Ts = (float)(0xFFFFFF - now_us + pid_vel_timestamp)/9*1e-6f;
pid_vel_timestamp = now_us;
if(Ts == 0 || Ts > 0.5) Ts = 1e-3f;
////////////////
//姿态环:PD控制算出target_v
proportional = pid_ang_P * error;
float derivative = pid_ang_D*(error - error_zt_prev)/Ts;
float target_v = proportional + derivative;
target_v = _constrain(target_v, -velocity_limit, velocity_limit);
error_zt_prev = error;
//获取速度
float now_angle,now_v;
now_angle = getAngle();
//now_v
now_v = (now_angle - angle_prev)/Ts;
now_v = LPF_velocity(now_v);
angle_prev = now_angle;
velocity_calc_timestamp = now_us;
//速度环
error = target_v - now_v;
proportional = pid_vel_P * error;
integral = integral_vel_prev + pid_vel_I*Ts*0.5*(error + error_vel_prev);
integral = _constrain(integral, -voltage_limit, voltage_limit);
output = proportional+integral;
output = _constrain(output, -voltage_limit, voltage_limit);
output_rate = (output - output_vel_prev)/Ts;
if(output_rate > output_vel_ramp)output = output_vel_prev + output_vel_ramp*Ts;
else if(output_rate < -output_vel_ramp)output = output_vel_prev - output_vel_ramp*Ts;
output = _constrain(output, -voltage_limit, voltage_limit);
integral_vel_prev = integral;
output_vel_prev = output;
error_vel_prev = error;
//控制电机
shaft_angle = shaftAngle();
electrical_angle = electricalAngle();
setPhaseVoltage(output, 0, electrical_angle);
// return output;
}