当前位置:   article > 正文

【STM32+OPENMV】二维云台颜色识别及追踪_匿名openmv色块追踪

匿名openmv色块追踪

一、准备工作

有关OPENMV最大色块追踪及与STM32通信内容,详情见【STM32+HAL】与OpenMV通信

有关七针OLED屏显示内容,详情见【STM32+HAL】七针OLED(SSD1306)配置(SPI版)

二、所用工具

1、芯片:STM32F407ZGT6

2、CUBEMX配置软件

3、KEIL5

4、OPENMV

三、实现功能

二维云台追踪最大色块,并显示中心x,y坐标至OLED

四、HAL配置步骤

1、生成两路PWM波控制舵机

周期为20ms

2、中断配置

五、KEIL填写代码

1、ptz.c
  1. #include "ptz.h"
  2. #include "string.h"
  3. #include "stdio.h"
  4. #include "stdlib.h"
  5. #include "main.h"
  6. #include "tim.h"
  7. #include "usart.h"
  8. #define RXBUFFERSIZE 256
  9. #define CCR_UD TIM2->CCR2 //up and down.... RANGE:420-2000
  10. #define CCR_LR TIM2->CCR3 //Left and Right.... RANGE:420-2500
  11. #define Cen_x 160 //x轴中心坐标值
  12. #define Cen_y 120 //y轴中心坐标值
  13. #define sp1 7 //x轴速度
  14. #define sp2 6 //y轴速度
  15. #define range 40 //识别范围
  16. char RxBuffer[RXBUFFERSIZE],rx_buf[RXBUFFERSIZE];
  17. uint8_t aRxBuffer;
  18. uint8_t Uart1_Rx_Cnt = 0;
  19. int cnt_rx=0,cnt_dt=0;
  20. int cx=0,cy=0;
  21. void Tilt(void)
  22. {
  23. if(cx < (Cen_x-range)) CCR_LR = (CCR_LR>2450)?2450:CCR_LR+sp1;
  24. else if (cx > (Cen_x+range)) CCR_LR = (CCR_LR<450)?450:CCR_LR -sp1;
  25. else CCR_LR= CCR_LR;
  26. if(cy < (Cen_y-range)) CCR_UD = (CCR_UD<420)?420:CCR_UD -sp2;
  27. else if (cy > (Cen_y+range)) CCR_UD = (CCR_UD>1800)?1800:CCR_UD+sp2;
  28. else CCR_UD= CCR_UD;
  29. }
  30. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  31. {
  32. UNUSED(huart);
  33. if(huart==&huart2){
  34. RxBuffer[Uart1_Rx_Cnt] = aRxBuffer;
  35. Uart1_Rx_Cnt++;
  36. if((RxBuffer[Uart1_Rx_Cnt-1] == 0xb3)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0xb3)) cnt_rx=1; //帧头判定
  37. else if((RxBuffer[Uart1_Rx_Cnt-2] == 0x0d)&&(RxBuffer[Uart1_Rx_Cnt-1] == 0x0a)) cnt_rx=2; //帧尾判定
  38. else cnt_rx=0;
  39. switch (cnt_rx)
  40. {
  41. case 1:
  42. Uart1_Rx_Cnt = 0;
  43. memset(RxBuffer,0x00,sizeof(RxBuffer));
  44. break;
  45. case 2:
  46. RxBuffer[Uart1_Rx_Cnt-1] = '\0';
  47. RxBuffer[Uart1_Rx_Cnt-2] = '\0';
  48. strcpy(rx_buf,RxBuffer);
  49. int st=0; //有效数值开始位置
  50. cnt_dt=0; //空格数
  51. for(int i=0;rx_buf[i];i++){
  52. if(cnt_dt==4) break;
  53. if(rx_buf[i]==' ') {
  54. cnt_dt++;
  55. int temp=0;
  56. for(int j=st;j<i;j++)
  57. temp=temp*10+(rx_buf[j]-'0');
  58. switch (cnt_dt){
  59. case 1:cx=temp;break;
  60. case 2:cy=temp;break;
  61. }
  62. st=i+1;
  63. }
  64. }
  65. while(HAL_UART_GetState(&huart2) == HAL_UART_STATE_BUSY_TX);
  66. Uart1_Rx_Cnt = 0;
  67. memset(RxBuffer,0x00,sizeof(RxBuffer));
  68. break;
  69. default:break;
  70. }
  71. HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);
  72. }
  73. }

2、main.c
  1. /* USER CODE BEGIN 2 */
  2. OLED_Init();
  3. HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);
  4. TIM2->CCR2 = 420-1;
  5. TIM2->CCR3 = 1400-1;
  6. HAL_TIM_PWM_Start (&htim2, TIM_CHANNEL_2);
  7. HAL_TIM_PWM_Start (&htim2, TIM_CHANNEL_3);
  8. /* USER CODE END 2 */
  9. /* Infinite loop */
  10. /* USER CODE BEGIN WHILE */
  11. while (1)
  12. {
  13. OLED_ShowNum(30,20,cx,3,16);
  14. OLED_ShowNum(30,40,cy,3,16);
  15. OLED_Refresh();
  16. /* USER CODE END WHILE */
  17. /* USER CODE BEGIN 3 */
  18. if(flag) Tilt();
  19. }
  20. /* USER CODE END 3 */
  21. }

