有趣的CMUcam5_Pixy机器人 CMUcam5_Pixy摄像头是Charmed实验室联合卡内基梅隆大学推出的一款开源机器视觉传感器,它强大的颜色别功能以及追踪色块功能远远超出了我的想象。 file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg 下面我们就一起动手来制作这么一款有趣的CMUcam5_Pixy机器人吧! file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpg 一. Pixymon 首先,要认识这款视觉传感器,必须下载它的一个附属软件,名字叫做Pixymon。 你需要一根USBmini数据线,用来连接你的电脑和Pixy。Pixy产品中并没有包含这根线。
file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image006.jpg
下载最新版本(0.1.41)的PixyMon: http://pan.baidu.com/s/1dDpDlvV 。当你下载完成后,双击开始安装,安装过程中,暂时不要将Pixy插在电脑上,这期间会预先安装驱动程序。并且会有“Pre-installing device drivers. Please bepatient!”的提示,等一段时间后,你将看到下面的对话框:
file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image008.jpg 直接点击“安装”。系统会等段时间,并且再次弹出一样的对话框。(Pixy需要安装两个硬件驱动。)如果你看到了新对话框,直接点击“安装”。等待Windows的安装,这可能要到几分钟,耐心等待。
然后就安装完成了。 现在将Pixy通过USB mini数据线连接到电脑上。
file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image010.jpg
file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image012.jpg 打开Pixymon界面后,进入当前页面进行颜色标记。file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image014.jpg 然后就能识别所标记不同颜色的物体了。 file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image016.jpg。 二.让Pixy与Arduino连接 想让Pixy与Arduino进行通讯,使用Pixy自带的数据线连接Pixy到Arduino; file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image018.jpg 接下来,下载Arduino库在这里:http://pan.baidu.com/s/1dDpDlvV ,打开Arduino IDE并且通过菜单Sketch->ImportLibrary导入Pixy库文件,然后浏览到Pixy库文件解压的地方。
然后,通过菜单File➜Examples➜Pixy载入“hello_world”例子。上传代码到Arduino并且打开Serial Monitor(串口监视器)。你应该可以看到一些类似于下面的数据信息:
<pre>Detected 1: block 0: sig: 1 x: 159 y:109 width: 61 height: 61Detected 1: block 0: sig: 1 x: 173 y: 114 width: 60height: 61Detected 1: block 0: sig: 1 x: 146 y: 111 width: 70 height: 65...</pre> 。 注意,这个例子中,如果Pixy运行了默认的固件,并且一个物体被识别才会打印这些信息。 Arduino API 在Arduino中使用Pixy是非常简单的,你只需要包含SPI和Pixy的头文件:
<pre>
#include <SPI.h>
#include <pixy.h>
</pre>
并且在setup()和loop()函数外面创建一个全局的Pixy实例变量:
<pre>
Pixy pixy;
</pre>
API包含一个函数:getBlocks(),这个函数将返回Pixy所识别的物体数量。然后你就可以通过pixy.blocks[]的数组得到每个识别到的物体数据(每个数组成员对应一个被识别的物体)。每个成员(i)包含下列元素:
pixy.blocks.signature:被识别物体的标记编号;
pixy.blocks.x:被识别物体中心位置在x方向的坐标;
pixy.blocks.y:被识别物体中心位置在y方向的坐标;
pixy.blocks.width:被识别物体的宽度(1~320);
pixy.blocks.height:被识别物体的高度(1~200);
pixy.blocks.print():一个成员函数用来打印被识别物体的信息到串口上。 三.拼装机器人 机器人运动机构由两个360度舵机带动前轮运动; file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image020.jpg。 机器人头部采用一个180度舵机转动能够实现Pixy上下追踪物块,并且Pixy有专门的安装平台可以用来固定在舵机支架上; file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image022.jpg。 四.电控部分 电控部分主要由一块Arduino R3板(1),一块稳压扩展板(2),一块IO扩展板(3)构成,从上往下分别为(1)(2)(3)。file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image024.jpgfile:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image026.jpgfile:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image028.jpg 电控部分由一块8.4伏的锂电池供电,通过稳压扩展板降压为5.2伏后给3个舵机供电,并给Pixy供电。 下面我们来看一下Pixy的连线接口 SPI:这是默认的输出端口,使用了三根心(IO口的第Pin1、3、4)并且用于与Arduino通讯;
I2C:两线接口(IO口的Pin5和9),可以支持一个主机与127个从机的通讯(多大127个Pixy);
UART:这是普通的串口(IO口的Pin1和4)。Pixy通过Pin1(输入)接受数据,Pin4(输出)发送数据;
模拟/数字 X:这种方式将在Pin3口输出0~3.3V的模拟电压,表示监测到的最大物体的X值;
模拟/数字 Y:这种方式将在Pin3口输出0~3.3V的模拟电压,表示监测到的最大物体的Y值;
file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image030.jpg 下面为Pixy与Arduino的接线方式,file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image032.jpg。 成果展示 终于在我的努力下,CMUcam5_Pixy机器人终于可以随着物块移动了,下面便是我的代码。 #include <Servo.h> #include <SPI.h> //Pixy库函数 #include <Pixy.h> Pixy pixy; Servo myservo_1; //定义舵机 Servo myservo_2; Servo myservo_3; int upsize=50; int downsize=150; int center=90; void setup() { Serial.begin(9600); Serial.print("Starting...\n"); myservo_1.attach(9); //定义舵机的引脚 myservo_2.attach(8); myservo_1.write(90); myservo_2.write(90); myservo_3.attach(7); myservo_3.write(center); pixy.init(); } void advance() //前进 { myservo_1.write(0); myservo_2.write(180); } void back() //后退 { myservo_1.write(160); myservo_2.write(20); } void left() //左转 { myservo_1.write(0); myservo_2.write(90); } void right() //右转 { myservo_1.write(90); myservo_2.write(180); } void Stop() //停止 { myservo_1.write(90); myservo_2.write(90); } void loop() { static int i =0; int j; uint16_tblocks; char buf[32]; blocks =pixy.getBlocks(); //读取数值 Serial.print(pixy.blocks[0].width); Serial.print(" "); Serial.print(pixy.blocks[0].height); Serial.print(" "); Serial.print(pixy.blocks[0].x); Serial.print(" "); Serial.println(pixy.blocks[0].width * pixy.blocks[0].height); //通过物块面积追踪 if(blocks) { if(pixy.blocks[0].x<200&&pixy.blocks[0].x>100) { if(pixy.blocks[0].width * pixy.blocks[0].height<55000) advance(); elseif(pixy.blocks[0].width * pixy.blocks[0].height>55000) back(); } if(pixy.blocks[0].x>200) { right(); } if(pixy.blocks[0].x<100) { left(); } if(pixy.blocks[0].width * pixy.blocks[0].height>500) { if (pixy.blocks[0].y < 90 &¢er> upsize) { center-=2; delay(2); } if(pixy.blocks[0].y>120 && center<downsize) { center+= 2; delay(2); } } } myservo_3.write(center); }
|