当前位置:   article > 正文

基于STM32F407VET6开发板通过Arduino进行13线霍尔编码器电机PID调速_stm32f407 arduino

stm32f407 arduino

步骤一:硬/软件准备

硬件部分:

1.STM32F407VET6开发板

2.13线霍尔编码器

3.AT8236电机驱动

4.VS code /  Platformio

5.星瞳串口波形显示器

步骤二:硬件线路连接及相关端口定义

 

 相关宏定义:

  1. #include <Arduino.h>
  2. //A电机端口定义
  3. #define Motor_A_IN1 PE9 //输入1
  4. #define Motor_A_IN2 PE11 //输入2
  5. #define Motor_A_countA PA15 //编码器A
  6. #define Motor_A_countB PB3 //编码器B
  7. //B电机端口定义
  8. #define Motor_B_IN1 PE13 //输入1
  9. #define Motor_B_IN2 PE14 //输入2
  10. #define Motor_B_countA PB4 //编码器A
  11. #define Motor_B_countB PB5 //编码器B
  12. //C电机端口定义
  13. #define Motor_C_IN1 PE5 //输入1
  14. #define Motor_C_IN2 PE6 //输入2
  15. #define Motor_C_countA PA0 //编码器A
  16. #define Motor_C_countB PA1 //编码器B
  17. //D电机端口定义
  18. #define Motor_D_IN1 PB15 //输入1
  19. #define Motor_D_IN2 PB14 //输入2
  20. #define Motor_D_countA PD12 //编码器A
  21. #define Motor_D_countB PD13 //编码器B

步骤三:相关模块函数

1.电机两输入IN1/IN2及编码器AB相中断定时器使能函数

  1. //引脚初始化
  2. void Motor_Init(){
  3. //A电机
  4. pinMode(Motor_A_IN2,OUTPUT); //驱动芯片控制引脚
  5. pinMode(Motor_A_IN1,OUTPUT); //驱动芯片控制引脚,PWM调速
  6. pinMode(Motor_A_countA,INPUT); //编码器A引脚
  7. pinMode(Motor_A_countB,INPUT); //编码器B引脚
  8. //B电机
  9. pinMode(Motor_B_IN2,OUTPUT); //驱动芯片控制引脚
  10. pinMode(Motor_B_IN1,OUTPUT); //驱动芯片控制引脚,PWM调速
  11. pinMode(Motor_B_countA,INPUT); //编码器A引脚
  12. pinMode(Motor_B_countB,INPUT); //编码器B引脚
  13. //C电机
  14. pinMode(Motor_C_IN2,OUTPUT); //驱动芯片控制引脚
  15. pinMode(Motor_C_IN1,OUTPUT); //驱动芯片控制引脚,PWM调速
  16. pinMode(Motor_C_countA,INPUT); //编码器A引脚
  17. pinMode(Motor_C_countB,INPUT); //编码器B引脚
  18. //D电机
  19. pinMode(Motor_D_IN2,OUTPUT); //驱动芯片控制引脚
  20. pinMode(Motor_D_IN1,OUTPUT); //驱动芯片控制引脚,PWM调速
  21. pinMode(Motor_D_countA,INPUT); //编码器A引脚
  22. pinMode(Motor_D_countB,INPUT); //编码器B引脚
  23. //驱动芯片控制引脚全部拉低
  24. digitalWrite(Motor_A_IN2,LOW); //A电机
  25. digitalWrite(Motor_A_IN1,LOW);
  26. digitalWrite(Motor_B_IN2,LOW); //B电机
  27. digitalWrite(Motor_B_IN1,LOW);
  28. digitalWrite(Motor_C_IN2,LOW); //C电机
  29. digitalWrite(Motor_C_IN1,LOW);
  30. digitalWrite(Motor_D_IN2,LOW); //D电机
  31. digitalWrite(Motor_D_IN1,LOW);
  32. }

