R2_NEW/User/Module/up.c
2025-06-27 21:43:58 +08:00

429 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 "up.h"
#include "gpio.h"
#include "user_math.h"
#include "bsp_buzzer.h"
#include "bsp_delay.h"
/*接线
*/
#define GEAR_RATIO_2006 (36) // 2006减速比
#define GEAR_RATIO_3508 (19)
#define CAN_MOTOR_ENC_RES 8191 // 编码器分辨率
#define MOTOR2006_ECD_TO_ANGLE (360.0 / 8191.0 / (GEAR_RATIO_2006)) //2006编码值转轴角度
#define MOTOR3508_ECD_TO_ANGLE (360.0 / 8191.0 / (GEAR_RATIO_3508)) //3508编码值转轴角度
#define CAN2_G3508_ID (0x200)
// 定义继电器控制
#define RELAY1_TOGGLE(state) HAL_GPIO_WritePin(GPIOE, RELAY_Pin, (state) ? GPIO_PIN_SET : GPIO_PIN_RESET)
int8_t up_init(UP_t *u,const UP_Param_t *param,float target_freq)
{
u->param = param; /*初始化参数 */
/*pid初始化*/
PID_init (&u->pid.VESC_5065_M1 ,PID_POSITION ,&(u->param ->VESC_5065_M1_param ));
PID_init (&u->pid.VESC_5065_M2 ,PID_POSITION ,&(u->param ->VESC_5065_M2_param ));
PID_init (&u->pid .Shoot_M2006angle ,PID_POSITION ,&(u->param->Shoot_M2006_angle_param ));
PID_init (&u->pid .Shoot_M2006speed ,PID_POSITION ,&(u->param->Shoot_M2006_speed_param ));
PID_init (&u->pid .Pitch_Angle_M2006_speed ,PID_POSITION ,&(u->param->Pitch_Angle_M2006_speed_param));
PID_init (&u->pid .Pitch_M2006_angle ,PID_POSITION ,&(u->param->Pitch_M2006_angle_param ));
PID_init (&u->pid .Pitch_M2006_speed ,PID_POSITION ,&(u->param->Pitch_M2006_speed_param ));
u->go_cmd =u->param ->go_cmd ;
LowPassFilter2p_Init(&(u->filled[0]),target_freq,100.0f);
if (!u->PitchContext .is_init) {
u->PitchContext .PitchConfig = u->param ->PitchCfg ;//赋值
u->PitchContext .PitchState = PITCH_PREPARE; //状态更新
u->PitchContext .is_init = 1;
}
if(!u->PassContext.is_init) {
u->PassContext .PassCfg = u->param ->PassCfg ;//赋值
u->PassContext .PassState = PASS_STOP; //状态更新
u->PassContext .is_init = 1;
}
u->LaunchContext.LaunchCfg = u->param->LaunchCfg;
BSP_UART_RegisterCallback(BSP_UART_RS485, BSP_UART_RX_CPLT_CB, USART6_RxCompleteCallback);//注册串口回调函数bsp层
}
/*can上层状态更新*/
int8_t UP_UpdateFeedback(UP_t *u, const CAN_t *can, CMD_t *c) {
u->motorfeedback .VESC.VESC_5065_M1_rpm =can ->motor .chassis5065 .as_array [0].rotor_speed ;
u->motorfeedback .VESC.VESC_5065_M2_rpm =can ->motor .chassis5065 .as_array [1].rotor_speed ;
u->motorfeedback .Encoder .angle = can ->Oid.angle ;
u->motorfeedback .Encoder .ecd = can ->Oid.ecd ;
for(int i=0;i<4;i++){ //范围0x201--0x204
u->motorfeedback .DJmotor_feedback[i].id =i+CAN2_G3508_ID+1;
u->motorfeedback .DJmotor_feedback[i].rpm =can ->motor .up_dribble_motor3508 .as_array [i].rotor_speed ;
u->motorfeedback .DJmotor_feedback[i].ecd =can ->motor .up_dribble_motor3508.as_array [i].rotor_ecd ;
DJ_processdata(&u->motorfeedback .DJmotor_feedback [i], MOTOR3508_ECD_TO_ANGLE);
}
for(int i=0;i<2;i++){ //范围0x205--0x206
u->motorfeedback .DJmotor_feedback[i+4].id =i+CAN2_G3508_ID+4+1;
u->motorfeedback .DJmotor_feedback[i+4].rpm =can ->motor .up_shoot_motor3508 .as_array [i].rotor_speed ;
u->motorfeedback .DJmotor_feedback[i+4].ecd =can ->motor .up_shoot_motor3508.as_array [i].rotor_ecd ;
DJ_processdata(&u->motorfeedback .DJmotor_feedback [i+4], MOTOR2006_ECD_TO_ANGLE);
}
u->cmd =c;
return 0;
}
/*
这里id范围为1-4
*/
int8_t DJ_Angle_Control(UP_t *u,int id,DJmotor_feedback_t *f,pid_type_def *Angle_pid,pid_type_def *Speed_pid,fp32 target_angle)
{
fp32 delta_angle,delta_speed;
delta_angle = PID_calc(Angle_pid , f->total_angle , target_angle);
delta_speed = PID_calc(Speed_pid , f->rpm , delta_angle);
u->final_out .DJfinal_out [id-CAN2_G3508_ID-1]=delta_speed;
return 0;
}
int8_t DJ_Speed_Control(UP_t *u,int id,DJmotor_feedback_t *f,pid_type_def *Speed_pid,fp32 target_speed)
{
fp32 delta_speed;
delta_speed = PID_calc(Speed_pid , f->rpm , target_speed);
u->final_out .DJfinal_out [id-CAN2_G3508_ID-1]=delta_speed;
return 0;
}
int8_t VESC_M5065_Control(UP_t *u,fp32 speed)
{
u->motor_target .VESC_5065_M1_rpm =speed;
u->motor_target .VESC_5065_M2_rpm =speed;
//根据正反加负号
u->final_out .final_VESC_5065_M1out =-u->motor_target .VESC_5065_M1_rpm;
u->final_out .final_VESC_5065_M2out =u->motor_target .VESC_5065_M2_rpm;
return 0;
}
int8_t ALL_Motor_Control(UP_t *u,CAN_Output_t *out)
{
//电机控制 传进can
DJ_Angle_Control(u,0x205,&u->motorfeedback .DJmotor_feedback[4] ,
&u->pid .Shoot_M2006angle ,
&u->pid .Shoot_M2006speed ,
u->motor_target .Shoot_M2006_angle );
/*俯仰2006双环内使用oid角度环外电机速度环
*/
DJ_Speed_Control(u,0x206,&u->motorfeedback .DJmotor_feedback[5],&u->pid .Pitch_M2006_speed,
(PID_calc (&(u->pid .Pitch_M2006_angle ),
u->motorfeedback .Encoder.angle,u->motor_target .Pitch_angle)+0.14)
);
GO_SendData(
&u->motorfeedback.go_data,
&u->go_cmd,u->motor_target .go_shoot,
u->motor_target.go_pull_speed
);
for(int i=0;i<4;i++){
out ->motor_UP3508_Dribble.as_array[i]=u->final_out.DJfinal_out [i] ;
}
for(int i=0;i<2;i++){
out ->motor_UP3508_shoot.as_array[i]=u->final_out.DJfinal_out [i+4] ;
}
out ->chassis5065 .erpm [0]= u->final_out .final_VESC_5065_M1out ;
out ->chassis5065 .erpm [1]= -u->final_out .final_VESC_5065_M2out ;
return 0;
}
fp32 posss=0;
int8_t UP_control(UP_t *u,CAN_Output_t *out,CMD_t *c)
{
if(u ==NULL) return 0;
if(out ==NULL) return 0;
if(c ==NULL) return 0;
/*指针简化*/
PitchCfg_t *pitch_cfg = &u->PitchContext.PitchConfig;
LaunchCfg_t *LaunchCfg =&u->LaunchContext.LaunchCfg;
up_motor_target_t *target=&u->motor_target ;
/*config值限位*/
abs_limit_min_max_fp(&u->PitchContext.PitchConfig.go_release_pos ,-215.0f,0.0f);
abs_limit_min_max_fp(&u->PitchContext.PitchConfig.Pitch_angle ,48.0f,67.0f);
/*部分数据更新*/
static int is_pitch=1;
posss=CurveChange(LowPassFilter2p_Apply(&u->filled[0],c->pos),3,4,&u->PitchContext.Curve);
// if (u->PitchContext.Curve == CURVE_58) {
// target->Pitch_angle = 58;
// } else {
// target->Pitch_angle = 66;
// }
switch (c->CMD_CtrlType )
{
case RCcontrol: //在手动模式下
switch (c-> CMD_mode )
{
case Normal : //复位go位置和俯仰角保持LaunchCfg最后修改后的位置扳机2006角度复位用于发射
/*投篮*/
if(is_pitch){
target->go_shoot = LaunchCfg->go_init ;
target->Pitch_angle = LaunchCfg->Pitch_angle;
is_pitch=0;
} //初始上电
LaunchCfg->go_up_speed=15;
target->Pitch_angle =LaunchCfg->Pitch_angle;
target->Shoot_M2006_angle=LaunchCfg->m2006_init;
u->PitchContext .PitchState = PITCH_PREPARE; //状态更新
u->LaunchContext.LaunchState = Launch_Stop;
break;
case Pitch :
if (u->PitchContext .PitchState ==PITCH_PREPARE)
{
u->PitchContext .PitchState=PITCH_START;//置标志位用于启动投篮
}
Pitch_Process(u,out,c);
break ;
case UP_Adjust: //测试用,手动使用pitch下的cfg
LaunchCfg->go_up_speed=5;
pitch_cfg ->go_release_pos += c->Vx ;
LaunchCfg->Pitch_angle += c->Vy/100;
target->go_shoot=pitch_cfg ->go_release_pos;
target->Pitch_angle=LaunchCfg->Pitch_angle;
break ;
default:
break;
}
break;
case AUTO:
/*自动下数据更新,根据距离切换俯仰角,如需自动调整,放在*/
// if (u->PitchContext.Curve == CURVE_58) {
// target->Pitch_angle = 58;
// } else {
// target->Pitch_angle = 66;
// }
switch(c-> CMD_mode)
{
case AUTO_MID360_Pitch:
if (u->PitchContext .PitchState ==PITCH_PREPARE || u->PitchContext .PitchState ==PITCH_COMPLETE)
{
u->PitchContext .PitchState=PITCH_START;//置标志位用于启动投篮
}
/*根据距离实时计算所需pos*/
if(c->pos){
pitch_cfg ->go_release_pos=
CurveChange(LowPassFilter2p_Apply(&u->filled[0],c->pos),3,4,&u->PitchContext.Curve);
}
else pitch_cfg ->go_release_pos=0 ;
Pitch_Process(u,out,c);
break ;
case AUTO_MID360:
target->Shoot_M2006_angle =LaunchCfg ->m2006_init ;
break ;
default:
break;
}
break ;
case PASS_BALL:
// if (u->PitchContext.Curve == CURVE_58) {
// target->Pitch_angle = 58;
// } else {
// target->Pitch_angle = 66;
// }
Pass_Process(u,out,c);
break;
case RELAXED:
// target->go_shoot= pitch_cfg .
target->Pitch_angle = 58;
target->go_shoot = -210.0f;
// target->Pitch_angle = 58;
break ;
}
return 0;
}
//复用发射,
int8_t Pitch_Launch_Sequence(UP_t *u, LaunchContext_t *LaunchContext,fp32 StartPos,fp32 EndPos,CAN_Output_t *out){
switch(LaunchContext->LaunchState){
case Launch_Stop: break;
case Launch_PREPARE:
u->motor_target.go_shoot = StartPos;
if(is_reached(u->motorfeedback.go_data.Pos,StartPos,1.0f)&&
is_reached(u->motorfeedback.go_data.W,0,1.0f)){
//根据位置和速度判断是否到达初始位置
LaunchContext->LaunchState = Launch_START;
}break;
case Launch_START:
u->motor_target.go_pull_speed=LaunchContext->LaunchCfg.go_up_speed;
u->motor_target.go_shoot = u->LaunchContext.LaunchCfg.go_pull_pos;
if(u->motorfeedback .go_data .Pos < -209){ //检测go位置到达最上面这里的检测条件可以更改
u->motor_target.Shoot_M2006_angle = u->LaunchContext.LaunchCfg.m2006_trig ;//设置2006角度关闭
LaunchContext->LaunchState = Launch_TRIGGER;
}break;
case Launch_TRIGGER:
if( u->motorfeedback .DJmotor_feedback [4].total_angle>-1){ //当2006的总角度小于1可以认为已经勾上,误差为1
u->motor_target.go_pull_speed=LaunchContext->LaunchCfg.go_down_speed;
u->motor_target.go_shoot = EndPos ;
if(is_reached(u->motorfeedback.go_data.Pos,EndPos,1.0f))
LaunchContext->LaunchState = Launch_SHOOT_WAIT;
} break;
case Launch_SHOOT_WAIT:
if(u->motorfeedback.DJmotor_feedback[4].total_angle<-1) //认为发射
LaunchContext->LaunchState = Launch_DONE;
break;
case Launch_DONE:
break ;
}
}
int8_t Pitch_Process(UP_t *u, CAN_Output_t *out,CMD_t *c)
{
/*简化*/
PitchCfg_t *cfg = &u->PitchContext.PitchConfig;
PitchState_t *state =&u->PitchContext .PitchState;
up_motor_target_t *target=&u->motor_target ;
LaunchContext_t *LaunchContext = &u->LaunchContext;
// 可根据实际需要传入不同的起始和末位置,起始:当前位置
Pitch_Launch_Sequence(u, LaunchContext, u->motorfeedback.go_data.Pos, cfg->go_release_pos, out);
switch(*state){
case PITCH_START:
LaunchContext->LaunchState = Launch_PREPARE;
*state=PITCH_WAIT;
break;
case PITCH_WAIT:
if(LaunchContext->LaunchState==Launch_DONE)
*state=PITCH_COMPLETE;
break;
case PITCH_COMPLETE:
break;
default:
break;
}
return 0;
}
int8_t Pass_Process(UP_t *u,CAN_Output_t *out,CMD_t *c)
{
PassCfg_t *PassCfg = &u->PassContext.PassCfg;
PassState_t *state = &u->PassContext.PassState;
up_motor_target_t *target=&u->motor_target ;
LaunchContext_t *LaunchContext = &u->LaunchContext;
Pass_Sequence_Check(u,c);
if(c->pos) //
{
PassCfg ->go_release_pos =
CurveChange(LowPassFilter2p_Apply(&u->filled[0],c->pos),3,4,&u->PitchContext.Curve);
}
switch (*state) { //遥控器按键进行状态切换
case PASS_STOP:
break;
case PASS_IDLE:
LaunchContext->LaunchState = Launch_PREPARE;
break;
case PASS_PREPARE:
target->go_pull_speed=PassCfg->go_up_speed;
Pitch_Launch_Sequence(u,LaunchContext,u->motorfeedback.go_data.Pos,PassCfg->go_wait,out);
break;
case PASS_START:
if(LaunchContext->LaunchState == Launch_SHOOT_WAIT){
target->go_pull_speed=PassCfg->go_down_speed;
target->go_shoot = PassCfg->go_release_pos ;
}
break ;
case PASS_POS_PREPARE:
target->Shoot_M2006_angle=LaunchContext->LaunchCfg.m2006_init;//发射
break;
case PASS_COMPLETE:
break;
default:
break;
}
return 0;
}