有关OPENMV最大色块追踪及与STM32通信内容,详情见【STM32+HAL】与OpenMV通信
有关七针OLED屏显示内容,详情见【STM32+HAL】七针OLED(SSD1306)配置(SPI版)
1、芯片:STM32F407ZGT6
2、CUBEMX配置软件
3、KEIL5
4、OPENMV
二维云台追踪最大色块,并显示中心x,y坐标至OLED
周期为20ms
- #include "ptz.h"
- #include "string.h"
- #include "stdio.h"
- #include "stdlib.h"
- #include "main.h"
- #include "tim.h"
- #include "usart.h"
-
- #define RXBUFFERSIZE 256
- #define CCR_UD TIM2->CCR2 //up and down.... RANGE:420-2000
- #define CCR_LR TIM2->CCR3 //Left and Right.... RANGE:420-2500
- #define Cen_x 160 //x轴中心坐标值
- #define Cen_y 120 //y轴中心坐标值
-
- #define sp1 7 //x轴速度
- #define sp2 6 //y轴速度
- #define range 40 //识别范围
-
-
-
- char RxBuffer[RXBUFFERSIZE],rx_buf[RXBUFFERSIZE];
- uint8_t aRxBuffer;
- uint8_t Uart1_Rx_Cnt = 0;
-
- int cnt_rx=0,cnt_dt=0;
- int cx=0,cy=0;
-
-
-
-
- void Tilt(void)
- {
- if(cx < (Cen_x-range)) CCR_LR = (CCR_LR>2450)?2450:CCR_LR+sp1;
- else if (cx > (Cen_x+range)) CCR_LR = (CCR_LR<450)?450:CCR_LR -sp1;
- else CCR_LR= CCR_LR;
-
- if(cy < (Cen_y-range)) CCR_UD = (CCR_UD<420)?420:CCR_UD -sp2;
- else if (cy > (Cen_y+range)) CCR_UD = (CCR_UD>1800)?1800:CCR_UD+sp2;
- else CCR_UD= CCR_UD;
- }
-
-
-
-
-
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
- {
- UNUSED(huart);
- if(huart==&huart2){
- RxBuffer[Uart1_Rx_Cnt] = aRxBuffer;
- Uart1_Rx_Cnt++;
- if((RxBuffer[Uart1_Rx_Cnt-1] == 0xb3)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0xb3)) cnt_rx=1; //帧头判定
- else if((RxBuffer[Uart1_Rx_Cnt-2] == 0x0d)&&(RxBuffer[Uart1_Rx_Cnt-1] == 0x0a)) cnt_rx=2; //帧尾判定
- else cnt_rx=0;
-
- switch (cnt_rx)
- {
- case 1:
- Uart1_Rx_Cnt = 0;
- memset(RxBuffer,0x00,sizeof(RxBuffer));
- break;
- case 2:
- RxBuffer[Uart1_Rx_Cnt-1] = '\0';
- RxBuffer[Uart1_Rx_Cnt-2] = '\0';
- strcpy(rx_buf,RxBuffer);
-
- int st=0; //有效数值开始位置
- cnt_dt=0; //空格数
- for(int i=0;rx_buf[i];i++){
- if(cnt_dt==4) break;
- if(rx_buf[i]==' ') {
- cnt_dt++;
- int temp=0;
- for(int j=st;j
- temp=temp*10+(rx_buf[j]-'0');
- switch (cnt_dt){
- case 1:cx=temp;break;
- case 2:cy=temp;break;
- }
- st=i+1;
- }
- }
-
- while(HAL_UART_GetState(&huart2) == HAL_UART_STATE_BUSY_TX);
- Uart1_Rx_Cnt = 0;
- memset(RxBuffer,0x00,sizeof(RxBuffer));
- break;
- default:break;
- }
- HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);
- }
- }
2、main.c
- /* USER CODE BEGIN 2 */
- OLED_Init();
-
- HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);
-
- TIM2->CCR2 = 420-1;
- TIM2->CCR3 = 1400-1;
- HAL_TIM_PWM_Start (&htim2, TIM_CHANNEL_2);
- HAL_TIM_PWM_Start (&htim2, TIM_CHANNEL_3);
- /* USER CODE END 2 */
-
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- OLED_ShowNum(30,20,cx,3,16);
- OLED_ShowNum(30,40,cy,3,16);
- OLED_Refresh();
- /* USER CODE END WHILE */
-
- /* USER CODE BEGIN 3 */
- if(flag) Tilt();
- }
- /* USER CODE END 3 */
- }
3、按键控制暂停
- /* USER CODE BEGIN 4 */
-
- void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
- {
- if(GPIO_Pin == KEY0_Pin){
- HAL_Delay(20); //延时消抖
- if(GPIO_Pin == KEY0_Pin){
- flag=0;
- }
- }
- }
- /* USER CODE END 4 */
六、巨人之肩
【毕业设计】基于STM32F103C8T6最小系统板与OpenMV的二维云台PID控制追踪系统
后续优化方案:PID调控
七、源码提供
【STM32+OPENMV】二维云台颜色识别及追踪【无PID版】
八、成果展示
PTZ
九、优化方案:PID控制
- #include "ptz.h"
- #include "string.h"
- #include "stdio.h"
- #include "stdlib.h"
- #include "main.h"
- #include "tim.h"
- #include "usart.h"
-
- #define RXBUFFERSIZE 256
- #define CCR_UD TIM1->CCR1 //up and down.... RANGE:1250-7500
- #define CCR_LR TIM1->CCR2 //Left and Right.... RANGE:1250-7500
- #define Cen_x 160 //x轴中心坐标值
- #define Cen_y 120 //y轴中心坐标值
-
- #define KP1 0.45
- #define KD1 2
- #define KP2 0.35
- #define KD2 2
-
- #define sp1 30
- #define sp2 23
- #define range 35
-
-
-
- char RxBuffer[RXBUFFERSIZE],rx_buf[RXBUFFERSIZE];
- uint8_t aRxBuffer;
- uint8_t Uart1_Rx_Cnt = 0;
-
- int cnt_rx=0,cnt_dt=0;
- int cx=0,cy=0;
-
-
-
-
- void Tilt(void)
- {
- if(PID1(cx,Cen_x)+CCR_LR>7450) CCR_LR=7450;
- else if(CCR_LR<1250) CCR_LR=1250;
- else CCR_LR+=PID1(cx,Cen_x);
-
- if(CCR_UD>4000) CCR_UD=4000;
- else if(CCR_UD<1250) CCR_UD=1250;
- else CCR_UD-=PID2(cy,Cen_y);
-
- }
-
-
- int PID1(int current,int target) //PID速度控制
- {
- static int LastError; //Error[-1]
- int iError,Outpid; //当前误差
-
- iError=target-current; //增量计算
- Outpid=(KP1 * iError) //E[k]项
- +(KD1 * (iError-LastError)); //E[k]-E[k-1]项
-
- LastError=iError; //存储误差,用于下次计算
-
- return Outpid;
- }
-
- int PID2(int current,int target) //PID速度控制
- {
- static int LastError; //Error[-1]
- int iError,Outpid; //当前误差
-
- iError=target-current; //增量计算
- Outpid=(KP2 * iError) //E[k]项
- +(KD2 * (iError-LastError)); //E[k]-E[k-1]项
-
- LastError=iError; //存储误差,用于下次计算
-
- return Outpid;
- }
-
-
-
-
-
-
-
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
- {
- UNUSED(huart);
- if(huart==&huart2){
- RxBuffer[Uart1_Rx_Cnt] = aRxBuffer;
- Uart1_Rx_Cnt++;
- if((RxBuffer[Uart1_Rx_Cnt-1] == 0xb3)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0xb3)) cnt_rx=1; //帧头判定
- else if((RxBuffer[Uart1_Rx_Cnt-2] == 0x0d)&&(RxBuffer[Uart1_Rx_Cnt-1] == 0x0a)) cnt_rx=2; //帧尾判定
- else cnt_rx=0;
-
- switch (cnt_rx)
- {
- case 1:
- Uart1_Rx_Cnt = 0;
- memset(RxBuffer,0x00,sizeof(RxBuffer));
- break;
- case 2:
- RxBuffer[Uart1_Rx_Cnt-1] = '\0';
- RxBuffer[Uart1_Rx_Cnt-2] = '\0';
- strcpy(rx_buf,RxBuffer);
-
- int st=0; //有效数值开始位置
- cnt_dt=0; //空格数
- for(int i=0;rx_buf[i];i++){
- if(cnt_dt==4) break;
- if(rx_buf[i]==' ') {
- cnt_dt++;
- int temp=0;
- for(int j=st;j
- temp=temp*10+(rx_buf[j]-'0');
- switch (cnt_dt){
- case 1:cx=temp;break;
- case 2:cy=temp;break;
- }
- st=i+1;
- }
- }
-
- while(HAL_UART_GetState(&huart2) == HAL_UART_STATE_BUSY_TX);
- Uart1_Rx_Cnt = 0;
- memset(RxBuffer,0x00,sizeof(RxBuffer));
- break;
- default:break;
- }
- HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);
- }
- }
源码
-
相关阅读:
【chat】2:vs2022 连接远程ubuntu服务器远程cmake开发
js获取当前日期(年份,月份,时间)
JavaScript的事件循环机制浅析
关联线探究,如何连接流程图的两个节点
FreeRTOS深入教程(任务的引入及栈的作用)
全栈开发实战|Spring Boot文件上传与下载
Netty 进阶学习(九)-- 粘包与半包
进销存免费管理软件 进销存免费软件推荐 免费进销存
【必须安排】书单|1024程序员狂欢节充能书单!
全网最新的nacos 2.1.0集群多节点部署教程
-
原文地址:https://blog.csdn.net/m0_60372743/article/details/136491052