Chocho2017 发表于 2018-4-27 16:03:57

【chocho精选】报告!前方发现mega2560超声波雷达





小时候看美国电影,那里面经常出现一个黑黑的屏幕上一根绿色的线来回扫描的机器,后来才知道那叫雷达。在那个年代,雷达简直就是我跟小伙伴们心中唯一的“黑科技”。看见网上很多大神都制作了属于自己的超声波雷达,看得我心痒难耐。今天,我不能再压抑天性了——我也要做一台属于自己的超声波雷达,圆童年的梦,哈哈。
实现原理用arduino mega2560作为主控板,控制舵机转动,同时通过超声波采集距离数据,mega2560把这些信息处理后,显示在3.5寸 TFT屏幕上。
所需材料TowerPro SG90舵机 x1购买地址URM07-UART低功耗超声波测距模块x1购买地址Bluno Mega2560控制器x1购买地址3.5 TFT Mega 触摸显示屏x1购买地址
制作在制作之前,请先下载代码到Bluno Mega2560开发板上,点击下载程序源码,源码如下:#include<Servo.h>
#include "MultiLCD.h"
#include <SPI.h>
#include <Arduino.h>
#include <FlexiTimer2.h>
#define header_H    0x55 //帧头
#define header_L    0xAA //帧头
#define device_Addr 0x11 //模块地址
#define data_Length 0x00 //数据长度
#define get_Dis_CMD 0x02 //距离测量命令
#define checksum    (header_H+header_L+device_Addr+data_Length+get_Dis_CMD) //校验和
unsigned char Rx_DATA;
unsigned char CMD={header_H,header_L,device_Addr,data_Length,get_Dis_CMD,checksum};

bool clockwise1=false,clockwise2=false,sendFlag=true,angleFlag=true,Serial1Flag=false,dataFlag=false,drawFlag=false,clearFlag=false;
int degree_L=30,degree_S=1,angle=1;
int x,y,Dis,num=0,Plflag=0;
int x0=239,y0=0,r=239,r1=5;
int flag=0;
Servo myServo;
LCD_R61581 lcd;

void flash()
{
    if(Serial1.available())
    {
       Serial1Flag=true;
      }
   else
   {
         Serial1Flag=false;
      }
   /* if(flag>0)
      {
          myServo.write(degree_S);
          Sjudge();
      }*/
      // moveFan(degree_L,1);
      // Tjudge();
}

void setup() {
// put your setup code here, to run once:
   memset(Dis,0,sizeof(Dis));
   Serial.begin(19200);
   Serial1.begin(19200);
   lcd.begin();
   myServo.attach(9);
   //计算圆心为(239,0),半径为239的半圆每度对应圆周上的坐标
      for(int i=0;i<181;i++)
    {
         double d=(3.14/180)*i;
         x=int(x0-r*cos(d));
         y=int(r*sin(d));
      }
       for(int i=0;i<180;i++)
       {
         lcd.setFontSize(FONT_SIZE_MEDIUM);//set font size
         lcd.setColor(RGB16_GREEN);
         lcd.drawLine(x,y,x,y);
       }
      //drawMap();
      drawFan(31);
      FlexiTimer2::set(50,flash);
      FlexiTimer2::start();
}
void drawMap()
{
       lcd.setColor(RGB16_GREEN);
       lcd.drawCircle(x0,y0,50);
       lcd.drawCircle(x0,y0,100);
       lcd.drawCircle(x0,y0,150);
       lcd.drawCircle(x0,y0,200);
       for(int i=299;i<319;i++)
       {
          lcd.clearLine(i);
      }
       for(int i=0;i<=180;i+=30)
       {
         lcd.setColor(RGB16_GREEN);
          lcd.drawLine(x0,y0,x,y);
      }
}
void clearMap()
{
       lcd.setColor(0);
       lcd.drawCircle(x0,y0,50);
       lcd.drawCircle(x0,y0,100);
       lcd.drawCircle(x0,y0,150);
       lcd.drawCircle(x0,y0,200);
       for(int i=0;i<=180;i+=30)
       {
         lcd.setColor(RGB16_GREEN);
          lcd.drawLine(x0,y0,x,y);
      }
}
void clearFan(int i)
{
      if(i<30||i>150)
       return;
   for(int j=i+30;j>=i-30;j--)
   {
          lcd.setColor(0);
          lcd.drawLine(x0,y0,x,y);
      }
}
void drawFan(int i)
{
   if(i<30||i>150)
       return;
   for(int j=i-30;j<=i+30;j++)
   {
          lcd.setColor(RGB16_GREEN);
          lcd.drawLine(x0,y0,x,y);
      }
}
void moveFan(int d)
{
       if((d<30)||(d>150))
         return;
       if(clockwise2)
       {
               lcd.setColor(RGB16_GREEN);
               lcd.drawLine(x0,y0,x,y);
               lcd.setColor(0);
               lcd.drawLine(x0,y0,x,y);            
      }
      else
      {
               lcd.setColor(RGB16_GREEN);
               lcd.drawLine(x0,y0,x,y);
               lcd.setColor(0);
               lcd.drawLine(x0,y0,x,y);
          }
      /*   lcd.setColor(RGB16_GREEN);
         lcd.drawCircle(x0,y0,50);
         lcd.drawCircle(x0,y0,100);
         lcd.drawCircle(x0,y0,150);
         lcd.drawCircle(x0,y0,200);*/
         
    }
