DRV8837D.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. #include "DRV8837D.h"
  2. #include <math.h>
  3. uint8_t use_pid_control = 0; // 是否启用PID调节
  4. // cur_angle_deg 是当前实际角度值
  5. // target_angle_deg 是目标角度值
  6. tPid pidMotor1Speed;
  7. tPid angle_pid;
  8. tPid current_pid;
  9. MotorDirection Motormode;
  10. float target_angle_deg = 0.0f;
  11. float diff_Angle = 0.0f; // 目标角度和当前实际角度的差值
  12. extern float Motor_cur; // 电机电流
  13. extern float Motor_spe; // 电机转速
  14. void PID_init(void)
  15. {
  16. pidMotor1Speed.target_val = 0.0f; // 目标角度
  17. pidMotor1Speed.actual_val = 0.0f; // 实际角度
  18. pidMotor1Speed.target_speed = 200.0f;// 目标速度 度/秒
  19. pidMotor1Speed.err = 0.0f; //实际和目标角度差
  20. pidMotor1Speed.err_last = 0.0f;
  21. pidMotor1Speed.err_sum = 0.0f;
  22. pidMotor1Speed.Kp = 1.3f;
  23. pidMotor1Speed.Ki = 0.7f;
  24. pidMotor1Speed.Kd = 0.2f;
  25. pidMotor1Speed.output_max = 1000;
  26. pidMotor1Speed.output_min = -1000;
  27. pidMotor1Speed.integral_max = 5;
  28. }
  29. // 比例P调节
  30. float P_realize(tPid * pid, float actual_val)
  31. {
  32. pid ->actual_val = actual_val; // 传递真实值
  33. pid ->err = pid ->target_val - pid ->actual_val;//当前误差 = 目标值 - 真实值
  34. // 比例控制调节 输出 = Kp*当前误差
  35. pid ->output = pid ->Kp*pid ->err;
  36. return pid ->output;
  37. }
  38. // 比例P 积分I 控制函数
  39. float PI_realize(tPid * pid, float actual_val)
  40. {
  41. pid ->actual_val = actual_val; // 传递真实值
  42. pid ->err = pid ->target_val - pid ->actual_val;//当前误差 = 目标值 - 真实值
  43. pid ->err_sum += pid ->err; // 误差累计值 = 当前误差累计和
  44. // 使用PI控制 输出 = Kp*当前误差 + Ki*误差累计值
  45. pid ->output = pid ->Kp*pid ->err +pid ->Ki*pid ->err_sum;
  46. return pid ->output;
  47. }
  48. // PID控制函数
  49. float PID_Realize(tPid *pid, float actual_val, float dt)
  50. {
  51. pid->actual_val = actual_val;
  52. pid->err = get_shortest_angle_error(pid->target_val, pid->actual_val);
  53. pid->err_sum += pid->err * dt;
  54. // 限制积分范围
  55. if (pid->err_sum > pid->integral_max) pid->err_sum = pid->integral_max;
  56. if (pid->err_sum < -pid->integral_max) pid->err_sum = -pid->integral_max;
  57. float P = pid->Kp * pid->err;
  58. float I = pid->Ki * pid->err_sum;
  59. float D = pid->Kd * (pid->err - pid->err_last) / dt;
  60. pid->output = P + I + D;
  61. // 死区控制,避免小抖动
  62. // if (pid->output > 0 && pid->output < 170)
  63. // pid->output = 170;
  64. // else if (pid->output < 0 && pid->output > -170)
  65. // pid->output = -170;
  66. // 限幅
  67. if (pid->output > pid->output_max)
  68. pid->output = pid->output_max;
  69. if (pid->output < pid->output_min)
  70. pid->output = pid->output_min;
  71. pid->err_last = pid->err;
  72. return pid->output;
  73. }
  74. // PID中间变量
  75. float pid_integral = 0.0f ;
  76. float pid_last_error = 0.0f ;
  77. float PID_Incremental_Calc(tPid *pid, float target_speed, float Motor_spe)
  78. {
  79. pid -> err = target_speed - Motor_spe;
  80. pid -> output += pid -> Kp * (pid -> err - pid -> err_last)+
  81. pid -> Ki * pid -> err +
  82. pid -> Kd * (pid -> err + pid -> PrevError - 2* pid -> err_last);
  83. pid -> PrevError = pid -> err_last;
  84. pid -> err_last = pid -> err;
  85. if( pid -> output > pid -> output_max ) pid -> output = pid -> output_max;
  86. if( pid -> output < - pid -> output_max ) pid -> output = - pid -> output_max;
  87. return pid ->output;
  88. }
  89. // 电机角度 cur_angle_deg(0到360度)
  90. // 电机转速 Motor_spe (-400到+400)
  91. // 电机电流 Motor_cur (正常是0.0几,堵转最高是到0.3)
  92. // 目标速度 target_speed
  93. void Motor_PID_Control(void)
  94. {
  95. float error = pidMotor1Speed.target_speed - Motor_spe;
  96. pid_integral += error;
  97. float derivative = error - pid_last_error;
  98. float output = pidMotor1Speed.Kp * error + pidMotor1Speed.Ki * pid_integral + pidMotor1Speed.Kd * derivative;
  99. pid_last_error = error;
  100. // 限制输出防止溢出
  101. if (output > 999.0f) output = 999.0f;
  102. if (output < -999.0f) output = -999.0f;
  103. if (output >= 0)
  104. {
  105. // 正转
  106. Motor_control_ZF((uint16_t)output, 0);
  107. }
  108. else
  109. {
  110. // 反转
  111. Motor_control_ZF(0, (uint16_t)(-output));
  112. }
  113. }
  114. /*角度 + 电流双环 PID*/
  115. void Motor_Angle_Current_PID_Control(void)
  116. {
  117. float dt = 0.001f; // 5ms 控制周期
  118. float angle_actual = cur_angle_deg; // 当前角度
  119. float current_actual = Motor_cur; // 实际电流
  120. // === 外环:角度 PID,输出为目标电流 ===
  121. float current_target = PID_Realize(&angle_pid, angle_actual, dt);
  122. // === 内环:电流 PID,输出为PWM值 ===
  123. current_pid.target_val = current_target;
  124. float pwm_output = PID_Realize(&current_pid, current_actual, dt);
  125. if (pwm_output >= 0)
  126. Motor_control_ZF((uint16_t)pwm_output, 0);
  127. else
  128. Motor_control_ZF(0, (uint16_t)(-pwm_output));
  129. }
  130. // 控制电机正转
  131. void Motor_Forward(uint16_t speed)
  132. {
  133. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, speed);
  134. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
  135. }
  136. // 控制电机反转
  137. void Motor_Reverse(uint16_t speed)
  138. {
  139. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
  140. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, speed);
  141. }
  142. // 控制输出到电机
  143. void Motor_Control(float control)
  144. {
  145. uint16_t pwm = (uint16_t)fabsf(control); // 取正值作为PWM占空比
  146. if (pwm > 1000) pwm = 1000;
  147. if (control > 0)
  148. {
  149. HAL_GPIO_WritePin(GPIOB, MOTOR_EN_Pin, GPIO_PIN_SET);
  150. Motor_Forward(pwm);
  151. }
  152. else if (control < 0)
  153. {
  154. HAL_GPIO_WritePin(GPIOB, MOTOR_EN_Pin, GPIO_PIN_SET);
  155. Motor_Reverse(pwm);
  156. }
  157. else
  158. {
  159. // 停止
  160. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);
  161. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, 0);
  162. HAL_GPIO_WritePin(GPIOB, MOTOR_EN_Pin, GPIO_PIN_RESET);
  163. }
  164. }
  165. // 求最短旋转角度差(带方向)
  166. float get_shortest_angle_error(float target, float actual)
  167. {
  168. float error = target - actual;
  169. if (error > 180.0f)
  170. error -= 360.0f;
  171. else if (error < -180.0f)
  172. error += 360.0f;
  173. return error;
  174. }
  175. // 控制电机正反转
  176. void Motor_control_ZF(uint16_t forward_speed ,uint16_t reverse_speed)
  177. {
  178. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, forward_speed); //电机正转
  179. __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_4, reverse_speed); //电机反转
  180. }
  181. /////////////////////////////////////////////////
  182. /*
  183. void motor_forward(void) // 电机正转
  184. {
  185. // 电机红色线接OUT1 电机黑色线接OUT2
  186. HAL_GPIO_WritePin(GPIOB, MOTOR_EN_Pin, GPIO_PIN_SET);
  187. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
  188. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET);
  189. }
  190. void motor_rollback(void) // 电机反转
  191. {
  192. // 电机红色线接OUT1 电机黑色线接OUT2
  193. HAL_GPIO_WritePin(GPIOB, MOTOR_EN_Pin, GPIO_PIN_SET);
  194. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET); // 反转
  195. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);
  196. }
  197. void motor_stop(void) // 电机停转
  198. {
  199. // 电机红色线接OUT1 电机黑色线接OUT2
  200. HAL_GPIO_WritePin(GPIOB, MOTOR_EN_Pin, GPIO_PIN_RESET);
  201. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);// 停转
  202. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);
  203. }
  204. */