在當(dāng)今的情況下,我們都忙于工作,沒(méi)有時(shí)間正確打掃房子。這個(gè)問(wèn)題的解決方法很簡(jiǎn)單,你只需要買一個(gè)家用吸塵器機(jī)器人,比如irobot roomba,它會(huì)通過(guò)按下一個(gè)按鈕來(lái)清潔你的房子。但是這些商業(yè)產(chǎn)品有一個(gè)共同的問(wèn)題,那就是成本。所以今天,我們決定做一個(gè)簡(jiǎn)單的掃地機(jī)器人, 與市面上的商業(yè)產(chǎn)品相比,它不僅制作簡(jiǎn)單,而且成本非常低。經(jīng)常閱讀的讀者可能還記得我們很久以前制造的Arduino 吸塵機(jī)器人,但那個(gè)機(jī)器人非常笨重,需要一個(gè)大的鉛酸電池才能移動(dòng)。新的Arduino 吸塵器 我們將在這里建造將更緊湊,更實(shí)用。最重要的是,該機(jī)器人將配備超聲波傳感器和紅外接近傳感器。超聲波傳感器將允許機(jī)器人避開(kāi)障礙物,以便它可以自由移動(dòng),直到房間被正確清潔,接近傳感器將幫助它避免從樓梯上摔下來(lái)。
構(gòu)建基于 Arduino 的地板清潔機(jī)器人所需的材料
由于我們使用非常通用的組件來(lái)構(gòu)建真空吸塵器機(jī)器人的硬件部分,因此您應(yīng)該能夠在當(dāng)?shù)氐膼?ài)好商店中找到所有這些組件。這是所需材料的完整列表以及所有組件的圖像。
Arduino Pro 迷你 - 1
HC-SR04 超聲波模塊 - 3
L293D 電機(jī)驅(qū)動(dòng)器 - 1
5Volt N20 電機(jī)和安裝支架 - 2
N20 電動(dòng)車輪 - 2
開(kāi)關(guān) - 1
LM7805 穩(wěn)壓器 - 1
7.4V 鋰離子電池 - 1
紅外模塊 - 1
穿孔板 - 1
腳輪 - 1
中密度纖維板
通用便攜式吸塵器
便攜式吸塵器
在組件需求部分,我們談到了便攜式真空吸塵器,下圖正是展示了這一點(diǎn)。這是一款來(lái)自亞馬遜的便攜式吸塵器。這帶有一個(gè)非常簡(jiǎn)單的機(jī)制。它在底部有三個(gè)部分(一個(gè)用于儲(chǔ)存灰塵的小室,中間部分包括電機(jī)、風(fēng)扇和頂部的電池插座(有一個(gè)電池蓋或蓋子)。它有一個(gè)直流電機(jī)和一個(gè)風(fēng)扇。這個(gè)電機(jī)通過(guò)一個(gè)簡(jiǎn)單的開(kāi)關(guān)直接連接到 3V(2*1.5volt AA 電池)。由于我們用 7.4V 電池為機(jī)器人供電,我們將切斷內(nèi)部電池的連接并從 5V 供電電源。所以,我們?nèi)サ袅怂胁槐匾牟考皇O聝删€電機(jī)。你可以在下圖中看到。
HC-SR04 超聲波傳感器模塊
為了檢測(cè)障礙物,我們使用了流行的HC-SR04 超聲波距離傳感器 ,也可以稱之為避障傳感器。工作很簡(jiǎn)單,首先,發(fā)射器模塊發(fā)送一個(gè)超聲波,該超聲波在空氣中傳播,遇到障礙物,然后反彈回來(lái),接收器接收到該波。通過(guò)用Arduino計(jì)算時(shí)間,我們可以確定距離。在之前關(guān)于基于 Arduino 的超聲波距離傳感器項(xiàng)目的文章中,我們已經(jīng)非常深入地討論了這種傳感器的工作原理。如果您想了解有關(guān) HC-SR04 超聲波距離傳感器模塊的更多信息,可以查看。
用于樓梯檢測(cè)的地板傳感器(IR 傳感器)
在功能部分,我們已經(jīng)討論了機(jī)器人可以檢測(cè)樓梯并防止自己跌倒的功能。為此,我們使用了IR Sensor。我們將在IR 傳感器和 Arduino之間建立一個(gè)接口。IR Proximity Sensor的工作原理很簡(jiǎn)單,它有一個(gè) IR LED 和一個(gè)光電二極管,IR LED 發(fā)出 IR 光,如果有任何障礙物擋在發(fā)出的光的前面,它就會(huì)被反射,并檢測(cè)到反射光由光電二極管。但是反射產(chǎn)生的電壓會(huì)非常低。為了增加它,我們可以使用運(yùn)算放大器比較器,我們可以放大并獲得輸出。紅外模塊具有三個(gè)引腳 - Vcc、接地和輸出。通常,當(dāng)傳感器前面有障礙物時(shí),輸出會(huì)變低。所以,我們可以用它來(lái)檢測(cè)地板。如果在一瞬間,我們從傳感器檢測(cè)到高電平,我們可以停止機(jī)器人,將其轉(zhuǎn)回或做任何我們想要防止它從樓梯上掉下來(lái)的事情。在上一篇文章中,我們制作了一個(gè)面包板版本的紅外接近傳感器模塊并詳細(xì)解釋了工作原理,如果您想了解更多關(guān)于該傳感器的信息,可以查看。
基于Arduino的地板清潔機(jī)器人電路圖
我們有三個(gè)檢測(cè)障礙物的超聲波傳感器。因此,我們需要連接超聲波傳感器的所有地線并將它們連接到公共地線。此外,我們連接傳感器的所有三個(gè) Vcc 并將其連接到公共 VCC 引腳。接下來(lái),我們將觸發(fā)和回聲引腳連接到 Arduino 的 PWM 引腳。我們還將 IR 模塊的 VCC 連接到 5V,并將地連接到 Arduino 的接地引腳,IR 傳感器模塊的輸出引腳連接到 Arduino 的數(shù)字引腳 D2。對(duì)于電機(jī)驅(qū)動(dòng)器,我們將兩個(gè)使能引腳連接到 5v,并將驅(qū)動(dòng)器電壓引腳連接到 5V,因?yàn)槲覀兪褂玫氖?5 伏電機(jī)。在上一篇文章中,我們制作了一個(gè)Arduino 電機(jī)驅(qū)動(dòng)器擴(kuò)展板,您可以查看它以了解有關(guān)L293D 電機(jī)驅(qū)動(dòng)器 IC的更多信息及其操作。Arduino、超聲波模塊、電機(jī)驅(qū)動(dòng)器和電機(jī)在 5 伏電壓下工作,更高的電壓會(huì)殺死它,我們使用 7.4 伏電池,將其轉(zhuǎn)換為 5 伏,使用 LM7805 穩(wěn)壓器。將真空吸塵器直接連接到主電路。
為基于 Arduino 的地板清潔機(jī)器人構(gòu)建電路
要將每個(gè)組件焊接在一起,首先,我拿了一小塊點(diǎn)狀穿孔板,根據(jù)電路圖放置每個(gè)組件,然后焊接所有東西。這部分非常簡(jiǎn)單,但要小心。此外,我們使用了兩個(gè)母頭來(lái)放置Arduino pro mini。完成穿孔板焊接后,我們將電線連接到超聲波模塊,并將它們連接到相應(yīng)的引腳上,如圖所示。
為基于 Arduino 的地板清潔機(jī)器人建造外殼
為了得到一些關(guān)于我的機(jī)器人的想法,我在網(wǎng)上搜索了吸塵器機(jī)器人,得到了一些圓形機(jī)器人的圖像。所以,我決定造一個(gè)圓形機(jī)器人。為了構(gòu)建機(jī)器人的追逐和身體,我有很多選擇,如泡沫板、MDF、紙板等。但我選擇 MDF 是因?yàn)樗苡膊⑶揖哂幸恍┓浪匦浴H绻@樣做,您可以決定為您的機(jī)器人選擇哪種材料。
為了構(gòu)建機(jī)器人,我拿了 MDF 板,然后畫(huà)了兩個(gè)半徑為 8 CM 的圓, 在那個(gè)圓內(nèi),我還畫(huà)了另一個(gè)半徑為 4 CM的圓用于安裝真空吸塵器。然后我剪掉了圓圈。此外,我已經(jīng)為車輪路徑切割并移除了適當(dāng)?shù)牟糠郑ㄕ?qǐng)參閱圖像以更好地理解)。最后,我為腳輪打了三個(gè)小孔。下一步是使用支架將電機(jī)安裝在底座上,同時(shí)將腳輪放置并固定到其位置。之后,將超聲波傳感器放置在機(jī)器人的左側(cè)、右側(cè)和中間。此外,將 IR 模塊連接到機(jī)器人的底部。不要忘記在外面添加開(kāi)關(guān)。這就是構(gòu)建機(jī)器人的全部?jī)?nèi)容,如果您對(duì)此感到困惑,可以參考以下圖片。
最上面的部分,我還在泡沫板上畫(huà)了一個(gè)半徑為11CM的圓,剪下來(lái)。對(duì)于頂部和底部之間的間距,我切了三個(gè) 4 厘米長(zhǎng)的塑料管。之后,我將塑料墊片粘在底部,然后粘在頂部。如果需要,您可以用塑料或類似材料覆蓋機(jī)器人的側(cè)面部分。
基于Arduino的地板清潔機(jī)器人 - 代碼
該項(xiàng)目的完整代碼在文檔末尾給出。這個(gè) Arduino 代碼類似于基于 Arduino 的超聲波距離傳感器代碼,唯一的變化是地板檢測(cè)。在以下幾行中,我將解釋代碼是如何工作的。在這種情況下,我們沒(méi)有使用任何額外的庫(kù)。下面我們一步一步地描述了代碼。我們沒(méi)有使用任何額外的庫(kù)來(lái)解碼來(lái)自 HC-SR04 傳感器的距離數(shù)據(jù),因?yàn)樗浅:?jiǎn)單。在以下幾行中,我們描述了如何。首先,我們需要為連接到 Arduino 板的所有三個(gè)超聲波距離傳感器定義 Trigger Pin 和 Echo Pin。在這個(gè)項(xiàng)目中,我們有三個(gè) Echo 引腳和三個(gè) Trigger 引腳。請(qǐng)注意,1 是左傳感器,2 是前傳感器,3 是右傳感器。
?
常量 int trigPin1 = 3; 常量 int echoPin1 = 5; 常量 int trigPin2 = 6; 常量 int echoPin2 =9; 常量 int trigPin3 = 10; 常量 int echoPin3 = 11; int irpin = 2;
?
然后我們?yōu)榫嚯x定義變量,這些變量都是 (int) 類型變量,對(duì)于持續(xù)時(shí)間,我們選擇使用 (long)。同樣,我們每個(gè)人都有三個(gè)。另外,我已經(jīng)定義了一個(gè)整數(shù)來(lái)存儲(chǔ)運(yùn)動(dòng)的狀態(tài),我們將在本節(jié)后面討論它。
?
持續(xù)時(shí)間長(zhǎng)1; 持續(xù)時(shí)間長(zhǎng)2; 持續(xù)時(shí)間長(zhǎng)3; int距離左; int 距離前沿; int distanceright; 詮釋a = 0;
?
接下來(lái),在設(shè)置部分,我們需要使用?pinModes()?函數(shù)將所有透視引腳設(shè)置為輸入或輸出。要從模塊發(fā)送超聲波,我們需要將觸發(fā)引腳設(shè)為高電平,即所有觸發(fā)引腳都應(yīng)定義為?OUTPUT。為了接收回聲,我們需要讀取回聲引腳的狀態(tài),因此所有回聲引腳都應(yīng)定義為?INPUT。此外,我們啟用串行監(jiān)視器以進(jìn)行故障排除。為了讀取 IR 模塊的狀態(tài),我將irpin定義為輸入。
?
pinMode(trigPin1,輸出); pinMode(trigPin2,輸出); pinMode(trigPin3,輸出); pinMode(echoPin1,輸入); pinMode(echoPin2,輸入); pinMode(echoPin3,輸入); pinMode(irpin,輸入);
?
這些數(shù)字引腳被定義為電機(jī)驅(qū)動(dòng)器輸入的輸出。
?
pinMode(4,輸出); pinMode(7,輸出); pinMode(8,輸出); pinMode(12,輸出);
?
在主循環(huán)中,我們?yōu)槿齻€(gè)傳感器設(shè)置了三個(gè)部分。所有部分的工作方式相同,但每個(gè)部分用于不同的傳感器。在本節(jié)中,我們從每個(gè)傳感器讀取障礙物距離并將其存儲(chǔ)在每個(gè)定義的整數(shù)中。要讀取距離,首先,我們必須確保觸發(fā)引腳清晰,為此,我們需要將觸發(fā)引腳設(shè)置為?低電平?2 μs。現(xiàn)在,為了產(chǎn)生超聲波,我們需要將觸發(fā)引腳設(shè)為?高電平?10 μs。這將發(fā)送超聲波,在?pulseIn()?函數(shù)的幫助下,我們可以讀取行進(jìn)時(shí)間,并將該值存儲(chǔ)到變量“持續(xù)時(shí)間”中。這個(gè)函數(shù)有2個(gè)參數(shù),第一個(gè)是echo pin的名字,第二個(gè)可以寫(xiě)高或?低。HIGH 表示?pulseIn?()?函數(shù)將等待??由反彈的聲波引起?的引腳變?yōu)楦唠娖讲㈤_(kāi)始計(jì)數(shù),然后?在聲波結(jié)束時(shí)等待引腳變?yōu)榈碗娖綄⑼V褂?jì)數(shù)。該函數(shù)以微秒為單位給出脈沖的長(zhǎng)度。為了計(jì)算距離,我們將持續(xù)時(shí)間乘以 0.034(空氣中的聲速為 340m/s)再除以 2(這是由于聲波的來(lái)回傳播)。最后,我們將每個(gè)傳感器的距離存儲(chǔ)在相應(yīng)的整數(shù)中。
?
數(shù)字寫(xiě)入(trigPin1,低); 延遲微秒(2); 數(shù)字寫(xiě)入(trigPin1,高); 延遲微秒(10); 數(shù)字寫(xiě)入(trigPin1,低); 持續(xù)時(shí)間1 = 脈沖輸入(echoPin1,高); 距離左 = 持續(xù)時(shí)間 1 * 0.034 / 2;
?
在得到每個(gè)傳感器的距離后,我們可以在if 語(yǔ)句的幫助下控制電機(jī),從而控制機(jī)器人的運(yùn)動(dòng)。這很簡(jiǎn)單,首先,我們給了一個(gè)障礙物距離值,在這個(gè)例子中,它是 15cm(根據(jù)你的意愿改變這個(gè)值)。然后我們根據(jù)該值給出條件。例如,當(dāng)左側(cè)傳感器前方有障礙物(即左側(cè)傳感器的距離應(yīng)小于或等于 15 厘米)且其他兩個(gè)距離較高(即傳感器前方?jīng)]有障礙物)時(shí),然后借助數(shù)字寫(xiě)入功能,我們可以將電機(jī)驅(qū)動(dòng)到正確的位置。后來(lái),我檢查了紅外傳感器的狀態(tài)。如果機(jī)器人在地板上,則 IR 引腳的值為L(zhǎng)OW,如果不是,則值為高。然后我將該值存儲(chǔ)在int s 變量中。我們將根據(jù)這個(gè)狀態(tài)來(lái)控制機(jī)器人。
這部分代碼用于向前和向后移動(dòng)機(jī)器人:
?
if(s==HIGH) { digitalWrite(4, LOW); 數(shù)字寫(xiě)入(7,高); 數(shù)字寫(xiě)入(8,低); 數(shù)字寫(xiě)入(12,高); 延遲(1000); a=1; }
?
但是這種方法有一個(gè)問(wèn)題,當(dāng)電機(jī)向后移動(dòng),地板回來(lái),機(jī)器人向前移動(dòng)時(shí),它會(huì)重復(fù)使機(jī)器人卡住。?為了克服這個(gè)問(wèn)題,我們?cè)诶斫?floor 不存在后將值 (1) 存儲(chǔ)在int中。我們還檢查這種情況是否有其他運(yùn)動(dòng)。
檢測(cè)到?jīng)]有地板后,機(jī)器人不會(huì)向前移動(dòng)。相反,它會(huì)向左移動(dòng),這樣我們就可以避免這個(gè)問(wèn)題。
?
if ((a==0)&&(s==LOW)&&(distanceleft <= 15 && distancefront > 15 && distanceright <= 15) || (a==0)&&(s==LOW)&&(distanceleft > 15 && distancefront > 15 && distanceright > 15))
?
在上述情況下。首先,機(jī)器人會(huì)檢查樓層狀態(tài)和整數(shù)值。只有滿足所有條件,機(jī)器人才會(huì)繼續(xù)前進(jìn)。
現(xiàn)在,我們可以為電機(jī)驅(qū)動(dòng)器編寫(xiě)命令了。這將驅(qū)動(dòng)右電機(jī)向后和左電機(jī)向前,從而將機(jī)器人向右轉(zhuǎn)動(dòng)。
這部分代碼用于向右移動(dòng)機(jī)器人:
?
數(shù)字寫(xiě)入(4,高); 數(shù)字寫(xiě)入(7,低); 數(shù)字寫(xiě)入(8,高); 數(shù)字寫(xiě)入(12,低);
?
如果機(jī)器人檢測(cè)到地板不存在,則該值變?yōu)?1,機(jī)器人將向左移動(dòng)。左轉(zhuǎn)后,'a' 的值從 1 變?yōu)?0。
?
if ((a==1) &&(s==LOW) ||(s==LOW) && (distanceleft <= 15 && distancefront <= 15 && distanceright > 15) || (s== LOW) && (distanceleft <= 15 && distancefront <= 15 && distanceright > 15) || (s==LOW) && (distanceleft <= 15 && distancefront > 15 && distanceright > 15) || (distanceleft <= 15 && distancefront > 15 && distanceright > 15)) { digitalWrite(4, HIGH); 數(shù)字寫(xiě)入(7,低); 數(shù)字寫(xiě)入(8,低); 數(shù)字寫(xiě)入(12,高); 延遲(100); a=0; }
?
這部分代碼用于向左移動(dòng)機(jī)器人:
?
if ((s==LOW)&&(distanceleft > 15 && distancefront <= 15 && distanceright <= 15) ||(s==LOW)&& (distanceleft > 15 && distancefront > 15 && distanceright <= 15) ||( s==LOW)&& (distanceleft > 15 && distancefront <= 15 && distanceright > 15) ) { digitalWrite(4, LOW); 數(shù)字寫(xiě)入(7,高); 數(shù)字寫(xiě)入(8,高); 數(shù)字寫(xiě)入(12,低); }
?
?
?
//定義引腳 常量 int trigPin1 = 3; 常量 int echoPin1 = 5; 常量 int trigPin2 = 6; 常量 int echoPin2 = 9; 常量 int trigPin3 = 10; 常量 int echoPin3 = 11; int irpin = 2; // 定義變量 持續(xù)時(shí)間長(zhǎng)1; 持續(xù)時(shí)間長(zhǎng)2; 持續(xù)時(shí)間長(zhǎng)3; int距離左; int 距離前沿; int distanceright; 詮釋a = 0; 無(wú)效設(shè)置(){ pinMode(trigPin1,輸出); pinMode(trigPin2,輸出); pinMode(trigPin3, OUTPUT);// 將 trigPin 設(shè)置為輸出 pinMode(echoPin1,輸入);// 將 echoPin 設(shè)置為輸入 pinMode(echoPin2,輸入); pinMode(echoPin3,輸入); pinMode(irpin,輸入); pinMode(4,輸出); pinMode(7,輸出); pinMode(8,輸出); pinMode(12,輸出); } 無(wú)效循環(huán)(){ 數(shù)字寫(xiě)入(trigPin1,低); 延遲微秒(2); 數(shù)字寫(xiě)入(trigPin1,高); 延遲微秒(10); 數(shù)字寫(xiě)入(trigPin1,低); 持續(xù)時(shí)間1 = 脈沖輸入(echoPin1,高); 距離左 = 持續(xù)時(shí)間 1 * 0.034 / 2; Serial.print("距離1:"); Serial.println(distanceleft); 數(shù)字寫(xiě)入(trigPin2,低); 延遲微秒(2); 數(shù)字寫(xiě)入(trigPin2,高); 延遲微秒(10); 數(shù)字寫(xiě)入(trigPin2,低); 持續(xù)時(shí)間2 = 脈沖輸入(echoPin2,高); 距離前沿 = 持續(xù)時(shí)間 2 * 0.034 / 2; Serial.print("距離2:"); Serial.println(distancefront); 數(shù)字寫(xiě)入(trigPin3,低); 延遲微秒(2); 數(shù)字寫(xiě)入(trigPin3,高); 延遲微秒(10); 數(shù)字寫(xiě)入(trigPin3,低); 持續(xù)時(shí)間3 = 脈沖輸入(echoPin3,高); distanceright = duration3 * 0.034 / 2; Serial.print("距離3:"); Serial.println(distanceright); int s = digitalRead(irpin); 如果(s==高) { 數(shù)字寫(xiě)入(4,低); 數(shù)字寫(xiě)入(7,高); 數(shù)字寫(xiě)入(8,低); 數(shù)字寫(xiě)入(12,高); 延遲(1000); a=1; } if ((a==0)&&(s==LOW)&&(distanceleft <= 15 && distancefront > 15 && distanceright <= 15) || (a==0)&&(s==LOW)&&(distanceleft > 15 && distancefront > 15 && distanceright > 15)) { 數(shù)字寫(xiě)入(4,高); 數(shù)字寫(xiě)入(7,低); 數(shù)字寫(xiě)入(8,高); 數(shù)字寫(xiě)入(12,低); } if ((a==1)&&(s==LOW)||(s==LOW)&&(distanceleft <= 15 && distancefront <= 15 && distanceright > 15)||(s==LOW)&&(distanceleft <= 15 && distancefront <= 15 && distanceright > 15)||(s==LOW)&& (distanceleft <= 15 && distancefront > 15 && distanceright > 15)||(distanceleft <= 15 && distancefront > 15 && distanceright > 15)) { 數(shù)字寫(xiě)入(4,高); 數(shù)字寫(xiě)入(7,低); 數(shù)字寫(xiě)入(8,低); 數(shù)字寫(xiě)入(12,高); 延遲(100); a=0; } if ((s==LOW)&&(distanceleft > 15 && distancefront <= 15 && distanceright <= 15) ||(s==LOW)&& (distanceleft > 15 && distancefront > 15 && distanceright <= 15) ||( s==LOW)&& (distanceleft > 15 && distancefront <= 15 && distanceright > 15)) { 數(shù)字寫(xiě)入(4,低); 數(shù)字寫(xiě)入(7,高); 數(shù)字寫(xiě)入(8,高); 數(shù)字寫(xiě)入(12,低); } }
?
?
評(píng)論
查看更多