void drawPoint(int d)//取值范围d:
{
            if(Dis==0)
                return;
            unsigned int dis=Dis;
            double dd=(3.14/180)*d;
            double d1=(3.14/180)*(d-1);
            int xd1=int(x0-dis*cos(dd));
            int yd1=int(dis*sin(dd));
            int xd2=int(x0-dis*cos(d1));
            int yd2=int(dis*sin(d1));
            
            int xxx=int((xd1+xd2)/2);
            int yyy=int((yd1+yd2)/2);
            lcd.setColor(RGB16_RED);
            lcd.fillCircle(xxx,yyy,r1);
    }
   void clearPoint(int d)//d:
{
    if(Dis!=0)
    {
            int dis=Dis;
            double dd=(3.14/180)*d;
            double d1=(3.14/180)*(d-1);
            int xd1=int(x0-dis*cos(dd));
            int yd1=int(dis*sin(d));
            int xd2=int(x0-dis*cos(d1));
            int yd2=int(dis*sin(d1));
            
            int xxx=int((xd1+xd2)/2);
            int yyy=int((yd1+yd2)/2);
            lcd.setColor(0);
            lcd.fillCircle(xxx,yyy,r1);
      }
}
void sendCmd()
{
          for(int i=0;i<6;i++)
          {
             Serial1.write(CMD);
         }
}   
void angleParse()
{
   if(angle>180)
   {
         angle=180;
         angleFlag=false;
      }
      if(angle<1)
      {
          angle=1;
          sendFlag=false;
          angleFlag=true;
          dataFlag=true;
      }
}
void Anglechange(unsigned int dis)
{
       if(angleFlag)
       {
         Dis=dis;
         angle+=2;
         angleParse();
      }
      else
      {
         Dis=dis;
         angle-=2;
         angleParse();
       }
}
void dataGet()
{
    if(dataFlag==true)
    {
         return;
      }
   while(Serial1.available())
   {
         Rx_DATA=Serial1.read();
         if(num==1&&Rx_DATA!=0x55)
         {
             num=0;
             Plflag++;
         }
         if(num==2&&Rx_DATA!=0xAA)
         {
             num=0;
             Plflag++;
         }
         if(num==2&&Rx_DATA==0xAA&&Rx_DATA==0x55)
         {
             int v=((Plflag%8>0)?1:0);
             v+=Plflag/8;
             for(int j=0;j<v;j++)
             {
               Anglechange(0);
             }
      
         }
            if(num==8)
            {
                  num=0;
                  unsigned char t=Rx_DATA+Rx_DATA+Rx_DATA+Rx_DATA+Rx_DATA+Rx_DATA+Rx_DATA;
                  if(t==Rx_DATA)
                  {
                         unsigned int dis=((Rx_DATA<<8)|Rx_DATA);
                         if(dis>220||dis<0)
                            dis=0;
                         Anglechange(dis);
                  }
                  else
                  {
                        Anglechange(0);
                      }
                }
   }
}

void Sjudge()
{
      if(clockwise1)
      {
          degree_S-=2;
          if(degree_S<1)
          {
             degree_S=1;
             clockwise1=false;
            }
      }
       else
       {
         degree_S+=2;
         if(degree_S>180)
         {
            degree_S=180;
            clockwise1=true;
            }
      }
    }

