当前位置:   article > 正文

四轮两驱小车(四):STM32驱动5路灰度传感器PID循迹_五路灰度循迹

五路灰度循迹

目录

前言:

小车效果展示:

5路数字灰度传感器:

巡线思路:

加入PID调节的代码:


前言:

        之前买了一批5路灰度传感器,想用这传感器进行循迹,无奈网上和官方的资料提供的还是比较少,这里还是做一下当初的学习记录。

小车效果展示:

STM32RCT6主控,5路灰度寻迹,超声波HC_SR04中断式测距,蓝牙模块HC_08通信,AS4950电机驱动芯片,减缓了MPU6050零漂问题,PID丝滑_哔哩哔哩_bilibili

5路数字灰度传感器:

         这是某宝上买的5路灰度传感器,价格稍微有点贵,50多块一个。当然,一分钱一分货,这个模块可以用小螺丝刀来调节传感器上面的旋钮,通过这个旋钮来调节灵敏度,这个灵敏度调节好了的话可以识别黑白循迹、红白循迹。所以还是比较值得的。

        对于这款5路数字灰度传感器来说。识别到黑线,传回来的数字量就是0,识别到白色,传回来的数字量就是1。

巡线思路:

        博主想着用这5路的中间三路来巡线,用最左和最右端的传感器用来识别十字或者丁字路口,巡线时,加入PID算法,遇到十字或者丁字路口就用最左和最右的传感器来识别,识别到了之后,我们就可以搭配MPU6050进行转90°弯了。

