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是 113task();if(x_now<114&&x_now>106)break;}count++;}if(x_now<114&&x_now>106){while(1){X_aim = 70;                         //原来的2的X_aim = 53task();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)

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

  1. 2022杭电多校赛第八场

    2022杭电多校赛第八场 文章目录 2022杭电多校赛第八场 1004.Quel'Thalas 1001.Theramore 1011.Stormwind 1008.Orgrimmar 1005.Ir ...

  2. 【电赛】电设校赛常用电路整理

    电设校赛常用电路整理 写在前面 引用与致谢 单电源供电集成运放 电压比较器 单限比较器 过零比较器 改进:限制幅度和设置偏置 滞回比较器 窗口比较器 波形发生与变换 正弦波 RC正弦振荡电路 LC正弦 ...

  3. “师创杯”山东理工大学第九届ACM程序设计竞赛 正式赛 F.校赛~校赛~【思维+规律题】

    校赛~校赛~ Time Limit: 1000MS  Memory Limit: 65536KB Submit  Statistic Problem Description SDUT 的校赛是从 20 ...

  4. 电赛校赛-三相逆变电源设计(模拟部分)

    写在前面 因为疫情问题,我们学校的这次电赛的校赛只能线上进行了,我是负责测量部分,所以其实压力相对小一点,为了统一评分,只能使用proteus8.6,我也是无奈,又捡起来了很多年不用的C51 OR C ...

  5. 鸿蒙系统代码开源不担忧友商,华为鸿蒙系统正式开源!打脸“安卓套皮论”,友商手机也可采用!...

    看得出在鸿蒙系统的推广和普及上华为行进的动作力度是又大又快.针对外界议论纷纷的"鸿蒙是不是安卓系统换皮"的争议,华为打算用最彻底的方式来辩驳,那就是将鸿蒙系统全面开源.据今天传来的 ...

  6. 电赛校赛-三相逆变电源设计(单片机部分--C52仿真测频+串口发送机与串口接收机)

    写在前面 承接前文的模拟部分,这次开始写下单片机部分的仿真程序设计,本文介绍C52单片机的设置,后面将会介绍MSP430F249的具体配置. 题目 基础部分 搭建 DC-AC 电路以及检测电路. 调整 ...

  7. 2019 西电ACM校赛网络赛 题解

    今年题目难度有较大提升,总体与往年类似,数学题居多.以下为我通过的部分题解. 赛题链接:http://acm.xidian.edu.cn/contest.php?cid=1053 A - 上帝视角 我 ...

  8. 电赛校赛-三相逆变电源设计(单片机部分--MSP430F249仿真测频+串口发送机与串口接收机)

    写在前面 觉得52单片机比较低端的,可以尝试本文的MSP430,两种测量方案均通过测试仿真,个人还是推荐C52,proteus对其他单片机仿真的速度好像提不了太快,承接上文,本次主要设计就是用的是MS ...

  9. 【2021杭电多校赛】2021“MINIEYE杯”中国大学生算法设计超级联赛(10)签到题2题

    Solved Pro.ID Title Ratio(Accepted / Submitted) 1001 Pty loves sequence 25.00%(52/208) 1002 Pty with ...

最新文章

  1. csvtk:命令行下表格统计分析、数据筛选、替换、整理神器
  2. mysql 渗透及漏洞利用总结
  3. 用Python制作酷炫的可视化报表。
  4. Mybatis源码阅读(四):核心接口4.2——Executor(下)
  5. swift之Mac中NSView视图里的截图【ScrollView中的内容截图】
  6. HDU 5067 Harry And Dig Machine:TSP(旅行商)
  7. 如何在 Web 开发中找到第一份工作?
  8. php和python-PHP和Python性能比较:放弃PHP改用Python
  9. Aspose.Words从零创建OOXML图表
  10. mysql常用的存储过程_MySQL存储过程的基本函数
  11. java中如何转换成台湾繁体,台湾繁体转换成大陆繁体的简单方法
  12. Qt系列文章之 右键菜单QMenu(下)
  13. Unity SetFromToRotation和FromToRotation的区别
  14. 给女朋友写一个微信小程序
  15. 玩游戏蓝牙耳机哪款好?适合打游戏的无线蓝牙耳机推荐
  16. 南京大学2021计算机考研复试线是多少,2021南京大学
  17. Z-Blog模板安装和使用教程
  18. 张景明:方剂【方歌】——清热剂
  19. Matlab plot画图 坐标字体、字号、范围、间隔等的设置
  20. cnn风格迁移_机器学习:利用卷积神经网络实现图像风格迁移 (一)

热门文章

  1. mSystems | 中农汪杰组揭示影响土壤“塑料际”微生物群落的机制
  2. 二手市场回收基于微信小程序和app两种应用开发uniapp
  3. vue使用video和vue-video-player并且可实现视频铺满呦
  4. Android HIDL接口
  5. thrift 技术分享待续
  6. 真爱至上Love Actually
  7. 管道pipe-有名管道
  8. 学计算机英语的心得体会,英语学习心得体会
  9. cache tier 分级缓存
  10. Mobile2.0不对等的战争