void Tjudge()
{
   if(clockwise2)
      {
          degree_L--;
          if(degree_L<30)
          {
             degree_L=30;
             clockwise2=false;
            }
      }
       else
       {
         degree_L++;
         if(degree_L>150)
         {
            degree_L=150;
            clockwise2=true;
            }
      }
}
void loop() {
// put your main code here, to run repeatedly:
       switch(flag)
       {
          case 0:
               sendCmd();
               myServo.write(degree_S);
               Sjudge();
               moveFan(degree_L);
               Tjudge();
               break;
          case 1:
                if(degree_S!=1)
                {
                     myServo.write(degree_S);
                     Sjudge();
                  }
               moveFan(degree_L);
               Tjudge();
               break;
          case 2:
               clearFan(30);
               drawMap();
               for(int i=1;i<181;i++)
               {
                  drawPoint(i);
                  }
                  delay(1000);
                  drawFlag=true;
               break;
          case 3:
                  for(int i=1;i<181;i++)
                  {
                     Dis=0;
                  }
                  lcd.clear(0,0,479,319);
                   for(int i=0;i<180;i++)
                   {
                        lcd.setColor(RGB16_GREEN);
                        lcd.drawLine(x,y,x,y);
                      }
                  drawFan(30);
                  clearFlag=true;
               /*moveFan(degree_L,1)
               clearPoint(degree_L-30+1)
               clearPoint(degree_L+30)
                  Tjudge();*/
                  
               break;
          default:
               break;
      
      }
       if(sendFlag==false)
       {
         flag=1;
      }
      if(degree_S==1&°ree_L==30&&clockwise2==false&&dataFlag==true)
      {
            flag=2;
         }
         if(drawFlag==true)
         {
             flag=3;
          }
          if(clearFlag)
          {
            sendFlag=true;
            drawFlag=false;
            dataFlag=false;
            clearFlag=false;
            flag=0;
            }
            if(Serial1Flag)
            {
                dataGet();
            }
}
将Mega2560控制板的VCC、GND、D9引脚用导线引出,并打上热熔胶,并将SG90舵机固定在Mega2560控制板的背面。
将超声波模块的引脚用杜邦线连接到3.5寸屏的UART1串口(这里要注意超声波的正负极哦~,不要连错了),连接好SG90舵机和Mega2560,SG90的橙、红、棕引线分别对应Mega2560的D9、VCC、GND引脚。
然后插上USB线,就可以测到数据啦,哈哈,已经可以从屏幕上看到障碍物了~
最后,为雷达制作一个外壳,起保护作用,那就用硬纸板加工吧。扫描的效果看着还是很炫酷哦,本人终于圆梦了啦,哈哈。


Forgotten 发表于 2018-4-27 17:56:37

超炫酷的,用激光测距是不是能得到更高的精度和刷新率

青夏 发表于 2018-4-28 16:18:16

Forgotten 发表于 2018-4-27 17:56
超炫酷的,用激光测距是不是能得到更高的精度和刷新率

我觉得是的,不过需要频率更高一些。

Grey 发表于 2018-4-28 17:04:40

青夏 发表于 2018-4-28 16:18
我觉得是的,不过需要频率更高一些。
可以用这种低成本ToF方案https://www.dfrobot.com.cn/goods-1643.html

digi_cow 发表于 2018-4-29 19:07:28

满足儿时梦想!{:5_157:}

gray6666 发表于 2018-5-3 08:49:46

炫酷的科技。。。。。。。。。。。。。。

阿斗 发表于 2018-5-3 09:08:05

{:5_118:}{:5_118:}{:5_118:}

Chocho2017 发表于 2018-5-4 10:49:44

Forgotten 发表于 2018-4-27 17:56
超炫酷的,用激光测距是不是能得到更高的精度和刷新率

对的,但是激光的贵一些。

安卓机器人 发表于 2018-5-14 21:38:20

{:5_148:}碉 碉 碉

Chocho2017 发表于 2018-5-15 11:02:36

安卓机器人 发表于 2018-5-14 21:38
碉 碉 碉

谢谢。

大道必成 发表于 2019-5-14 21:38:32

真精华!!!!!!

岑剑伟 发表于 2021-12-20 15:28:48

大佬的梦早的都完成了,我还在发梦
页: [1]
查看完整版本: 【chocho精选】报告!前方发现mega2560超声波雷达