加入PID调节的代码:

        其中 sensor_bias 是根据中间三路传感器和黑线的相对位置来估计出的误差(如果你要问我怎么得来的,其实这个数据大差不差就行,它只是为PID服务的一个变量罢了,甚至你可以把62.5改成50,最后只要调好PID三个参数,达到的效果是一样的),这里的decide类似于状态机的信号,我令decide为6的时候,也就是小车跑出了黑线,小车停止。

  1. #include "sensor.h"
  2. #include "stm32f10x.h"
  3. #include "move.h"
  4. #include "motor.h"
  5. #include "FSM.h"
  6. //STEER4 --> PA11 --> R2 红线
  7. //STEER3 --> PC9 --> R1 橘线
  8. // --> PB4 --> M0 黄线
  9. //STEER1 --> PA6 --> L1 绿线
  10. //ENCODE1_A --> PB5 --> L2 棕线
  11. float Kp_sensor = 8.134, Ki_sensor = 0.021, Kd_sensor = 2.36;//pid弯道参数参数
  12. float sensor_bias = 0;
  13. float sensor_bias_last = 0;
  14. float P = 0, I = 0, D = 0, PID_value = 0; //pid直道参数
  15. int decide;
  16. unsigned char move_flag;
  17. extern unsigned char FSM_state;
  18. void sensor_Init()
  19. {
  20. GPIO_InitTypeDef GPIO_InitStructure;
  21. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//开启C时钟 PC9
  22. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  23. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  24. //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//这句话其实可以不用,在使用输入功能时,不需要配置频率
  25. GPIO_Init(GPIOC, &GPIO_InitStructure);
  26. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启A时钟 PA11 PA6
  27. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  28. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_6;
  29. GPIO_Init(GPIOA, &GPIO_InitStructure);
  30. GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST, ENABLE);
  31. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启B时钟 PB4 PB5
  32. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  33. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;
  34. GPIO_Init(GPIOB, &GPIO_InitStructure);
  35. }
  36. unsigned char times;
  37. extern unsigned char FSM_hc08;
  38. unsigned char back_flag;
  39. unsigned char one_time;
  40. unsigned char one_flag;
  41. unsigned char channel_num;//channel的存在导致发送2号通道的时候只会进入一次
  42. void sensor_read()
  43. {
  44. if((L2 == 1)&&(L1 == 1)&&(M0 == 1)&&(R1 == 0))// 1 1 1 0
  45. {
  46. if(one_time == 0)
  47. {
  48. if(FSM_hc08 == Channel_1)
  49. {
  50. FSM_state = Turn_lift_state;//跳出循环,将PID分别清零。
  51. one_time++;
  52. P = 0;I = 0; D = 0;
  53. }
  54. else if(FSM_hc08 == Channel_2)
  55. {
  56. if(one_flag == 0)
  57. {
  58. channel_num++;
  59. one_flag = 1;
  60. }
  61. if(channel_num == 2)
  62. {
  63. FSM_state = stay2_state;//跳出循环,将PID分别清零。
  64. one_time++;
  65. P = 0;I = 0; D = 0;
  66. }
  67. }
  68. }
  69. }
  70. else if((L1 == 0)&&(M0 == 1)&&(R1 == 0))// 0 1 0
  71. {
  72. sensor_bias = 0;decide = 3;one_flag = 0;//积分项清零
  73. }
  74. else if((L1 == 1)&&(M0 == 1)&&(R1 == 0))// 1 1 0
  75. {
  76. sensor_bias = -62.5;decide = 2;
  77. }
  78. else if((L1 == 0)&&(M0 == 1)&&(R1 == 1))// 0 1 1
  79. {
  80. sensor_bias = 62.5;decide = 2;
  81. }
  82. else if((L1 == 1)&&(M0 == 0)&&(R1 == 0))// 1 0 0
  83. {
  84. sensor_bias = -125;decide = 4;
  85. }
  86. else if((L1 == 0)&&(M0 == 0)&&(R1 == 1))// 0 0 1
  87. {
  88. sensor_bias = 62.5;decide = 4;
  89. }
  90. else if((L1 == 0)&&(M0 == 0)&&(R1 == 0))// 0 0 0
  91. {
  92. decide = 6;
  93. }
  94. else if((L1 == 1)&&(M0 == 1)&&(R1 == 1))// 1 1 1
  95. {
  96. decide = 6;FSM_state = Judge_state; //如果读取到了整条黑线,那么就进入下一状态
  97. if(back_flag == 1)
  98. {
  99. FSM_state = Back_state;
  100. back_flag = 0;
  101. } //第一次识别到全黑线为小车停止线。第二次识别到,代表小车即将回归循迹
  102. }
  103. }
  104. void Sensor_pid()
  105. {
  106. if(decide<=5)
  107. {
  108. P = sensor_bias;
  109. I = I + sensor_bias;
  110. D = sensor_bias-sensor_bias_last;
  111. PID_value = Kp_sensor*P + Ki_sensor*I + Kd_sensor*D;
  112. sensor_bias_last = sensor_bias;
  113. //对积分值设置一个限制,防止积分值超标
  114. if(I >=3500)I = 3500;
  115. if(I <= -3500)I = -3500;
  116. PWM_value_R = 2099 - (int)PID_value;
  117. PWM_value_L = 2099 + (int)PID_value;//当线在左,左轮要慢,右轮要快,左轮要加,右轮要减,但这里的偏差是负值
  118. Motor3_forward(PWM_value_R);
  119. Motor4_forward(PWM_value_L);
  120. //4 --> 右电机
  121. //3 --> 左电机
  122. }
  123. else{
  124. Move_stop();
  125. }
  126. }

        对应的头文件部分

  1. #ifndef __SENSOR_H
  2. #define __SENSOR_H
  3. //STEER4 --> PA11 --> R2 绿线
  4. //STEER3 --> PC9 --> R1 黄线
  5. // B --> PB6 --> M0 橘线
  6. //STEER1 --> PA6 --> L1 红线
  7. // A --> PB7 --> L2 白线
  8. // 灰度传感器,当传感器识别到黑线的时候,输出为1,其余时刻输出为0
  9. // 所以在这里我们要使用下拉输入
  10. #define L2 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)
  11. #define L1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)
  12. #define M0 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_4)
  13. #define R1 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_9)
  14. #define R2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_11)
  15. void sensor_Init(void);
  16. void sensor_read(void);
  17. void Sensor_pid(void);
  18. #endif

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

闽ICP备14008679号