2.增量式PID控制函数(ABCD电机共用)

  1. int Incremental_Pid_A(int current_speed,int target_speed){
  2. static float pwm,bias,last_bias,prev_bias; //静态变量存在程序全周期:pwm:增量输出,bias:本次偏差,last_bias:上次偏差,prev_bais_:上上次偏差
  3. bias=current_speed-target_speed; //计算本次偏差e(k)
  4. pwm-=(kp*(bias-last_bias)+ki*bias+kd*(bias-2*last_bias+prev_bias)); //增量式PID控制器
  5. prev_bias=last_bias; //保存上上次偏差
  6. last_bias=bias; //保存上一次偏差
  7. //PWM 限幅度 Arduino的PWM 最高为255 限制在250
  8. if(pwm<-250){
  9. pwm=250;
  10. }
  11. if(pwm>250){
  12. pwm=250;
  13. }
  14. //Serial.println(pwm);
  15. return pwm; //增量输出
  16. }

3.中断电机脉冲读取函数

  1. /***************************
  2. * 中断函数:读A轮脉冲
  3. *
  4. **************************/
  5. void Read_Moto_A(){
  6. motorA++;
  7. }
  8. /**************************
  9. * 中断函数:读B轮脉冲
  10. *
  11. *************************/
  12. void Read_Moto_B(){
  13. motorB++;
  14. }
  15. /**************************
  16. * 中断函数:读C轮脉冲
  17. *
  18. *************************/
  19. void Read_Moto_C(){
  20. motorC++;
  21. }
  22. /**************************
  23. * 中断函数:读D轮脉冲
  24. *
  25. *************************/
  26. void Read_Moto_D(){
  27. motorD++;
  28. }

 4.电机转速读取函数(cm/s)

  1. /***********************************
  2. * 电机实际速度计算:
  3. * 已知参数:
  4. * 车轮直径100mm,
  5. * AC轮子一圈:13*30=390脉冲(RISING)
  6. * BD轮子一圈:13*30=390脉冲(RISING)
  7. * 单位时间读两个轮子脉冲读取两个轮子脉冲
  8. ***********************************/
  9. void Read_Moto_V(){
  10. unsigned long nowtime=0;
  11. motorA=0;
  12. motorB=0;
  13. motorC=0;
  14. motorD=O;
  15. nowtime=millis()+50;//读50毫秒
  16. attachInterrupt(digitalPinToInterrupt(Motor_A_countA),Read_Moto_A,RISING);//左轮脉冲开中断计数
  17. attachInterrupt(digitalPinToInterrupt(Motor_B_countA),Read_Moto_B,RISING);//右轮脉冲开中断计数
  18. attachInterrupt(digitalPinToInterrupt(Motor_C_countA),Read_Moto_C,RISING);//左轮脉冲开中断计数
  19. attachInterrupt(digitalPinToInterrupt(Motor_D_countA),Read_Moto_D,RISING);//左轮脉冲开中断计数
  20. while(millis()<nowtime); //达到50毫秒关闭中断
  21. detachInterrupt(digitalPinToInterrupt(Motor_A_countA));//左轮脉冲关中断计数
  22. detachInterrupt(digitalPinToInterrupt(Motor_B_countA));//右轮脉冲关中断计数
  23. detachInterrupt(digitalPinToInterrupt(Motor_C_countA));//左轮脉冲关中断计数
  24. detachInterrupt(digitalPinToInterrupt(Motor_D_countA));//左轮脉冲关中断计数
  25. V_A=((motorA/390)*10*PI)/0.05; //单位cm/s
  26. V_B=((motorB/390)*10*PI)/0.05; //单位cm/s
  27. V_C=((motorC/390)*10*PI)/0.05; //单位cm/s
  28. V_D=((motorD/390)*10*PI)/0.05; //单位cm/s
  29. v1=V_A;
  30. v2=V_B;
  31. v3=V_C;
  32. v4=V_D;
  33. }

