一、前言
阅读此文前请戳这个视频观看使用Arduino超声波传感器模拟雷达扫描教程,先了解效果,有直观感受再来看下文。
图1雷达扫描效果二、硬件准备
图2所需硬件如图2所示,需要Arduino主板(最好加上扩展板)1块、超声波传感器1个、伺服电机(舵机)1个,液晶显示屏(可选)。
我将超声波传感器的Trig、Echo分别连接在扩展板的4、5号引脚,将伺服电机连接在扩展板的9号引脚上,为了简化程序,后续我没有使用液晶显示屏,请你自行添加相关程序。
三、软件准备
1、ArduinoIDE1.8.9
图3ArduinoIDE2、Processing3.3.5
图4Processing备注:
1、上述软件版本是我自己调试成功的版本,略低版本可能会有兼容问题,请注意你的软件版本号;
2、如果Processing的程序编辑器内不能输入、显示中文,请在“文件”、“偏好设定”里,选择“启用复杂字体输入”并在“编辑器和控制台字体”中选择“宋体”即可显示或输入中文;
图5修改Processing偏好设定3、如果Processing的展示界面不能显示中文,请在程序里装载中文字库,如图6第5、19、20行代码所示。
图6装载中文字库四、编写程序
程序分两步实现:
第一步:使用ArduinoIDE,编写伺服电机度循环摇头、获取超声波传感器返回值(与障碍物的距离值)、向串口输出伺服电机转动的角度和超声波传感器的距离值(注意要和Processing中获取串口值的格式一致),代码如下(请注意修改超声波传感器、伺服电机的引脚号为你自己的实际引脚号):
#includestdio.h#includeServo.hServomServo;//创建一个舵机控制对象//当前角度intmAngleNum=0;//当前是正向旋转还是反向旋转charmFront=0;//超声波测距引脚constintmTrigPin=4;constintmEchoPin=5;//当前距离intmDistance=0;//像串口发送数据发送到processingvoidsendStatusToSerial();//测距voidranging();voidsetup(){//putyoursetupcodehere,torunonce:Serial.begin();mServo.attach(9);//该舵机由arduino第9脚控制pinMode(mTrigPin,OUTPUT);//要检测引脚上输入的脉冲宽度,需要先设置为输入状态pinMode(mEchoPin,INPUT);}voidloop(){//putyourmaincodehere,torunrepeatedly://多角度设置mServo.write(-mAngleNum);//超声波测距ranging();//发数据sendStatusToSerial();delay(60);if(mFront==0){mAngleNum++;if(mAngleNum){mFront=1;}}else{mAngleNum--;if(mAngleNum0){mFront=0;}}}//发送当前状态到串口voidsendStatusToSerial(){charmAngleStr[6];charmDistanceStr[6];sprintf(mAngleStr,%d,mAngleNum);sprintf(mDistanceStr,%d,mDistance);delayMicroseconds(2);Serial.print(mAngleStr);Serial.print(,);Serial.print(mDistanceStr);Serial.print(.);delay(50);}//测距voidranging(){//产生一个10us的高脉冲去触发TrigPindigitalWrite(mTrigPin,LOW);//低高低电平发一个短时间脉冲去TrigPindelayMicroseconds(2);digitalWrite(mTrigPin,HIGH);delayMicroseconds(10);digitalWrite(mTrigPin,LOW);mDistance=pulseIn(mEchoPin,HIGH)/58.0;//将回波时间换算成cm}
第二步:使用Processing,编写一图7的界面、获取串口发送过来的角度、距离值,将其转换旋转指针的动作、屏幕中间的红色提示、屏幕下方的文字提示等,具体代码如下:
图7模拟雷达界面图importprocessing.serial.*;importjava.awt.event.KeyEvent;importjava.io.IOException;PFontfont;SerialmyPort;Stringangle=;Stringdistance=;Stringdata=;StringnoObject;floatpixsDistance;intiAngle,iDistance;intindex1=0;intindex2=0;PFontorcFont;voidsetup(){size(,);//这个分辨率自己根据你的电脑的配置和显示屏幕配置进行更改。smooth();font=createFont(宋体.vlw,48);textFont(font);myPort=newSerial(this,COM5,);//这个串口号一定要更改。myPort.bufferUntil(.);}voiddraw(){fill(98,,31);noStroke();fill(0,4);rect(0,0,width,height-height*0.);fill(98,,31);drawRadar();drawLine();drawObject();drawText();}voidserialEvent(SerialmyPort){data=myPort.readStringUntil(.);data=data.substring(0,data.length()-1);index1=data.indexOf(,);angle=data.substring(0,index1);distance=data.substring(index1+1,data.length());iAngle=int(angle);iDistance=int(distance);}voiddrawRadar(){pushMatrix();translate(width/2,height-height*0.);noFill();strokeWeight(2);stroke(98,,31);//drawsthearclinesarc(0,0,(width-width*0.),(width-width*0.),PI,TWO_PI);arc(0,0,(width-width*0.27),(width-width*0.27),PI,TWO_PI);arc(0,0,(width-width*0.),(width-width*0.),PI,TWO_PI);arc(0,0,(width-width*0.),(width-width*0.),PI,TWO_PI);//drawstheanglelinesline(-width/2,0,width/2,0);line(0,0,(-width/2)*cos(radians(30)),(-width/2)*sin(radians(30)));line(0,0,(-width/2)*cos(radians(60)),(-width/2)*sin(radians(60)));line(0,0,(-width/2)*cos(radians(90)),(-width/2)*sin(radians(90)));line(0,0,(-width/2)*cos(radians()),(-width/2)*sin(radians()));line(0,0,(-width/2)*cos(radians()),(-width/2)*sin(radians()));line((-width/2)*cos(radians(30)),0,width/2,0);popMatrix();}voiddrawObject(){pushMatrix();translate(width/2,height-height*0.);strokeWeight(9);stroke(,10,10);//redcolorpixsDistance=iDistance*((height-height*0.)*0.);if(iDistance40){line(pixsDistance*cos(radians(iAngle)),-pixsDistance*sin(radians(iAngle)),(width-width*0.)*cos(radians(iAngle)),-(width-width*0.)*sin(radians(iAngle)));}popMatrix();}voiddrawLine(){pushMatrix();strokeWeight(9);stroke(30,,60);translate(width/2,height-height*0.);line(0,0,(height-height*0.12)*cos(radians(iAngle)),-(height-height*0.12)*sin(radians(iAngle)));popMatrix();}voiddrawText(){pushMatrix();if(iDistance40){noObject=检测范围外;}else{noObject=检测范围内;}fill(0,0,0);noStroke();rect(0,height-height*0.,width,height);fill(98,,31);textSize(25);text(10cm,width-width*0.,height-height*0.);text(20cm,width-width*0.,height-height*0.);text(30cm,width-width*0.,height-height*0.);text(40cm,width-width*0.,height-height*0.);textSize(28);text(对象:+noObject,width-width*0.,height-height*0.);text(角度:+iAngle+°,width-width*0.48,height-height*0.);text(距离:,width-width*0.26,height-height*0.);if(iDistance40){text(+iDistance+cm,width-width*0.,height-height*0.);}textSize(25);fill(98,,60);translate((width-width*0.)+width/2*cos(radians(30)),(height-height*0.)-width/2*sin(radians(30)));rotate(-radians(-60));text(30°,0,0);resetMatrix();translate((width-width*0.)+width/2*cos(radians(60)),(height-height*0.)-width/2*sin(radians(60)));rotate(-radians(-30));text(60°,0,0);resetMatrix();translate((width-width*0.)+width/2*cos(radians(90)),(height-height*0.)-width/2*sin(radians(90)));rotate(radians(0));text(90°,0,0);resetMatrix();translate(width-width*0.+width/2*cos(radians()),(height-height*0.)-width/2*sin(radians()));rotate(radians(-30));text(°,0,0);resetMatrix();translate((width-width*0.)+width/2*cos(radians()),(height-height*0.)-width/2*sin(radians()));rotate(radians(-60));text(°,0,0);popMatrix();}
图8我的模仿作品总之,实现模拟雷达扫描效果,只需要能将角度、距离值发送到串口,然后使用Processing将获得的数据模拟出来即可,这种方法可以推而广之,将其他传感器的返回值也发送给Processing,将返回值图形化,说不定你也可以做出其他不一样的创意出来。
好好学习,天天向上,初始化工作室和你一起学习Arduino知识,快去动手做吧,做出不一样的雷达扫描效果分享给大家。