3、按键控制暂停
  1. /* USER CODE BEGIN 4 */
  2. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
  3. {
  4. if(GPIO_Pin == KEY0_Pin){
  5. HAL_Delay(20); //延时消抖
  6. if(GPIO_Pin == KEY0_Pin){
  7. flag=0;
  8. }
  9. }
  10. }
  11. /* USER CODE END 4 */

六、巨人之肩

【毕业设计】基于STM32及OpenMV的云台追踪装置

电赛:二维云台控制

【毕业设计】基于STM32F103C8T6最小系统板与OpenMV的二维云台PID控制追踪系统

后续优化方案:PID调控

位置式PID与增量式PID区别浅析

七、源码提供

【STM32+OPENMV】二维云台颜色识别及追踪【无PID版】

八、成果展示

PTZ

九、优化方案:PID控制

  1. #include "ptz.h"
  2. #include "string.h"
  3. #include "stdio.h"
  4. #include "stdlib.h"
  5. #include "main.h"
  6. #include "tim.h"
  7. #include "usart.h"
  8. #define RXBUFFERSIZE 256
  9. #define CCR_UD TIM1->CCR1 //up and down.... RANGE:1250-7500
  10. #define CCR_LR TIM1->CCR2 //Left and Right.... RANGE:1250-7500
  11. #define Cen_x 160 //x轴中心坐标值
  12. #define Cen_y 120 //y轴中心坐标值
  13. #define KP1 0.45
  14. #define KD1 2
  15. #define KP2 0.35
  16. #define KD2 2
  17. #define sp1 30
  18. #define sp2 23
  19. #define range 35
  20. char RxBuffer[RXBUFFERSIZE],rx_buf[RXBUFFERSIZE];
  21. uint8_t aRxBuffer;
  22. uint8_t Uart1_Rx_Cnt = 0;
  23. int cnt_rx=0,cnt_dt=0;
  24. int cx=0,cy=0;
  25. void Tilt(void)
  26. {
  27. if(PID1(cx,Cen_x)+CCR_LR>7450) CCR_LR=7450;
  28. else if(CCR_LR<1250) CCR_LR=1250;
  29. else CCR_LR+=PID1(cx,Cen_x);
  30. if(CCR_UD>4000) CCR_UD=4000;
  31. else if(CCR_UD<1250) CCR_UD=1250;
  32. else CCR_UD-=PID2(cy,Cen_y);
  33. }
  34. int PID1(int current,int target) //PID速度控制
  35. {
  36. static int LastError; //Error[-1]
  37. int iError,Outpid; //当前误差
  38. iError=target-current; //增量计算
  39. Outpid=(KP1 * iError) //E[k]项
  40. +(KD1 * (iError-LastError)); //E[k]-E[k-1]项
  41. LastError=iError; //存储误差,用于下次计算
  42. return Outpid;
  43. }
  44. int PID2(int current,int target) //PID速度控制
  45. {
  46. static int LastError; //Error[-1]
  47. int iError,Outpid; //当前误差
  48. iError=target-current; //增量计算
  49. Outpid=(KP2 * iError) //E[k]项
  50. +(KD2 * (iError-LastError)); //E[k]-E[k-1]项
  51. LastError=iError; //存储误差,用于下次计算
  52. return Outpid;
  53. }
  54. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  55. {
  56. UNUSED(huart);
  57. if(huart==&huart2){
  58. RxBuffer[Uart1_Rx_Cnt] = aRxBuffer;
  59. Uart1_Rx_Cnt++;
  60. if((RxBuffer[Uart1_Rx_Cnt-1] == 0xb3)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0xb3)) cnt_rx=1; //帧头判定
  61. else if((RxBuffer[Uart1_Rx_Cnt-2] == 0x0d)&&(RxBuffer[Uart1_Rx_Cnt-1] == 0x0a)) cnt_rx=2; //帧尾判定
  62. else cnt_rx=0;
  63. switch (cnt_rx)
  64. {
  65. case 1:
  66. Uart1_Rx_Cnt = 0;
  67. memset(RxBuffer,0x00,sizeof(RxBuffer));
  68. break;
  69. case 2:
  70. RxBuffer[Uart1_Rx_Cnt-1] = '\0';
  71. RxBuffer[Uart1_Rx_Cnt-2] = '\0';
  72. strcpy(rx_buf,RxBuffer);
  73. int st=0; //有效数值开始位置
  74. cnt_dt=0; //空格数
  75. for(int i=0;rx_buf[i];i++){
  76. if(cnt_dt==4) break;
  77. if(rx_buf[i]==' ') {
  78. cnt_dt++;
  79. int temp=0;
  80. for(int j=st;j<i;j++)
  81. temp=temp*10+(rx_buf[j]-'0');
  82. switch (cnt_dt){
  83. case 1:cx=temp;break;
  84. case 2:cy=temp;break;
  85. }
  86. st=i+1;
  87. }
  88. }
  89. while(HAL_UART_GetState(&huart2) == HAL_UART_STATE_BUSY_TX);
  90. Uart1_Rx_Cnt = 0;
  91. memset(RxBuffer,0x00,sizeof(RxBuffer));
  92. break;
  93. default:break;
  94. }
  95. HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);
  96. }
  97. }

源码

STM32+OPENMV二维云台颜色识别及追踪PID版

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

闽ICP备14008679号