這篇文章來源于DevicePlus.com英語網(wǎng)站的翻譯稿。
點擊此處跳轉(zhuǎn)至本文第一部分 >
這是CMUcam5 Pixy簡介的第二部分。如果您對PixyMon不太熟悉,請先回顧 CMUcam5 Pixy視覺相機傳感器簡介。在第一部分中,我介紹了Pixy的基礎(chǔ)知識,解釋了hello_world代碼,并創(chuàng)建了一個簡單的伺服驅(qū)動的應(yīng)用程序。在本教程中,我將進一步探索Pixy的應(yīng)用,創(chuàng)建一個球平衡梁。通過一個伺服來設(shè)置平衡梁的角度,使球停留在中間,當然,Pixy相機傳感器會對球進行追蹤。
Arduino Uno (您可以使用任何 Arduino)
CMUcam5 Pixy 相機
伺服電機 (S06NF)
木片和螺絲
數(shù)據(jù)線(用于相機USB MINI 以及Uno USB B)
用于伺服的5V外部電源(!警告!如果您將伺服連接到Arduino通過USB進行供電,您的Arduino將會被燒壞)
軟件
Arduino IDE 1.6.9
PixyMon 軟件 (https://cmucam.org/projects/cmucam5/wiki/Install_PixyMon_on_Windows_Vista_7_8)
PixyMon 用于 Arduino 的庫(https://cmucam.org/projects/cmucam5/wiki/Latest_release)
Processing 3.1.1 (https://processing.org/download/?processing)
Processing的簡單介紹
Processing是非常有用又靈活的一款軟件。它主要用于視覺藝術(shù)和科技領(lǐng)域的視覺語言。這款軟件具有100多個庫,可支持各種項目。它的文檔非常齊全,提供了許多使用指南,涵蓋了從編程基礎(chǔ)到可視化等各種主題。它能夠支持所有操作系統(tǒng)(GNU/Linux, Mac OS X, 和 Windows)。該軟件的設(shè)計幾乎和Arduino IDE相同。
今天,我們將使用Processing,通過串行通信實現(xiàn)與Arduino之間的通信。
圖1:Processing界面
項目概況
在此項目中,我將制作一個球平衡梁,一個用木頭制成的“通道”將會像一桿秤那樣使球保持平衡(圖2)。平衡梁44cm寬,3cm高。我把它制造的像通道一樣狹窄,使我們所追蹤的球不會掉落出去。
我使用S06NF伺服電機來移動整個平衡梁,該電機由Arduino進行控制。之后我們會看一下在本教程后面部分的代碼?,F(xiàn)在,我已經(jīng)將伺服放置在了距離平衡梁左端?的位置。
圖2:S06NF STD 伺服電機/ ?RobotShop inc.
伺服將上下移動平衡梁,同時,球也會沿著該路徑移動。
圖3:平衡梁上下移動
數(shù)碼相機將會放置在平衡梁上。我將相機的視野范圍設(shè)置為僅限于平衡梁。這樣,相機就會只追蹤球,不追蹤任何其他物體了。
平衡梁結(jié)構(gòu)
首先,我們需要一些用于構(gòu)建平衡梁的材料。我將要使用的是一種簡單的XXMM木材(20cm x 27cm)。我用圓鋸來切割木材,但是您可以使用現(xiàn)有的任何類型的鋸來完成切割,只要能夠保障切割面平整、均勻即可。
圖4:XXMM木材
請記住,只有使用正確的工具才能夠制造出完美的平衡梁!我使用的是一把錘子、一把直尺、釘子、砂紙、熱膠、一個鉆頭和一把鋸子。
圖5:工具
首先,我將制造一個通道,使球能夠在其中左右移動。通道的側(cè)面由四塊木板組成(每個21cm x 3cm)。通道在高度方向的兩端將由兩塊木板(4cm x 3cm)封接。底座的尺寸是42cm x 3cm x 1cm。
我使用15mm大帽釘來連接零部件。
圖6:封閉通道
在通道中間建立傾斜點有很多種方法。我使用了一種非常簡單的方法,因為成本最低且最容易實現(xiàn)。我用了一個長釘子,兩個像軸承一樣的小管子,先標記了通道的中心點,然后將這些小軸承熱粘合到該中心點,再插入釘子。
圖7:用于構(gòu)建傾斜點的釘子和管子
為了設(shè)置傾斜點,我們還需要為釘子制作支架。我用了兩塊8cm x 2cm的木板,如圖8所示。我還制作了一個小平臺,可以將所有東西放置在一起,尺寸為12cm x 4.5cm。
圖8:傾斜點支架
我使用了一小塊木材來安裝伺服并將其架起。
圖9:安裝在木板上的伺服
在本教程中我使用的是Arduino UNO,但是您也可以使用其他具有SPI連接器的Arduino來連接到Pixy相機。
連接所有部件
一旦構(gòu)建完成,下一步就是將Pixy相機連接到Arduino,然后再連接到伺服。原理圖與 CMUcam5 Pixy視覺相機傳感器簡介中的相同。我仍然使用外部5V電源為伺服供電。
!警告!不要忘記連接接地端。如果沒有將電源、伺服和Arduino接地端相連接,伺服將會失控!
圖10:接線圖
接下來,我需要在平衡梁結(jié)構(gòu)上方的某個位置設(shè)置Pixy,以便它可以隨時檢測到球的位置。調(diào)整設(shè)置使其僅可以對球進行檢測。請參考第一部分進行設(shè)置。
圖11:Pixy視覺
現(xiàn)在,讓我們來看一些代碼。為了檢測伺服是否工作正常,我修改了中間、最右邊和最左邊的角度,使其適合于我的結(jié)構(gòu)。
#include uint8_t leveled = 110; //middle positon for s1 to keep the board leveled uint8_t far_right = 180; //far left positon for s1 to keep the board leveled uint8_t far_left = 0; //far right positon for s1 to keep the board levele Servo s; void setup(){ s.write(leveled); delay(2000); s.write(far_right); delay(2000); s.write(far_left); delay(2000); } void loop(){ }
當然,您可以根據(jù)自己的喜好來調(diào)整變量。
之前,我介紹了一個名叫Processing的軟件。我將使用它通過串行通信來實現(xiàn)與Arduino的通信。
Arduino 代碼
簡單的串行通信:
#include #include char val; // Data received from the serial port int ledPin = 13; // Set the pin to digital I/O 13 void setup() { pinMode(ledPin, OUTPUT); // Set pin as OUTPUT Serial.begin(9600); // Start serial communication at 9600 bps } void loop() { if (Serial.available()) { // If data is available to read, val = Serial.read(); // read it and store it in val } if (val == '1') { // If 1 was received digitalWrite(ledPin, HIGH); // turn the LED on } else { digitalWrite(ledPin, LOW); // otherwise turn it off } delay(10); // Wait 10 milliseconds for next reading }
Processing 代碼
import processing.serial.*; Serial myPort; // Create object from Serial class void setup() { size(200,200); //make our canvas 200 x 200 pixels big String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port myPort = new Serial(this, portName, 9600); } void draw() { if (mousePressed == true) { //if we clicked in the window myPort.write('1'); //send a 1 println("1"); } else { //otherwise myPort.write('0'); //send a 0 } }
改代碼創(chuàng)建了一個200×200像素的窗口并初始化串行端口。draw()空函數(shù)用于檢查是否在窗口上按下了鼠標(如果按下寫入1,沒有按下則寫入0)。
現(xiàn)在,我們來測試代碼。點擊運行,然后嘗試點擊窗口中任意位置,這時您的LED燈應(yīng)發(fā)生閃爍,這就表示著一切工作正常!
圖12:Processing 和 Arduino代碼的基本測試
使用Processing編程
我獲取了伺服的相關(guān)值,并在Processing中對其進行了處理,所以產(chǎn)生了一個類似于下圖所示的圖片。
圖13:示例圖片
請用以下代碼創(chuàng)建圖像:
import processing.serial.*; Serial myPort; // The serial port int xPos = 1; // horizontal position of the graph float inByte = 0; void setup () { // set the window size: size(400, 300); // List all the available serial ports // if using Processing 2.1 or later, use Serial.printArray() println(Serial.list()); // I know that the first port in the serial list on my mac // is always my Arduino, so I open Serial.list()[0]. // Open whatever port is the one you're using. myPort = new Serial(this, Serial.list()[0], 9600); // don't generate a serialEvent() unless you get a newline character: myPort.bufferUntil('n'); // set inital background: background(0); } void draw () { // draw the line: stroke(127, 34, 255); line(xPos, height, xPos, height - inByte); // at the edge of the screen, go back to the beginning: if (xPos >= width) { xPos = 0; background(0); } else { // increment the horizontal position: xPos++; } } void serialEvent (Serial myPort) { // get the ASCII string: String inString = myPort.readStringUntil('n'); if (inString != null) { // trim off any whitespace: inString = trim(inString); // convert to an int and map to the screen height: inByte = float(inString); println(inByte); inByte = map(inByte, 0, 1023, 0, height); } }
Arduino 代碼:
#include #include #include #include //37 164 288 uint8_t leveled = 110; //middle positon for s1 to keep the board leveled uint8_t far_right = 180; //far left positon for s1 to keep the board leveled uint8_t far_left = 0; //far right positon for s1 to keep the board levele int current_pos = leveled; int percentage,var,_percen; Servo s; Pixy pixy; void test_board(){ while(Serial.read() != 'b'); Serial.write("Starting test"); s.write(leveled); delay(2000); s.write(far_right); delay(2000); s.write(far_left); delay(2000); Serial.write("Finished test, press any key to continue"); while(Serial.read() != 'c'); s.write(current_pos); Serial.write("Continued"); } void setup() { Serial.begin(9600); s.attach(9); pixy.init(); while (!Serial); //test_board(); s.write(current_pos); } void _servo(unsigned char side,int var){ //by the % we get how "hard" we need to wip :D var = var - 90; if(side == 'L'){ //Serial.write("LEFT"); //90 180 _percen = 90 + var; s.write(_percen); }else{ //Serial.write("RIGHT"); //0 90 _percen = 90 - var; s.write(_percen); } } void loop() { static int i = 0; int j; uint16_t blocks; char buf[32]; // grab blocks! blocks = pixy.getBlocks(); // If there are detect blocks, print them! if (blocks) { i++; // do this (print) every 50 frames because printing every // frame would bog down the Arduino if (i%1 ==0) { //sprintf(buf, "Detected %d:n", blocks); //Serial.print(buf); for (j=0; j= 0){ // Serial.write("LEFT"); var = percentage / 0.4; _servo('L',var); }else if(percentage >= 60 && percentage <= 110){ //Serial.write("RIGHT"); var = (percentage - 60) / 0.5; _servo('R',var); }else{ //Serial.write("MIDDLE"); } } } } }
代碼釋義
我將x的位置從Pixy轉(zhuǎn)換為0-100%,并由此了解球的具體位置。通過獲取球的位置,我可以調(diào)整伺服轉(zhuǎn)速。如果球的位置<=10%,伺服會轉(zhuǎn)得更快來維持平衡;如果在~40%附近,伺服會以很低的轉(zhuǎn)速來維持平衡。想要一直保持平衡是比較棘手的,我們可以改進算法以使其更加精確。
以下是一些有益于提升的建議:
? 嘗試多種算法
? 有多種類型的數(shù)學(xué)算法可以進行計算。我至少嘗試了兩到三種,但是最后決定選擇該算法。我建議您自己來編寫算法,以更好地掌握這種平衡的方法。
? 更好的硬件
? 對于本項目來說,沒有什么材料可稱得上是完美的,木材就更差得遠了。如果我擁有及時可用的資源,那我會選擇用金屬來建造它,這樣整個項目將會更加穩(wěn)定和精確。
? 變得更快
? 我們?nèi)绾巫龅绞蛊涓斓鼗謴?fù)平衡?我在這里使用了一個簡單的伺服。我們可以將其替換為UART或者AX-12之類的伺服,它們會強大、快速得多。速度也與算法有關(guān)。同樣,我建議您嘗試不同的算法,以找到適用于您的目的的算法。
有許多項目使用類似的概念來對平衡某物體。除了Pixy,您還可以將OpenCV與任何網(wǎng)絡(luò)相機一起使用來檢測目標和顏色。除了Processing,還有Max/MSP版本5。您可以使用距離傳感器、壓力傳感器等。因此,有多種方式可以幫助您對該項目進行提升,使其更加堅固、穩(wěn)定和更快。
審核編輯黃宇
-
傳感器
+關(guān)注
關(guān)注
2545文章
50445瀏覽量
751031 -
Arduino
+關(guān)注
關(guān)注
187文章
6457瀏覽量
186501
發(fā)布評論請先 登錄
相關(guān)推薦
評論