(某科学的)电磁炮-2019电设

练了这么久,终于到了比赛的日子了(好吧开始写这篇文章的时候综测都结束了)。

那天早上拿到题目,我们是懵逼的:

excuse me?有控制组的题目吗?

小车?无线充电打扰了;机器人?飞行器打扰了;电磁炮?高压打扰……等等,再打扰就没题目了。经过一波商量,就电磁炮吧,于是开始了我们的四天打炮之旅(雾)

废话不多说,看看题目。

/***********************我是一条分割线**************************/
一、任务
自行设计并制作一模拟电磁曲射炮,炮管水平方位及垂直仰角方向可调节,用电磁力将弹丸射出 ,击中目标环形靶(发射周期不得超过 3 0 秒 。电磁炮由直流稳压电源供电, 电磁炮系统内允许使用容性储能元件。
二、要求
电磁炮与环形靶的位置示意如图1 及图2 所示。电磁炮放置在定标点处,炮
管初始水平方向与中轴线夹角为0°、垂直方向仰角为0°。环形靶水平放置在
地面,靶心位置在与定标点距离200cm≤d≤300cm,与中心轴线夹角a≤±30°
的范围内。
1.基本要求
(1) 电磁炮能够将弹丸射出炮口。
(2) 环形靶放置在靶心距离定标点200~300cm 间,且在中心轴线上的位置处,键盘输入距离d 值,电磁炮将弹丸发射至该位置,距离偏差的绝对值不大50cm。
(3) 用键盘给电磁炮输入环形靶中心与定标点的距离d 及与中心轴线的偏离角度a,一键启动后,电磁炮自动瞄准射击,按击中环形靶环数计分;若脱靶则不计分。
2.发挥部分
(1) 在指定范围内任意位置放置环形靶(有引导标识,参见说明2),一键启动后,电磁炮自动搜寻目标并炮击环形靶,按击中环形靶环数计分,完成时间≤30s。
(2) 环形靶与引导标识一同放置在距离定标点d=250cm 的弧线上(以靶心定位),引导标识处于最远位置。电磁炮放置在定标点,炮管水平方向与中轴线夹角a =-30°、仰角0°。一键启动电磁炮,炮管在水平方向与中轴线夹角a从-30°至30°、再返回-30°做往复转动,在转动过程中(中途不得停顿)电磁炮自动搜寻目标并炮击环形靶,按击中环形靶环数计分,启动至击发完成时间≤10s。
(3) 其他。

/***********************我是一条分割线**************************/

第一天确定题目后,让外面的朋友千里迢迢跑去电子市场买了升压模块,然后研究了下电磁炮原理。模块和电容到货后,就正式开始(话说这电容是真的大,放图)

第一天晚上,一组组都可以把炮弹发射出去了,走廊里架起了多组电磁炮,吸引了别的组的一大堆围观人员,确定电路结构没有问题后,回家睡觉。

第二天第三天,进展缓慢,第一天没出现的问题一个个出来了。

1、继电器是250v5a的,而我们电压过百,电阻不到1欧,电流轻松过百安,一个个组都开始烧继电器,甚至有些组因为解决不掉这个问题,暂时直接手动给电容充放电(胆子是真的大),房间里面电光石火的。

2、炮弹落点不准。我们炮管内径14mm,试了5/8/10/12/13/14各种直径钢珠,发现各钢珠不仅射程不一样,落点精度也不一样,有些钢珠一会2m,一会3m,有些就能保证落点很接近一个点,最后我们选用了13mm的钢珠。

等我们弄完机械结构和电路结构,已经是第三天晚上11点了,离比赛结束(第四天晚上六点)还有19小时,我这个写软件的终于干回了老本行,肝了一晚,第四天上午七点把软件写完,又花了几小时调了调,收工睡觉。

下面看下代码,初始化什么的就不讲了,就看看几个功能吧,用arduino写的:

第一题,随意开炮(我设了打250cm处):

servo_move(1, cor_angel1, 100);
servo_move(2, angel_list[50], 100); //转到打50cm位置
Serial.println("mode1, booooom!");
charge();
delay(3000);
boom();

cor_angel是水平方向中心位置,其他应该很好理解

/***********************我是一条分割线**************************/

第三题,选择角度和距离:

dis = 101;
angel = 61;
Serial.println("Waiting dis and angel");
while(dis > 100 || angel > 60)
{
  Blu_ana();
  servo_move(1, left_angel-x_step*angel, 100); //left_angel右30度
  servo_move(2, angel_list[dis], 100);
  Serial.println("mode3, booooom!");
  charge();
  delay(3000);
  boom();
}

第四题,靠openmv发来的数据,判断目标在左边还是右边(炮管转动时摄像头也是跟着转的),转到水平轴对齐之后(其实并没有完全对齐,摄像头和炮管有一定角度偏差,故开炮前需移动一个固定的小角度),上下摇摆炮管(其实是为了摇摆和炮管在一起的超声波传感器),同时打开100ms定时器,执行读取us100的数据,定时器代码如下:
void wave_dis()
{
  unsigned int lenHigh = 0; // 高位
  unsigned int lenLow = 0; // 低位
  unsigned int dist_mm = 0; // 距离

  Serial2.flush(); // 清空串口接收缓冲区
  Serial2.write(0x55); // 发送0x55,触发US-100 开始测距

// 当串口接收缓冲区中数据大于2字节
  if(Serial2.available() >= 2){
  lenHigh = Serial2.read(); // 距离的高字节
  lenLow = Serial2.read(); // 距离的低字节
  dist_mm = lenHigh*256 + lenLow; // 计算距离值

// 有效的测距的结果
  if((dist_mm > 2000) && (dist_mm < 2950))
  { 
// 输出结果至串口监视器 
    Serial.print("Distance is: ");
    Serial.print(dist_mm, DEC); 
    Serial.println("mm"); 
    get_dis = dist_mm/10+3; 
    if(min_dis > get_dis)
    min_dis = get_dis;
    }
  }
}

读取到距离之后,就调整炮管打击角度,正式开炮,完整流程如下:
void mode4()
{
  int l_r = 5; //偏左还是右
  char mv_s;
  Serial3.print("#");
  delay(100);
  while(Serial3.available() > 0)
  {
    mv_s = Serial3.read();
    if(mv_s >= '0' && mv_s <= '5')
    {
      l_r = mv_s-48;
      Serial.print("l_r: ");
      Serial.println(l_r);
    }
  }
  if(l_r == 1 && now_servo1_pulse < left_angel) //右转(慢) 
    servo_move(1, now_servo1_pulse+5, 5); 
  else if(l_r == 2 && now_servo1_pulse > right_angel)
    servo_move(1, now_servo1_pulse-5, 5);

  if(l_r == 3 && now_servo1_pulse < left_angel) 
    servo_move(1, now_servo1_pulse+20, 20); 
  else if(l_r == 4 && now_servo1_pulse > right_angel)
    servo_move(1, now_servo1_pulse-20, 20);

  else if(l_r == 0) //对准了
  {
    charge();
    Timer1.start(50000);

    servo_move(2, 1950, 2);
    delay(2000);
    servo_move(2, 1800, 2);
    delay(2000);

    Timer1.stop();
    Serial.print("min_dis: ");
    Serial.println(min_dis);

    if(min_dis >= 230 && min_dis <= 330) 
    { 
      servo_move(1, now_servo1_pulse-65, 10); 
      servo_move(2, angel_list[min_dis-230], 20); 
      delay(1000); boom(); app_mode = 0; 
    } 
  } 
}

然而。。。这道题由于一个致命的bug,测评时0分。
在测试的时候,由于场地不够大,离炮管3m处就是墙,所以当超声波读到的距离小于等于2.95米时才算有效数据(滤除了墙)。然而引导牌的范围应该是2.3米到3.3米,测评时引导牌处于3.3m位置。。。当场暴毙

第五题,按我们对题目的理解,做出了第四题之后就很简单,代码先贴一下:

void mode5() 
{ 
  int shot_flag = 0;//开炮前后 
  int l_r = 5; //偏左还是右 
  char mv_s; Serial3.print("#"); 
  delay(100); 
  while(Serial3.available() > 0)
  {
    mv_s = Serial3.read();
    if(mv_s >= '0' && mv_s <= '5') 
    { 
      l_r = mv_s-48; 
      Serial.print("l_r: "); 
      Serial.println(l_r); 
    } 
  } 
  if(l_r == 2 && now_servo1_pulse > right_angel)
    servo_move(1, now_servo1_pulse-5, 5);
  else if((l_r == 4 || l_r == 5)&& now_servo1_pulse > right_angel)
    servo_move(1, now_servo1_pulse-20, 20);

  else if(l_r == 0 || l_r == 1 || l_r == 3) //对准了或者超了
  {
    shot_flag = 1;
    servo_move(1, now_servo1_pulse-55, 5);
    delay(500);
    boom();
  }

  if(shot_flag)
  {
    servo_move(1, right_angel, 30);
    while(now_servo1_pulse != right_angel)
    {
      delay(50);
      servo_move(1, left_angel, 12);
      servo_move(2, 1940, 12);

      app_mode = 0;
      start_press = 0;
    }
  }
}

虽然题目和专家理解的有一些出入,经过我们现场的争辩,也应该是给了满分(毕竟打了10环=-=)

下载链接

点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注