5.电机速度控制/模式选择函数函数

  1. /**************************************************************************
  2. 函数功能:设置电机工作模式和运动速度
  3. 入口参数:工作模式,pwm
  4. 返回 值:无
  5. **************************************************************************/
  6. void Set_Pwm(int mode,int speed_A,int speed_B,int speed_C,int speed_D){
  7. if(mode==1){
  8. //前进模式
  9. //A电机
  10. digitalWrite(Motor_A_IN2,LOW);
  11. analogWrite(Motor_A_IN1,speed_A);
  12. //B电机
  13. digitalWrite(Motor_B_IN2,LOW);
  14. analogWrite(Motor_B_IN1,speed_B);
  15. //C电机
  16. digitalWrite(Motor_C_IN2,LOW);
  17. analogWrite(Motor_C_IN1,speed_C);
  18. //D电机
  19. digitalWrite(Motor_D_IN2,LOW);
  20. analogWrite(Motor_D_IN1,speed_D);
  21. }else if(mode==2){
  22. //后退模式
  23. //A电机
  24. digitalWrite(Motor_A_IN2,speed_A);
  25. analogWrite(Motor_A_IN1,LOW);
  26. //B电机
  27. digitalWrite(Motor_B_IN2,speed_B);
  28. analogWrite(Motor_B_IN1,LOW);
  29. //C电机
  30. digitalWrite(Motor_A_IN2,speed_C);
  31. analogWrite(Motor_A_IN1,LOW);
  32. //D电机
  33. digitalWrite(Motor_B_IN2,speed_D);
  34. analogWrite(Motor_B_IN1,LOW);
  35. }else if(mode==3){
  36. //左旋转模式
  37. //A电机
  38. digitalWrite(Motor_A_IN2,speed_A);
  39. analogWrite(Motor_A_IN1,LOW);
  40. //B电机
  41. digitalWrite(Motor_B_IN2,LOW);
  42. analogWrite(Motor_B_IN1,speed_B);
  43. //C电机
  44. digitalWrite(Motor_C_IN2,speed_C);
  45. analogWrite(Motor_C_IN1,LOW);
  46. //D电机
  47. digitalWrite(Motor_D_IN2,LOW);
  48. analogWrite(Motor_D_IN1,speed_D);
  49. }else if(mode==4){
  50. //右旋转模式
  51. //A电机
  52. digitalWrite(Motor_A_IN2,LOW);
  53. analogWrite(Motor_A_IN1,speed_A);
  54. //B电机
  55. digitalWrite(Motor_B_IN2,speed_B);
  56. analogWrite(Motor_B_IN1,LOW);
  57. //C电机
  58. digitalWrite(Motor_C_IN2,LOW);
  59. analogWrite(Motor_C_IN1,speed_C);
  60. //D电机
  61. digitalWrite(Motor_D_IN2,speed_D);
  62. analogWrite(Motor_D_IN1,LOW);
  63. }else if(mode==5){
  64. //左平移模式
  65. //A电机
  66. digitalWrite(Motor_A_IN2,LOW);
  67. analogWrite(Motor_A_IN1,speed_A);
  68. //B电机
  69. digitalWrite(Motor_B_IN2,speed_B);
  70. analogWrite(Motor_B_IN1,LOW);
  71. //C电机
  72. digitalWrite(Motor_C_IN2,speed_C);
  73. analogWrite(Motor_C_IN1,LOW);
  74. //D电机
  75. digitalWrite(Motor_D_IN2,speed_D);
  76. analogWrite(Motor_D_IN1,LOW);
  77. }else if(mode==6){
  78. //右平移模式
  79. //A电机
  80. digitalWrite(Motor_A_IN2,speed_A);
  81. analogWrite(Motor_A_IN1,LOW);
  82. //B电机
  83. digitalWrite(Motor_B_IN2,LOW);
  84. analogWrite(Motor_B_IN1,speed_B);
  85. //C电机
  86. digitalWrite(Motor_C_IN2,LOW);
  87. analogWrite(Motor_C_IN1,speed_C);
  88. //D电机
  89. digitalWrite(Motor_D_IN2,speed_D);
  90. analogWrite(Motor_D_IN1,LOW);
  91. }
  92. }

