电赛校赛总结----一维板球系统【代码开源】

news2024/11/27 21:08:22

 2022/4/21

搭建了整体的机械结构,最后因为经费问题,选择了用去年风力摆的架子去搭摄像头【openmv】,看当年的国赛题,选择的是ov7670,但我们讨论后觉得还是openmv的识别比较好,,下面的小球选用的是外径为3.2cm的水管,然后将水管一分为二,然后去放置小球,舵机采用是的是MG996R舵机,原本想着用的是MG995R【因为以前学长他们做过一个就用的是这个】,但是发现996R响应的更快。通过舵机占空比的调整将占空比传入PID算法去完成让管子进行倾斜且保持平衡。板子用的就是stm32mini开发板,这次这个不用考虑这个板子大小,就选IO口多的。

2022/4/22

凌晨开始较为正式写代码,才开始还是比较头疼这个PID该怎么调以及怎么调用,因为确实平时用的很少,后来想到了一个简单的方法,先调试舵机的占空比,知道这个转轴什么时候是水平,最高和最低,把三个的占空比分别记录出来,为后面的PID调用的做准备,调好之后我们把舵机那个转轴放置水平去安装机械结构【这样为我们后面省了不少事】,相当于我们起始装置就是水平的,这样直接将算出来的PID的占空比直接加减到上面就行了,调试简单了很多。

Xplot运行代码:

运行函数
//send_wave();
//getdatas();
//get_cmd();


函数定义
//void send_wave(void)
//{
//	//定义通道名帧头帧尾
//	u8 frameNameHead[] = "AABBCC";
//	u8 frameNameEnd[] = "CCBBAA";
//	
//	//定义数据帧头帧尾
//	u8 frameDataHead[] = "DDEEFF";
//	u8 frameDataEnd[] = "FFEEDD";
//	
//	//定义通道名
//	u8 name[] = {"x_now,I,D,PWM_X,flag,aim,MOtor_X_PWM"};
//	
//	//赋值数据
//	float channels[7];
//	channels[0] = x_now;
//	channels[1] = kp;
//	channels[2] = kd;
//	channels[3] = data[0];
//	channels[4] = flag;
//	channels[5] = X_aim;
//	channels[6] = Motor_X_PWM;
//	//通过串口1,向上位机发送数据
//	usart_senddatas(USART1,frameNameHead,sizeof(frameNameHead)-1);
//	usart_senddatas(USART1,name,sizeof(name)-1);
//	usart_senddatas(USART1,frameNameEnd,sizeof(frameNameEnd)-1);
//	
//	usart_senddatas(USART1,frameDataHead,sizeof(frameDataHead)-1);
//	usart_senddatas(USART1,(u8*)channels,sizeof(channels));
//	usart_senddatas(USART1,frameDataEnd,sizeof(frameDataEnd)-1);
//	
//}

//void getdatas(void)
//{
//	data[0] = kp*X.err[0]+flag*ki*X.e_I+kd*(X.err[0]-X.err[1]);
//}

//void get_cmd(void)
//{
//	char u_buff[10];
//	float u_d1,u_d2,u_d3;
//	if(usart_get_data(u_buff,&u_d1,&u_d2,&u_d3))
//	{
//		if(strcmp(u_buff,"PID") == 0) //比较命令控制字符是否为PID
//		{
//			kp = u_d1;
//		  ki = u_d2;
//			kd = u_d3;
//		}
//	}
//	memset(u_buff,0,sizeof(u_buff));
//}




usart.c

//char usart_readbuff[30] = {0}; //串口接受缓存数组
//u8 usart_readok = 0; //一帧数据处理标志
//void USART1_IRQHandler(void)                	//串口1中断服务程序
//{
//	u8 temp;
//	static u8 count = 0;  // 接收数组控制变量
//	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //判断是否为接收中断
//	{
//		temp = USART_ReceiveData(USART1);	//读取接收到的数据,并清除中断标志
//		if(temp == '#' && usart_readok == 0) 
//		{
//			usart_readbuff[count] = '#';
//			usart_readok = 1;
//			count = 0;
//		}
//		else if(usart_readok==0)
//		{
//			usart_readbuff[count] = temp; //保存接收到的数据到接收缓存数组
//			count++; //数组下标切换
//			if(count >= 30) // 防止数据越界
//				count = 0;
//		}
//	}
//}


