当前位置:   article > 正文

大一萌新の作品:红外寻迹模块做跟随小车之没有I的极简PID算法_红外循迹小车pid算法

红外循迹小车pid算法

(纯萌新,学习单片机半年了,这是寒假回家的作品,师从江科大,写博客纪录我实现后的经验)(比较粗略)

前言:

因为没买超声波避障模块,只能勉强一下用红外寻迹做一个类似的小车。

问题很多:光线会干扰读取到的AD值,且难以设置详细的距离,只能设置大概距离;碍于萌新我不会PID算法的I算法的编程,以及暂时无法读取电机的转苏,做不出内环,只能勉强做一个只有P,D的PID跟随小车,但实现基本功能是绰绰有余的;本文只用了一个模块,所以只能直线,如果要做到转弯等功能,可以三个模块再用简单的if语句就像寻迹小车一样即可。

目标:

  1. 能够使用单片机读取红外模块的AD值

  1. 写简单的没有I的PID算法,实现比较稳定的简单跟踪

  1. 写main函数结合上述目标

接下来分析做该项目的思路:

首先要解决读取红外模块的数值,红外模块有四根接口,其中AO是读取具体电压值的口,DO是只输出0/1的口。所以接AO。用AD的代码即可读取其值。当其遇见不反光的面时,会输出很高的AD值,反之为低。使用AD的原因是如果用DO口,只能识别有无,但是没法控制距离。

其次是PID的算法,萌新我实力有限,只能写没有I的PID算法博君一笑了。P指的是跟随比例变化电机的转速,D指的是能接收的最终误差。具体可以看其他大佬的PID讲解,很详细,但是我暂时没能将其完全写成自己的代码。

最后就是通过PID算法获知应该输入给电机的转速了,大概思路就是如此。

解决&源码:

首先是AD读取,这里建议观看江科大老师的stm32教程,很容易上手的代码(比较重要的部分在注释中已经标明。ps.标注释真是个好习惯)。

  1. #include "stm32f10x.h" // Device header
  2. #include "AD.h"
  3. void AD_Init(void)
  4. {
  5. RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); //打开ADC
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
  7. RCC_ADCCLKConfig(RCC_PCLK2_Div6); //打开ADCCLK的6分频
  8. GPIO_InitTypeDef GPIO_InitStructure;
  9. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //专属ADC的模式捏
  10. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
  11. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12. GPIO_Init(GPIOB, &GPIO_InitStructure);
  13. //结构体初始化ADC
  14. ADC_InitTypeDef ADC_InitStructure;
  15. ADC_InitStructure.ADC_Mode= ADC_Mode_Independent; //ADC1单打模式!
  16. ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right ; //右对齐就欧克啦
  17. ADC_InitStructure.ADC_ExternalTrigConv= ADC_ExternalTrigConv_None; //只用软件触发啦
  18. ADC_InitStructure.ADC_ContinuousConvMode=DISABLE ; //连续转换模式(ENABLE)
  19. ADC_InitStructure.ADC_NbrOfChannel= 1; //通道数目
  20. ADC_InitStructure.ADC_ScanConvMode= DISABLE; //扫描模式 看江科大啦
  21. ADC_Init(ADC1,&ADC_InitStructure);
  22. ADC_Cmd(ADC1,ENABLE); //ADC准备就绪捏
  23. //但是我们要校准呢
  24. ADC_ResetCalibration(ADC1);
  25. while(ADC_GetResetCalibrationStatus(ADC1)==SET); //没校准开始给我站在这里
  26. ADC_StartCalibration(ADC1);
  27. while(ADC_GetCalibrationStatus(ADC1)==SET); //等待校准完成捏
  28. ADC_SoftwareStartConvCmd(ADC1,ENABLE);
  29. }
  30. uint16_t AD_GetValue_D(void)
  31. {
  32. ADC_SoftwareStartConvCmd(ADC1,ENABLE); //连续触发可放在上面,这样也不需要等到转化完成啦↓
  33. while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET); //转换完成变成1就退出啦
  34. return ADC_GetConversionValue(ADC1); //因为读取后自动清除标志位,所以不用清除标志位啦
  35. }
  36. //若是连续触发模式,可以将软件触发的函数挪到初始化的最后,只需要触发一次即可~
  37. uint16_t AD_GetValue_E(void) //这个就是连续转换用的函数啦
  38. {
  39. return ADC_GetConversionValue(ADC1);
  40. }
  41. uint16_t AD_GetValue(uint8_t ADC_Channel)
  42. {
  43. ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_55Cycles5);
  44. ADC_SoftwareStartConvCmd(ADC1,ENABLE); //连续触发可放在上面,这样也不需要等到转化完成啦↓
  45. while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET); //转换完成变成1就退出啦
  46. return ADC_GetConversionValue(ADC1); //因为读取后自动清除标志位,所以不用清除标志位啦
  47. }

然后是PID

  1. #include "stm32f10x.h" // Device header
  2. #include "AD.h"
  3. void PID_Init(void)
  4. {
  5. AD_Init();
  6. }
  7. float PID(uint16_t Aim,uint16_t D)        //Aim是目标,D是误差
  8. {
  9. uint16_t Now;
  10. float Speed=0;
  11. Now=AD_GetValue(ADC_Channel_8); //假如3500是目标,50是误差,则可以计算具体比例
  12. if(Now<(Aim-D))
  13. {
  14. Speed=((Now-Aim)/70)-50;
  15. return(Speed); //返回的速度
  16. }
  17. else if(Now>(Aim+D))
  18. {
  19. Speed=((Now-Aim)/7)+30;
  20. return(Speed);
  21. }
  22. else {return 0;}
  23. }

最后是main代码

  1. #include "stm32f10x.h"
  2. #include "Delay.h"
  3. #include "Motor.h"
  4. #include "PID.h"
  5. #include "OLED.h"
  6. #include "AD.h" // Device header
  7. int main(void) //电机范围-100~100
  8. {
  9. float Speed;
  10. Motor_Init();
  11. PID_Init();
  12. OLED_Init();
  13. while(1)
  14. {
  15. Speed=PID(3500,75);
  16. Motor_L_SetSpeed(Speed);
  17. Motor_R_SetSpeed(Speed);
  18. OLED_ShowNum(1,1,Speed+100,3);
  19. OLED_ShowNum(2,1,AD_GetValue(ADC_Channel_8),4);
  20. }
  21. }

尾声:

本次作品的实现,让我提前适应了超声波避障的思路,便于之后的继续学习和研究。自己编写极其简单的PID算法也让我知道了许多算法的精妙之处,适应算法的难度。这是学习路上一个避不开的坎,努力坚持下去,终会有成果的。

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

闽ICP备14008679号