5.PID串口调参函数

  1. //PID串口调试函数
  2. //格式:参数(kp/ki/kp) 数值
  3. //示例:ki 2.1
  4. void PID_test(){
  5. while (Serial.available() > 0) { // 串口收到字符数大于零。
  6. if(Serial.find("kp"))
  7. {
  8. kp = Serial.parseFloat();
  9. }
  10. if(Serial.find("ki"))
  11. {
  12. ki = Serial.parseFloat();
  13. }
  14. if(Serial.find("kd"))
  15. {
  16. kd = Serial.parseFloat();
  17. }
  18. }
  19. }

步骤四:整合相关模块函数

  1. #include <Arduino.h>
  2. //A电机端口定义
  3. #define Motor_A_IN1 PE9 //输入1
  4. #define Motor_A_IN2 PE11 //输入2
  5. #define Motor_A_countA PA15 //编码器A
  6. #define Motor_A_countB PB3 //编码器B
  7. //B电机端口定义
  8. #define Motor_B_IN1 PE13 //输入1
  9. #define Motor_B_IN2 PE14 //输入2
  10. #define Motor_B_countA PB4 //编码器A
  11. #define Motor_B_countB PB5 //编码器B
  12. //C电机端口定义
  13. #define Motor_C_IN1 PE5 //输入1
  14. #define Motor_C_IN2 PE6 //输入2
  15. #define Motor_C_countA PA0 //编码器A
  16. #define Motor_C_countB PA1 //编码器B
  17. //D电机端口定义
  18. #define Motor_D_IN1 PB14 //输入1
  19. #define Motor_D_IN2 PB15 //输入2
  20. #define Motor_D_countA PD12 //编码器A
  21. #define Motor_D_countB PD13 //编码器B
  22. //定义相关变量
  23. volatile float motorA=0;//中断变量,A轮子脉冲计数
  24. volatile float motorB=0;//中断变量,B轮子脉冲计数
  25. volatile float motorC=0;//中断变量,C轮子脉冲计数
  26. volatile float motorD=0;//中断变量,D轮子脉冲计数
  27. float V_A=0; //A轮速度 单位cm/s
  28. float V_B=0; //B边轮速 单位cm/s
  29. float V_C=0; //C轮速度 单位cm/s
  30. float V_D=0; //D轮速度 单位cm/s
  31. int v1=0; //单位cm/s
  32. int v2=0; //单位cm/s
  33. int v3=0;
  34. int v4=0;
  35. float Target_V_A=40,Target_V_B=40,Target_V_C=40,Target_V_D=40; //单位cm/s 经过测试最大速度为 :150 cm/s
  36. int Pwm_A=0,Pwm_B=0,Pwm_C=0,Pwm_D=0 ; //左右轮PWM
  37. //PID变量(根据个人情况调试)
  38. float kp=1,ki=0.15,kd=0; //PID参数
  39. //函数声明
  40. void Motor_Init();//电机初始化
  41. void Read_Moto_V();//读取电机速度 单位:cm/s
  42. void Read_Moto_A(); //读取编码器脉冲
  43. void Read_Moto_B();
  44. void Read_Moto_C();
  45. void Read_Moto_D();
  46. void Set_Pwm(int mode,int speed_A,int speed_B,int speed_C,int speed_D);//pwm设置
  47. int Incremental_Pid_A(int current_speed,int target_speed);//pid函数
  48. int Incremental_Pid_B(float current_speed,float target_speed);
  49. int Incremental_Pid_C(float current_speed,float target_speed);
  50. int Incremental_Pid_D(float current_speed,float target_speed);
  51. void PID_test();//离线kp ki kd 调试
  52. /**************************************
  53. * //Arduino初始化函数
  54. *************************************/
  55. void setup() {
  56. Motor_Init();//电机端口初始化
  57. Serial.begin(9600);//开启串口
  58. }
  59. /***************************************
  60. * Arduino主循环
  61. *
  62. ***************************************/
  63. void loop() {
  64. Read_Moto_V();//读取脉冲计算速度
  65. Pwm_A=Incremental_Pid_A(V_A,Target_V_A);//A轮PI运算
  66. Pwm_B=Incremental_Pid_B(V_B,Target_V_B);//B轮PI运算
  67. Pwm_C=Incremental_Pid_C(V_C,Target_V_C);//C轮PI运算
  68. Pwm_D=Incremental_Pid_D(V_D,Target_V_D);//D轮PI运算
  69. Serial.print("V_A: ");
  70. Serial.print(V_A);
  71. Serial.print("cm/s, V_B: ");
  72. Serial.print(V_B);
  73. Serial.print("cm/s, V_C: ");
  74. Serial.print(V_C);
  75. Serial.print("cm/s, V_D: ");
  76. Serial.print(V_D);
  77. Serial.println("cm/s");
  78. Set_Pwm(1,Pwm_A,Pwm_B,Pwm_C,Pwm_D); //设置速度
  79. // PID_test();//调试参数
  80. }
  81. /*********************************************************
  82. * 函数功能:增量式PI控制器(A电机)
  83. * 入口参数:当前速度(编码器测量值),目标速度
  84. * 返回 值:电机PWM
  85. * 参考资料:
  86. * 增量式离散PID公式:
  87. * Pwm-=Kp*[e(k)-e(k-1)]+Ki*e(k)+Kd*[e(k)-2e(k-1)+e(k-2)]
  88. * e(k):本次偏差
  89. * e(k-1):上一次偏差
  90. * e(k-2):上上次偏差
  91. * Pwm:代表增量输出
  92. * 在速度闭环控制系统里面我们只使用PI控制,因此对PID公式可简化为:
  93. * Pwm-=Kp*[e(k)-e(k-1)]+Ki*e(k)
  94. * e(k):本次偏差
  95. * e(k-1):上一次偏差
  96. * Pwm:代表增量输出
  97. *
  98. * 注意增量式PID先调I,再调P,最后再调D
  99. *********************************************************/
  100. int Incremental_Pid_A(int current_speed,int target_speed){
  101. static float pwm,bias,last_bias,prev_bias; //静态变量存在程序全周期:pwm:增量输出,bias:本次偏差,last_bias:上次偏差,prev_bais_:上上次偏差
  102. bias=current_speed-target_speed; //计算本次偏差e(k)
  103. pwm-=(kp*(bias-last_bias)+ki*bias+kd*(bias-2*last_bias+prev_bias)); //增量式PID控制器
  104. prev_bias=last_bias; //保存上上次偏差
  105. last_bias=bias; //保存上一次偏差
  106. //PWM 限幅度 Arduino的PWM 最高为255 限制在250
  107. if(pwm<-250){
  108. pwm=250;
  109. }
  110. if(pwm>250){
  111. pwm=250;
  112. }
  113. //Serial.println(pwm);
  114. return pwm; //增量输出
  115. }
  116. //B电机速度增量式PID控制器
  117. int Incremental_Pid_B(float current_speed,float target_speed){
  118. static float pwm,bias,last_bias,prev_bias; //静态变量存在程序全周期:pwm:增量输出,bias:本次偏差,last_bias:上次偏差,prev_bais_:上上次偏差
  119. bias=current_speed-target_speed; //计算本次偏差e(k)
  120. pwm-=(kp*(bias-last_bias)+ki*bias+kd*(bias-2*last_bias+prev_bias)); //增量式PID控制器
  121. prev_bias=last_bias; //保存上上次偏差
  122. last_bias=bias; //保存上一次偏差
  123. //PWM 限幅度 Arduino的PWM 最高为255限制在250
  124. if(pwm<-250){
  125. pwm=250;
  126. }
  127. if(pwm>250){
  128. pwm=250;
  129. }
  130. //Serial.println(pwm);
  131. return pwm; //增量输出
  132. }
  133. //C电机速度增量式PID控制器
  134. int Incremental_Pid_C(float current_speed,float target_speed){
  135. static float pwm,bias,last_bias,prev_bias; //静态变量存在程序全周期:pwm:增量输出,bias:本次偏差,last_bias:上次偏差,prev_bais_:上上次偏差
  136. bias=current_speed-target_speed; //计算本次偏差e(k)
  137. pwm-=(kp*(bias-last_bias)+ki*bias+kd*(bias-2*last_bias+prev_bias)); //增量式PID控制器
  138. prev_bias=last_bias; //保存上上次偏差
  139. last_bias=bias; //保存上一次偏差
  140. //PWM 限幅度 Arduino的PWM 最高为255限制在250
  141. if(pwm<-250){
  142. pwm=250;
  143. }
  144. if(pwm>250){
  145. pwm=250;
  146. }
  147. //Serial.println(pwm);
  148. return pwm; //增量输出
  149. }
  150. //D电机速度增量式PID控制器
  151. int Incremental_Pid_D(float current_speed,float target_speed){
  152. static float pwm,bias,last_bias,prev_bias; //静态变量存在程序全周期:pwm:增量输出,bias:本次偏差,last_bias:上次偏差,prev_bais_:上上次偏差
  153. bias=current_speed-target_speed; //计算本次偏差e(k)
  154. pwm-=(kp*(bias-last_bias)+ki*bias+kd*(bias-2*last_bias+prev_bias)); //增量式PID控制器
  155. prev_bias=last_bias; //保存上上次偏差
  156. last_bias=bias; //保存上一次偏差
  157. //PWM 限幅度 Arduino的PWM 最高为255限制在250
  158. if(pwm<-250){
  159. pwm=250;
  160. }
  161. if(pwm>250){
  162. pwm=250;
  163. }
  164. //Serial.println(pwm);
  165. return pwm; //增量输出
  166. }
  167. /**************************************************************************
  168. 函数功能:设置电机工作模式和运动速度
  169. 入口参数:工作模式,pwm
  170. 返回 值:无
  171. **************************************************************************/
  172. void Set_Pwm(int mode,int speed_A,int speed_B,int speed_C,int speed_D){
  173. if(mode==1){
  174. //前进模式
  175. //A电机
  176. digitalWrite(Motor_A_IN2,LOW);
  177. analogWrite(Motor_A_IN1,speed_A);
  178. //B电机
  179. digitalWrite(Motor_B_IN2,LOW);
  180. analogWrite(Motor_B_IN1,speed_B);
  181. //C电机
  182. digitalWrite(Motor_C_IN2,LOW);
  183. analogWrite(Motor_C_IN1,speed_C);
  184. //D电机
  185. digitalWrite(Motor_D_IN2,LOW);
  186. analogWrite(Motor_D_IN1,speed_D);
  187. }else if(mode==2){
  188. //后退模式
  189. //A电机
  190. digitalWrite(Motor_A_IN2,speed_A);
  191. analogWrite(Motor_A_IN1,LOW);
  192. //B电机
  193. digitalWrite(Motor_B_IN2,speed_B);
  194. analogWrite(Motor_B_IN1,LOW);
  195. //C电机
  196. digitalWrite(Motor_A_IN2,speed_C);
  197. analogWrite(Motor_A_IN1,LOW);
  198. //D电机
  199. digitalWrite(Motor_B_IN2,speed_D);
  200. analogWrite(Motor_B_IN1,LOW);
  201. }else if(mode==3){
  202. //左旋转模式
  203. //A电机
  204. digitalWrite(Motor_A_IN2,speed_A);
  205. analogWrite(Motor_A_IN1,LOW);
  206. //B电机
  207. digitalWrite(Motor_B_IN2,LOW);
  208. analogWrite(Motor_B_IN1,speed_B);
  209. //C电机
  210. digitalWrite(Motor_C_IN2,speed_C);
  211. analogWrite(Motor_C_IN1,LOW);
  212. //D电机
  213. digitalWrite(Motor_D_IN2,LOW);
  214. analogWrite(Motor_D_IN1,speed_D);
  215. }else if(mode==4){
  216. //右旋转模式
  217. //A电机
  218. digitalWrite(Motor_A_IN2,LOW);
  219. analogWrite(Motor_A_IN1,speed_A);
  220. //B电机
  221. digitalWrite(Motor_B_IN2,speed_B);
  222. analogWrite(Motor_B_IN1,LOW);
  223. //C电机
  224. digitalWrite(Motor_C_IN2,LOW);
  225. analogWrite(Motor_C_IN1,speed_C);
  226. //D电机
  227. digitalWrite(Motor_D_IN2,speed_D);
  228. analogWrite(Motor_D_IN1,LOW);
  229. }else if(mode==5){
  230. //左平移模式
  231. //A电机
  232. digitalWrite(Motor_A_IN2,LOW);
  233. analogWrite(Motor_A_IN1,speed_A);
  234. //B电机
  235. digitalWrite(Motor_B_IN2,speed_B);
  236. analogWrite(Motor_B_IN1,LOW);
  237. //C电机
  238. digitalWrite(Motor_C_IN2,speed_C);
  239. analogWrite(Motor_C_IN1,LOW);
  240. //D电机
  241. digitalWrite(Motor_D_IN2,speed_D);
  242. analogWrite(Motor_D_IN1,LOW);
  243. }else if(mode==6){
  244. //右平移模式
  245. //A电机
  246. digitalWrite(Motor_A_IN2,speed_A);
  247. analogWrite(Motor_A_IN1,LOW);
  248. //B电机
  249. digitalWrite(Motor_B_IN2,LOW);
  250. analogWrite(Motor_B_IN1,speed_B);
  251. //C电机
  252. digitalWrite(Motor_C_IN2,LOW);
  253. analogWrite(Motor_C_IN1,speed_C);
  254. //D电机
  255. digitalWrite(Motor_D_IN2,speed_D);
  256. analogWrite(Motor_D_IN1,LOW);
  257. }
  258. }
  259. //引脚初始化
  260. void Motor_Init(){
  261. //A电机
  262. pinMode(Motor_A_IN2,OUTPUT); //驱动芯片控制引脚
  263. pinMode(Motor_A_IN1,OUTPUT); //驱动芯片控制引脚,PWM调速
  264. pinMode(Motor_A_countA,INPUT); //编码器A引脚
  265. pinMode(Motor_A_countB,INPUT); //编码器B引脚
  266. //B电机
  267. pinMode(Motor_B_IN2,OUTPUT); //驱动芯片控制引脚
  268. pinMode(Motor_B_IN1,OUTPUT); //驱动芯片控制引脚,PWM调速
  269. pinMode(Motor_B_countA,INPUT); //编码器A引脚
  270. pinMode(Motor_B_countB,INPUT); //编码器B引脚
  271. //C电机
  272. pinMode(Motor_C_IN2,OUTPUT); //驱动芯片控制引脚
  273. pinMode(Motor_C_IN1,OUTPUT); //驱动芯片控制引脚,PWM调速
  274. pinMode(Motor_C_countA,INPUT); //编码器A引脚
  275. pinMode(Motor_C_countB,INPUT); //编码器B引脚
  276. //D电机
  277. pinMode(Motor_D_IN2,OUTPUT); //驱动芯片控制引脚
  278. pinMode(Motor_D_IN1,OUTPUT); //驱动芯片控制引脚,PWM调速
  279. pinMode(Motor_D_countA,INPUT); //编码器A引脚
  280. pinMode(Motor_D_countB,INPUT); //编码器B引脚
  281. //驱动芯片控制引脚全部拉低
  282. digitalWrite(Motor_A_IN2,LOW); //A电机
  283. digitalWrite(Motor_A_IN1,LOW);
  284. digitalWrite(Motor_B_IN2,LOW); //B电机
  285. digitalWrite(Motor_B_IN1,LOW);
  286. digitalWrite(Motor_C_IN2,LOW); //C电机
  287. digitalWrite(Motor_C_IN1,LOW);
  288. digitalWrite(Motor_D_IN2,LOW); //D电机
  289. digitalWrite(Motor_D_IN1,LOW);
  290. }
  291. /***********************************
  292. * 电机实际速度计算:
  293. * 已知参数:
  294. * 车轮直径100mm,
  295. * 左边轮子一圈:13*30=390脉冲(RISING)
  296. * 右边轮子一圈:13*30=390脉冲(RISING)
  297. * 单位时间读两个轮子脉冲读取两个轮子脉冲
  298. ***********************************/
  299. void Read_Moto_V(){
  300. unsigned long nowtime=0;
  301. motorA=0;
  302. motorB=0;
  303. motorC=0;
  304. motorD=0;
  305. nowtime=millis()+50;//读50毫秒
  306. attachInterrupt(digitalPinToInterrupt(Motor_A_countA),Read_Moto_A,RISING);//A轮脉冲开中断计数
  307. attachInterrupt(digitalPinToInterrupt(Motor_B_countA),Read_Moto_B,RISING);//B轮脉冲开中断计数
  308. attachInterrupt(digitalPinToInterrupt(Motor_C_countA),Read_Moto_C,RISING);//C轮脉冲开中断计数
  309. attachInterrupt(digitalPinToInterrupt(Motor_D_countA),Read_Moto_D,RISING);//D轮脉冲开中断计数
  310. while(millis()<nowtime); //达到50毫秒关闭中断
  311. detachInterrupt(digitalPinToInterrupt(Motor_A_countA));//A轮脉冲关中断计数
  312. detachInterrupt(digitalPinToInterrupt(Motor_B_countA));//B轮脉冲关中断计数
  313. detachInterrupt(digitalPinToInterrupt(Motor_C_countA));//C轮脉冲关中断计数
  314. detachInterrupt(digitalPinToInterrupt(Motor_D_countA));//D轮脉冲关中断计数
  315. V_A=((motorA/390)*10*PI)/0.05; //单位cm/s
  316. V_B=((motorB/390)*10*PI)/0.05; //单位cm/s
  317. V_C=((motorC/390)*10*PI)/0.05; //单位cm/s
  318. V_D=((motorD/390)*10*PI)/0.05; //单位cm/s
  319. v1=V_A;
  320. v2=V_B;
  321. v3=V_C;
  322. v4=V_D;
  323. }
  324. /***************************
  325. * 中断函数:读A轮脉冲
  326. *
  327. **************************/
  328. void Read_Moto_A(){
  329. motorA++;
  330. }
  331. /**************************
  332. * 中断函数:读B轮脉冲
  333. *
  334. *************************/
  335. void Read_Moto_B(){
  336. motorB++;
  337. }
  338. /**************************
  339. * 中断函数:读B轮脉冲
  340. *
  341. *************************/
  342. void Read_Moto_C(){
  343. motorC++;
  344. }
  345. /**************************
  346. * 中断函数:读B轮脉冲
  347. *
  348. *************************/
  349. void Read_Moto_D(){
  350. motorD++;
  351. }
  352. //PID串口调试函数
  353. //格式:参数(kp/ki/kp) 数值
  354. //示例:ki 2.1
  355. void PID_test(){
  356. while (Serial.available() > 0) { // 串口收到字符数大于零。
  357. if(Serial.find("kp"))
  358. {
  359. kp = Serial.parseFloat();
  360. }
  361. if(Serial.find("ki"))
  362. {
  363. ki = Serial.parseFloat();
  364. }
  365. if(Serial.find("kd"))
  366. {
  367. kd = Serial.parseFloat();
  368. }
  369. }
  370. }

步骤五:具体PID调参过程(雾)

本人pid调参过程极其痛苦,很久才发现方向错误,所以本人不想经历第二次调参过程,所以没有相应过程图片,可以参考一下最后调参完成的波形:

不过下面给大家一些过来人的建议:

对于增量式pid调参,尤其是对于13线霍尔编码器,首先调ki,尽量选择10附近的值采用二分法测量,测量过程对于变化较大的波形应及时舍去,当波形满足略微振荡,在调整时间t_s内调整次数在3-5次可以确保调整时间t_s较小,而最大超调量M_p也较小。接着调节kp,这个主要影响其稳定性,可以从10左右的ki开始下调,直至M_p基本等于零,这样就基本完成pi调试,最后kd我的结果为0,查阅相关资料后,发现大部分情况低精度速度增量编码器很难会用到kd,所以大家参考我这种应用场景就可以忽略。

最后祝大家早日找到属于你的kp和ki!(完结撒花)

步骤六:特别鸣谢up

 cbirdfly.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/713355
推荐阅读
相关标签
  

闽ICP备14008679号