// 

//u8 usart_get_data(char *cmd,float *d1,float *d2,float *d3)
//{
//	u8 flag = 0;
//	if(usart_readok == 1)
//	{
//		if(sscanf(usart_readbuff,"%3s=%f,%f,%f#",
//											cmd,d1,d2,d3)==4)
//		{
//			flag = 1;
//		}
//		//清除接收完成标志
//		memset(usart_readbuff,0,sizeof(usart_readbuff));
//		usart_readok = 0;
//	}
//	return flag;
//}


//void usart_senddatas(USART_TypeDef* USARTx,u8* addr,int size)
//{
//	while(size--) //判断数据发送完没有
//	{
//		while(USART_GetFlagStatus(USARTx,USART_FLAG_TC) == RESET);//等待上一个byte的数据发送结束。
//		USART_SendData(USARTx,*addr);//调用STM32标准库函数发送数据
//		addr++; //地址偏移
//	}
//}

凌晨两点:我和我们组的一个女生还在对着电脑用一个第一次用的软甲yplot去调试PID参数,现在想想,还是觉得痛苦,最后调到大概中午12点,感觉还算满意,就先放着了,当时调的差不多的时候,我们就觉得没啥事情了,就有点懈怠,因为看了看这几个题,觉得只要PID调出来了,就没啥难的了【为后来埋下了后患!!!!】

因为有八道题,原本用的是触摸屏进行串口发送信息读取去选择功能的,但是我不小心把供电的电源短接了,结果瞬间就烧了,哎,后来就换了OLED【多级菜单,板载按键控制】,设定了两级菜单,因为就八个功能,当时发现还有个按键,就想着用给调平【让系统保持水平】吧,所以就有了2的功能。

//按键控制发送信息
void Menu_key_set(void)
{
    key_state = KEY_Scan(0);
    if (key_state == 1)
    {
			  OLED_Clear();
        func_index = table[func_index].next;
    }
		if(key_state == 2)
		{
		    TIM_SetCompare1(TIM3,14.5);
		}
    if(key_state == 3)
		{
			  OLED_Clear();
				func_index = table[func_index].enter;
		}
    current_operation_index = table[func_index].current_operation;
    (*current_operation_index)();
}

//多级菜单
void meun1_func(void)
{
    OLED_ShowString(0, 0, "   1.I    ", 16);
    OLED_ShowString(0, 2, "   2.II", 16);
}

void meun3_func(void)
{
    OLED_ShowString(0, 0, "   1.1    ", 16);
    OLED_ShowString(0, 2, "   2.2", 16);
    OLED_ShowString(0, 4, "   3.3", 16);
    OLED_ShowString(0, 6, "   4.4", 16);
}

void meun2_func(void)
{
    OLED_ShowString(0, 0, "   1.21    ", 16);
    OLED_ShowString(0, 2, "   2.22", 16);
    OLED_ShowString(0, 4, "   3.23", 16);
    OLED_ShowString(0, 6, "   4.24", 16);
}

功能1,2,3都是从1运动到某个点,因为我们在开始的时候,用openmv详细的记录了每个点的像素位置,这样相当于我们把目标位置的X_aim传入到pid算法就可以了,然后openmv会实时的读取当前的小球坐标然后借助串口3传回给单片机,将这个X_now也回传到PID,进行计算出来的占空比。

后面的4,5相较于之前的是变为三个点,且需要稳定2s,这样就需要加入定时器的功能,才开始用的TIM1,但是发现无法进行定时,我到现在不知道为啥,后来该到了TIM2,一下子就好了,真够玄学的,定时器时间就设为0.5s,在定时器的中断里面加入一个static静态变量,这样你需要传一次flag标志位由你定,当时间到了,对应的flag的数值一变,定时就结束了

