123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- #include "DRV8837D.h"
- #include <math.h>
- uint8_t use_pid_control = 0; // 是否启用PID调节
- // cur_angle_deg 是当前实际角度值
- // target_angle_deg 是目标角度值
- tPid pidMotor1Speed;
- tPid angle_pid;
- tPid current_pid;
- MotorDirection Motormode;
- float target_angle_deg = 0.0f;
- float diff_Angle = 0.0f; // 目标角度和当前实际角度的差值
- extern float Motor_cur; // 电机电流
- extern float Motor_spe; // 电机转速
- void PID_init(void)
- {
- pidMotor1Speed.target_val = 0.0f; // 目标角度
- pidMotor1Speed.actual_val = 0.0f; // 实际角度
-
- pidMotor1Speed.target_speed = 200.0f;// 目标速度 度/秒
-
- pidMotor1Speed.err = 0.0f; //实际和目标角度差
- pidMotor1Speed.err_last = 0.0f;
- pidMotor1Speed.err_sum = 0.0f;
-
- pidMotor1Speed.Kp = 1.3f;
- pidMotor1Speed.Ki = 0.7f;
- pidMotor1Speed.Kd = 0.2f;
-
- pidMotor1Speed.output_max = 1000;
- pidMotor1Speed.output_min = -1000;
- pidMotor1Speed.integral_max = 5;
-
- }
- // 比例P调节
- float P_realize(tPid * pid, float actual_val)
- {
- pid ->actual_val = actual_val; // 传递真实值
- pid ->err = pid ->target_val - pid ->actual_val;//当前误差 = 目标值 - 真实值
- // 比例控制调节 输出 = Kp*当前误差
- pid ->output = pid ->Kp*pid ->err;
- return pid ->output;
-
- }
- // 比例P 积分I 控制函数
- float PI_realize(tPid * pid, float actual_val)
- {
- pid ->actual_val = actual_val; // 传递真实值
- pid ->err = pid ->target_val - pid ->actual_val;//当前误差 = 目标值 - 真实值
- pid ->err_sum += pid ->err; // 误差累计值 = 当前误差累计和
- // 使用PI控制 输出 = Kp*当前误差 + Ki*误差累计值
- pid ->output = pid ->Kp*pid ->err +pid ->Ki*pid ->err_sum;
- return pid ->output;
- }
- // PID控制函数
- float PID_Realize(tPid *pid, float actual_val, float dt)
- {
- pid->actual_val = actual_val;
- pid->err = get_shortest_angle_error(pid->target_val, pid->actual_val);
- pid->err_sum += pid->err * dt;
- // 限制积分范围
- if (pid->err_sum > pid->integral_max) pid->err_sum = pid->integral_max;
- if (pid->err_sum < -pid->integral_max) pid->err_sum = -pid->integral_max;
- float P = pid->Kp * pid->err;
- float I = pid->Ki * pid->err_sum;
- float D = pid->Kd * (pid->err - pid->err_last) / dt;
- pid->output = P + I + D;
- // 死区控制,避免小抖动
- // if (pid->output > 0 && pid->output < 170)
- // pid->output = 170;
- // else if (pid->output < 0 && pid->output > -170)
- // pid->output = -170;
- // 限幅
- if (pid->output > pid->output_max)
- pid->output = pid->output_max;
- if (pid->output < pid->output_min)
- pid->output = pid->output_min;
- pid->err_last = pid->err;
- return pid->output;
- }
- // PID中间变量
- float pid_integral = 0.0f ;
- float pid_last_error = 0.0f ;
- float PID_Incremental_Calc(tPid *pid, float target_speed, float Motor_spe)
- {
- pid -> err = target_speed - Motor_spe;
-
- pid -> output += pid -> Kp * (pid -> err - pid -> err_last)+
- pid -> Ki * pid -> err +
- pid -> Kd * (pid -> err + pid -> PrevError - 2* pid -> err_last);
-
- pid -> PrevError = pid -> err_last;
- pid -> err_last = pid -> err;
- if( pid -> output > pid -> output_max ) pid -> output = pid -> output_max;
- if( pid -> output < - pid -> output_max ) pid -> output = - pid -> output_max;
-
- return pid ->output;
-
- }
- // 电机角度 cur_angle_deg(0到360度)
- // 电机转速 Motor_spe (-400到+400)
- // 电机电流 Motor_cur (正常是0.0几,堵转最高是到0.3)
- // 目标速度 target_speed
- void Motor_PID_Control(void)
- {
- float error = pidMotor1Speed.target_speed - Motor_spe;
- pid_integral += error;
- float derivative = error - pid_last_error;
- float output = pidMotor1Speed.Kp * error + pidMotor1Speed.Ki * pid_integral + pidMotor1Speed.Kd * derivative;
- pid_last_error = error;
- // 限制输出防止溢出
- if (output > 999.0f) output = 999.0f;
- if (output < -999.0f) output = -999.0f;
- if (output >= 0)
- {
- // 正转
- Motor_control_ZF((uint16_t)output, 0);
- }
- else
- {
- // 反转
- Motor_control_ZF(0, (uint16_t)(-output));
- }
- }
- /*角度 + 电流双环 PID*/
- void Motor_Angle_Current_PID_Control(void)
- {
- float dt = 0.001f; // 5ms 控制周期
- float angle_actual = cur_angle_deg; // 当前角度
- float current_actual = Motor_cur; // 实际电流
- // === 外环:角度 PID,输出为目标电流 ===
- float current_target = PID_Realize(&angle_pid, angle_actual, dt);
- // === 内环:电流 PID,输出为PWM值 ===
- current_pid.target_val = current_target;
- float pwm_output = PID_Realize(¤t_pid, current_actual, dt);
- if (pwm_output >= 0)
- Motor_control_ZF((uint16_t)pwm_output, 0);
- else
- Motor_control_ZF(0, (uint16_t)(-pwm_output));
- }
- // 控制电机正转
- void Motor_Forward(uint16_t speed)
- {
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, speed);
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
- }
- // 控制电机反转
- void Motor_Reverse(uint16_t speed)
- {
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, speed);
- }
- // 控制输出到电机
- void Motor_Control(float control)
- {
- uint16_t pwm = (uint16_t)fabsf(control); // 取正值作为PWM占空比
- if (pwm > 1000) pwm = 1000;
- if (control > 0)
- {
- HAL_GPIO_WritePin(GPIOB, MOTOR_EN_Pin, GPIO_PIN_SET);
- Motor_Forward(pwm);
- }
- else if (control < 0)
- {
- HAL_GPIO_WritePin(GPIOB, MOTOR_EN_Pin, GPIO_PIN_SET);
- Motor_Reverse(pwm);
- }
- else
- {
- // 停止
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
- HAL_GPIO_WritePin(GPIOB, MOTOR_EN_Pin, GPIO_PIN_RESET);
- }
- }
- // 求最短旋转角度差(带方向)
- float get_shortest_angle_error(float target, float actual)
- {
- float error = target - actual;
- if (error > 180.0f)
- error -= 360.0f;
- else if (error < -180.0f)
- error += 360.0f;
- return error;
- }
- // 控制电机正反转
- void Motor_control_ZF(uint16_t forward_speed ,uint16_t reverse_speed)
- {
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, forward_speed); //电机正转
- __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, reverse_speed); //电机反转
- }
- /////////////////////////////////////////////////
- /*
- void motor_forward(void) // 电机正转
- {
- // 电机红色线接OUT1 电机黑色线接OUT2
-
- HAL_GPIO_WritePin(GPIOB, MOTOR_EN_Pin, GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET);
- }
- void motor_rollback(void) // 电机反转
- {
- // 电机红色线接OUT1 电机黑色线接OUT2
- HAL_GPIO_WritePin(GPIOB, MOTOR_EN_Pin, GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET); // 反转
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);
- }
- void motor_stop(void) // 电机停转
- {
- // 电机红色线接OUT1 电机黑色线接OUT2
- HAL_GPIO_WritePin(GPIOB, MOTOR_EN_Pin, GPIO_PIN_RESET);
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);// 停转
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);
-
- }
- */
|