//定时器2中断服务程序
void TIM2_IRQHandler(void)
{
    //判断TIM2更新中断是否发生
    if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
{
        //代码应用区
		i++;
		t++;
		if(i%20 == 0)
		{
			timeflag = 1;
		}
		if(t%20 == 0)
		{
			lanyaflag= 1;  
    }
		
} 

 当时就是如何开始定时器的计时,还是想了一些时间的,后来设置一个jinruflag标志位,这样达到要求初始化一次了,然后根据timeflag的数值,若为1,则时间到了,然后就去走到下一个点。

为啥我这个时间这么长,哎,主要pid调的不是很好,所以想给小球更多的时间去稳定下来,因为我们测试发现,当时间太短,确实可以到达目标点,但是却没有稳定下来,结果就是,去往下一个点的时候有初速度,这样下一个点就更不稳定了,恶性循环,所以就想着时间拉长一点,给它多一点的时间,让他在一个点稳定下来。

else if(a==5)
	{
		if(timeflag == 0)
		{
			X_aim = 83;
			task();
			if(jinruflag==0)
			{
				TIM2_Init(5000-1,7200-1);         //0.5s中断一次   
				delay_ms(20);
				jinruflag = 1;
			}
		}	
		if(timeflag == 1)
		{
			 X_aim = 145;
			 task();
		}
	}

第6题用的自主选择四个点,让小球进行平衡,看看也就是将之前的三个固定点变为随机的四个点,用蓝牙输入就行,我们选择的是蓝牙app上位机软件,发送的就是四个字符,到时候接收过来之后直接放在接收的数组里面,直接调用就行,确实,思路没啥问题,可是偏偏蓝牙接收就出问题了,我们可以在手机app端发送字符串,但是单片机的串口并不接受字符,换了几个串口都无济于事,花费了几个小时的时间,最后突然用了一个之前调好项目的蓝牙代码就好了,最后也找到了问题的根源---->

这是串口的中断的代码,你会发现有0X0D和0X0A的判断,对了,这是我们输入在app软件也要有这个多一行的换行符的存在,因为这个中断是通过判断0X0D和0X0A判断接收完成的,如果你的中断不加这个,就可以不用换行。

void USART2_IRQHandler(void)                    //串口1中断服务程序
    {
    u8 Res;
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
        {
        Res =USART_ReceiveData(USART2);    //读取接收到的数据
        if((USART2_RX_STA&0x8000)==0)//接收未完成
            {
            if(USART2_RX_STA&0x4000)//接收到了0x0d
                {
                if(Res!=0x0a)USART2_RX_STA=0;//接收错误,重新开始
                else USART2_RX_STA|=0x8000;    //接收完成了 
                }
            else //还没收到0X0D
                {    
                if(Res==0x0d)USART2_RX_STA|=0x4000;
                else
                    {
                    USART2_RX_BUF[USART2_RX_STA&0X3FFF]=Res;
                    USART2_RX_STA++;
                    if(USART2_RX_STA>(USART_REC_LEN-1))USART2_RX_STA=0;//接收数据错误,重新开始接收      
                    }         
                }
            }   
        						
     } 

} 

功能7:在2,4两点运行四次往复,最后去往5,因为当时就剩几个小时了,我们的硬件电路还没接好,所以我就有点着急,也没休息好,脑子很乱,当时想了一个方案计时,用static的静态变量去算,到2,4的次数有没有8次,来确定是否往复四次,想想也简单,就是传个已经有的现成坐标和openmv的实时坐标相减,得到位置差,传入PID,可是PID的参数调的不是很好,小球从2出发,到4还没稳定就又往2,所以误差越来越大,以至于到最后5的时候就飞出去了,当时去调PID已经不太可能了,但是我们发现选择的2,4两个点,它却在1,5之间徘徊,所以我们干脆把判断的范围直接往小了缩,类似于给小球一个预判,原本小球的目标是4,到4或者快到4它才开始大幅度调节,我们现在让他变成3.5,从2开始的距离差变小了,它就会判断提前,改了之后还真效果不错,只有一次没达到标【比之前就一次达标好太多了】,这道题后来也这样了。

else if(a == 7)
	{
		if(x_now<57&&x_now>46)
  {
   while(1)
   {
    X_aim = 93;                      //原来 4的X_aim是 113
    task();
    if(x_now<114&&x_now>106)
     break;
   }
   count++;
  }
  if(x_now<114&&x_now>106)
  {
   while(1)
   {
    X_aim = 70;                         //原来的2的X_aim = 53
     task();
    if(x_now<57&&x_now>50)
     break;
   } 
   count++;
  }
  if(count >= 8)
  {
   while(1)
   {
    X_aim = 145;
     task();
   }
  }
	}

最后一个是鲁棒性的测试,这个和之前的1,2,3很像,还是如果PID调的好的话,就很快,我们那个就是有点慢,这个题就在那个秒数限定的极限范围。

后来时间不允许就做了8问。

总结回顾:

1.PID调参很重要,如果有友友有啥好的推荐的软件可以给我推荐一下吗??

2.硬件电路的降压以及电压稳压问题需要格外重视

3.32的部分模块具体详细的作用还是不太清晰。

4.我们的团队配合还是不太好,团队的力量很重要

代码开源:MMMMMs426/-: 电赛一维板球代码 (github.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/471113.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式——七大原则

目录 一、通过经典面试题掌握重点 二、设计模式的目的和核心原则 三、设计模式七大原则 3.1 单一职责原则&#xff08;Single Responsibility Principle&#xff09; 3.2 接口隔离原则&#xff08;Interface Segregation Principle&#xff09; 3.3 依赖倒转原则&#xf…

Mysql表索引(普通索引)

文章目录 一、创建表时定义索引二、已存在的表上创建索引 1.指向create语句2.指向alter table 语句三、查看索引执行情况总结 前言 所谓普通索引&#xff0c;就是在创建索引时&#xff0c;不附加任何限制条件&#xff08;唯一、非空等限制&#xff09;。该类型的索引可以创建…

C plus plus ——【面向对象编程】

系列文章目录 C plus plus 面向对象编程 文章目录 系列文章目录前言一、编程语言概述1.1低级语言概述1.2高级语言概述1.3面向过程、面向对象概述 二、面向过程编程的特性三、面向对象编程的特性四、类和对象4.1 类的概述4.2 类的声明与定义4.3 类的实现4.4 对象的生命 五、构造…

数字化转型导师坚鹏:BLM企业数字化转型战略

BLM企业数字化转型战略 ——以BLM模型为核心&#xff0c;实现知行果合一 课程背景&#xff1a; 很多企业存在以下问题&#xff1a; 不知道企业如何制定数字化转型战略&#xff1f; 不清楚其它企业数字化转型战略是如何制定的&#xff1f; 不知道其它企业数字化转型战略…

Spring-boot集成swagger以及MapStruct简单使用

1&#xff09;添加依赖&#xff0c;我使用3.0.0版本时会出现swagger-ui页面404的问题&#xff0c;所以改成2.9.2&#xff0c;使用默认版本swagger-model会出现判空异常。 <!-- swagger--><dependency><groupId>io.springfox</groupId><arti…

python+nodejs+php+springboot+vue 社区小区报修 -社区信息管理

客户可以对社区信息进行添加&#xff0c;修改&#xff0c;删除以及查询操作。界面如下图所示: 四、客户模块的实现 4.1车位租买支付 客户可以对车位信息进行租买后可以在个人后台进行支付操作。界面如下图所示: 4.2前台车位信息 客户登录之后&#xff0c;可以查看前台车位…

传输层 — UDP协议

目录 一、传输层 1.1 端口号 1.2 关于端口的常见问题 1.3 netstat && pidof 二、UDP协议 2.1 UDP协议格式 2.2 UDP协议特点 2.3 UDP缓冲区 2.4 基于UDP的应用层协议 一、传输层 在进行网络传输时&#xff0c;应用层需先将数据交给传输层&#xff0c;由传输层…

基于matlab仿真混合波束成形在多用户MIMO-OFDM系统中的使用

一、前言 本 例 说明 了 如何 在 大规模 MIMO 通信 系统 的 发射 端 采用 混合 波束 成形&#xff0c; 同时 使用 多 用户 和 单 用户 系统 的 技术。该示例采用全通道探测来确定发射机的通道状态信息。它将所需的预编码划分为数字基带和模拟RF组件&#xff0c;对多用户和单用户…

智能的PHP开发工具PhpStorm v2023.1全新发布——集成3v4l.org

PhpStorm是一个轻量级且便捷的PHP IDE&#xff0c;其旨在提高用户效率&#xff0c;可深刻理解用户的编码&#xff0c;提供智能代码补全&#xff0c;快速导航以及即时错误检查。可随时帮助用户对其编码进行调整&#xff0c;运行单元测试或者提供可视化debug功能。 PhpStorm v20…

商城订单模块实战 - 数据库设计、ABA问题处理、读写分离分库分表

引言 订单系统可以说是整个电商系统中最重要的一个子系统&#xff0c;因此订单数据可以算作电商企业最重要的数据资产。这篇文章我们来看看在我们的商城系统中订单服务是如何实现的&#xff0c;特别是在设计和实现一个订单系统的过程中有哪些问题是需要特别考虑的。 业务分析…

逾 200 家港企参与! GoGBA大湾区发展日(广州)圆满举行

2023年4月26日 – 由香港特别行政区政府政制及内地事务局粤港澳大湾区发展办公室、香港特别行政区政府驻粤经济贸易办事处&#xff08;驻粤办&#xff09;、香港贸易发展局&#xff08;香港贸发局&#xff09;广州办事处&#xff0c;以及香港贸发局GoGBA商贸支援合办的GoGBA大湾…

BSN-DDC基础网络详解(十):官方DDC应用SDK

官方 SDK 是 BSN 联盟为平台方推出的可快速接入 DDC 网络的工具包&#xff0c;目前 DID 和各个开放联盟链的官方 DDC SDK 都使用 Java 语言开发&#xff0c;其它主流语言的 SDK 根据市场反馈我们将陆续增加。如果算力中心方和平台方的业务系统的开发语言与 SDK 不匹配&#xff…

基于DSP+FPGA+ADS1282支持31Bit高精度数据采集方案(一)

3.1 系统需求分析 3.1.1 系统功能设计要求 本硬件处理平台的主要任务有三类&#xff0c;一是数据采集&#xff0c;包括采集惯性测量元件 的输出信号&#xff0c;接收外部系统校正信息&#xff0c;如 GPS 信息等&#xff1b;二是数据处理与计算&#xff0c;包 括惯性测量…

如何实现自动化按图片搜索淘宝商品(拍立淘)功能?拍立淘API接口item_search_img

我们都知道淘宝平台推出了拍立淘功能&#xff0c;如果大家遇到了自己喜欢的商品&#xff0c;就可以拍一张照片&#xff0c;在淘宝用拍立淘搜索就能够出现相似的同款&#xff0c;这样就不用再去找别人要链接了。淘宝拍立淘主要是通过图片识别来找相似主图的宝贝&#xff0c;那么…

基于JavaSpringmvc+myabtis+html的鲜花商城系统设计和实现

基于JavaSpringmvcmyabtishtml的鲜花商城系统设计和实现 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式…

分布式的流处理平台Kafka

目录&#xff1a; 一、简介二、基本概念三、生产者使用详解四、发送消息五、消费者代码示例 一、简介 ApacheKafka 是一个分布式的流处理平台。它具有以下特点&#xff1a; 支持消息的发布和订阅&#xff0c;类似于 RabbtMQ、ActiveMQ 等消息队列&#xff1b;支持数据实时处理…

从零开始实现VAE和CVAE

扩散模型可以看作是一个层次很深的VAE(变分自编码器)&#xff0c;前向&#xff08;forward&#xff0c;或者译为正向&#xff09;的过程&#xff0c;通过在多个尺度上添加噪声来逐步扰乱数据分布&#xff1b;然后是反向的过程&#xff0c;去学习如何恢复数据结构&#xff0c;上…

喜报 | 国家发明专利证书! 再添2项!

​近日&#xff0c;擎创科技自主研发的《一种基于倒序表的实时日志聚类分析方法》以及《一种基于社区检测的运维告警场景生成方法》正式获得国家颁发的发明专利证书&#xff01;擎创的专业性、自主性、创新能力、技术水平以及研发实力在得到了确切的肯定。 作为智能运维领域领先…

DJ4-5 路由算法:LS 和 DV

目录 一、迪杰斯特拉算法 1. 术语定义 2. 算法描述 3. 举例说明 4. 构建从源节点到目的节点的路径 5. 构建最低费用路径树 6. 构建转发表 二、距离向量路由算法 1. 术语定义 2. 举例说明 3. 距离向量表 4. 更新距离向量表 5. 举例说明 三、距离向量路由算法 PLUS…

多维评测指标解读2022MSU世界编码器大赛结果

是极致性能&#xff0c;更是最佳商用。 19项第一之上&#xff0c;是63%的极致带宽降低 近日&#xff0c;2022 MSU世界视频编码器大赛成绩正式揭晓。报告显示&#xff0c;阿里媒体处理服务MPS&#xff08;Alibaba Media Processing Service&#xff09;s264及s265编码器共计斩获…