機器人已經慢慢開始爬進我們的社會,讓我們的生活變得更簡單。我們已經可以在英國的道路上找到來自 Starship 的六輪送餐機器人,它們巧妙地在平民中導航到達目的地。每個導航到環境中的移動機器人都應該始終了解其相對于現實世界的位置和方向。有很多方法可以通過使用不同的技術來實現這一點,如 GPS、RF 三角測量、加速度計、陀螺儀等。每種技術都有其自身的優勢,并且是獨一無二的。在這個Arduino LM393 速度傳感器教程中,我們將使用簡單易用的LM393 速度傳感器模塊使用 Arduino 測量一些重要參數,例如速度、行進距離和機器人角度。通過這些參數,機器人將能夠了解其真實世界的狀態,并可以使用它進行安全導航。
Arduino 是構建機器人的愛好者中最受歡迎的選擇,從簡單的線跟隨器到更復雜的自平衡或地板清潔機器人。您可以在機器人部分查看所有類型的機器人。
我們將建造一個由鋰電池供電的小型機器人,并使用操縱桿驅動它。在運行期間,我們可以測量機器人的速度、距離和角度,并將其實時顯示在連接到 Arduino 的 LCD 顯示器上。這個項目只是幫助你測量這些參數,一旦你完成了這個,你就可以根據需要使用這些參數來自主操作你的機器人。聽起來很有趣吧?所以讓我們開始吧。
LM393 速度傳感器模塊 (H206)
在我們進入項目的電路圖和代碼之前,讓我們了解LM393 速度傳感器模塊,因為它在項目中起著至關重要的作用。H206 速度傳感器模塊由集成了 LM393 電壓比較器 IC 的紅外光傳感器組成,因此名稱為 LM393 速度傳感器。該模塊還包括一個網格板,該網格板必須安裝在電機的旋轉軸上。所有組件都標記在下圖中。
紅外光傳感器由一個 IR LED 和一個由一個小間隙隔開的光電晶體管組成。整個傳感器裝置放置在黑色外殼中,如上圖所示。網格板由槽組成,板布置在紅外光傳感器的間隙之間,傳感器可以感應到網格板中的間隙。柵板中的每個縫隙在通過縫隙時都會觸發IR傳感器;然后使用比較器將這些觸發器轉換為電壓信號。比較器不過是 ON 半導體的 LM393 IC。該模塊共有三個引腳,其中兩個用于為模塊供電,一個輸出引腳用于計數觸發次數。
H206 傳感器安裝布置
安裝這些類型的傳感器有點棘手。它只能安裝在兩側都有軸突出的電機上。軸的一側連接到車輪,而另一側用于安裝網格板,如上圖所示。
由于輪子和盤子連接到同一根軸上,兩者都以相同的速度旋轉,因此通過測量盤子的速度,我們可以測量輪子的速度。確保網格板中的間隙通過 IR 傳感器,只有這樣傳感器才能計算已通過的間隙數。只要滿足指定條件,您也可以提出自己的機械布置來安裝傳感器。紅外傳感器通常用于許多機器人項目中,以引導機器人繞過障礙物。
上面顯示的網格板有 20 個槽(網格)。這意味著傳感器會為車輪一整圈找到 20 個間隙。通過計算傳感器檢測到的間隙數量,我們可以計算車輪行進的距離,類似地,通過測量傳感器找到間隙的速度,我們可以檢測到車輪的速度。在我們的機器人中,我們將這個傳感器安裝在兩個輪子上,因此我們也可以找到機器人的角度。然而,使用加速度計或陀螺儀可以更明智地計算旋轉角度,在此處學習將加速度計和陀螺儀與 Arduino連接,并嘗試使用它們來測量旋轉角度。
DIY Arduino LM393 速度傳感器機器人電路圖
該速度和距離感應機器人的完整電路圖如下所示。Bot 由Arduino Nano作為其大腦組成,兩個用于車輪的直流電機由 L298N H 橋電機驅動模塊驅動。操縱桿用于控制機器人的速度和方向,兩個速度傳感器 H206 用于測量機器人的速度、距離和角度。然后測量值顯示在16x2 LCD 模塊中。連接到 LCD 的電位器可用于調節 LCD 的對比度,電阻器用于限制流向 LCD 背光的電流。
整個電路由一個 7.4V 鋰電池供電。這個 7.4V 提供給電機驅動模塊的 12V 引腳。然后,電機驅動模塊上的穩壓器將 7.4V 轉換為穩定的 +5V,用于為 Arduino、LCD、傳感器和操縱桿供電。
電機由 Arduino 的數字引腳 8、9、10 和 11 控制。由于還必須控制電機的速度,我們應該向電機的正極端子提供PWM 信號。因此,我們有引腳 9 和 10,它們都是支持 PWM 的引腳。操縱桿的 X 和 Y 值分別使用模擬引腳 A2 和 A3 讀取。
正如我們所知,H206 傳感器在檢測到網格板中的間隙時會生成觸發器。由于不應始終準確讀取這些觸發器以計算正確的速度和距離,因此兩個觸發器(輸出)引腳都連接到 Arduino 板的外部中斷引腳 2 和 3。將整個電路組裝在底盤上并按照說明安裝速度傳感器,連接完成后,我的機器人如下所示。您還可以觀看本頁末尾的視頻,了解傳感器的安裝方式。
現在硬件部分已經完成,讓我們進入如何測量機器人的速度、距離和單程的邏輯,然后進入編程部分。
使用 LM393 速度傳感器模塊測量速度背后的邏輯
從傳感器安裝設置中,您應該知道 LM393 速度傳感器模塊 (H206) 僅測量網格板中存在的間隙。安裝時應確保車輪(應測量其速度)和網格板以相同的速度旋轉。就像這里一樣,由于我們將輪子和盤子都安裝在同一軸上,因此它們顯然將以相同的速度旋轉。
在我們的設置中,我們為每個車輪安裝了兩個傳感器來測量機器人的角度。但是,如果您的目標只是測量速度和距離,我們可以將傳感器安裝在任何一個車輪上。傳感器的輸出(觸發信號)最常連接到微控制器的外部中斷引腳。每次檢測到網格板中的間隙時,都會觸發中斷,并執行 ISR(中斷服務程序)中的代碼。如果我們能夠計算出兩個這樣的觸發器之間的時間間隔,我們就可以計算出車輪的速度。
在 Arduino 中,我們可以使用millis()函數輕松計算此時間間隔。從設備上電開始,該毫秒函數將每毫秒遞增 1。因此,當第一個中斷發生時,我們可以將 millis() 的值保存在一個虛擬變量中(如代碼中的pevtime),然后當第二個中斷發生時,我們可以通過從millis()中減去pevtime值來計算所花費的時間。
所用時間 = 當前時間 - 上一個時間所
用時間= millis ()- pevtime ; //以毫秒為單位的時間
一旦我們計算出所花費的時間,我們可以使用以下公式簡單地計算 rpm 的值,其中 (1000/timetaken) 給出 RPS(每秒轉數),然后乘以 60 將 RPS 轉換為 RPM(每分鐘轉數) 。
rpm=(1000/timetaken)*60;
在計算 rpm 后,我們可以使用以下公式計算車輛的速度,前提是我們知道車輪的半徑。
速度 = 2π × RPS × 車輪半徑。
v = radius_of_wheel * rpm * 0.104
注意,上面的公式是以 m/s 為單位計算速度的,如果你想以 km/hr 為單位計算,請將 0.0104 替換為 0.376。如果您想知道值 0.104 是如何獲得的,請嘗試簡化公式 V = 2π × RPS × 車輪半徑。
即使使用霍爾傳感器來測量旋轉物體的速度,也使用相同的技術。但是對于 H206 傳感器有一個問題,網格板有 20 個插槽,因此測量兩個插槽間隙之間的時間會使微控制器過載。因此,我們僅在車輪完全旋轉時測量速度。由于每個間隙都會產生兩個中斷(一個在間隙開始,另一個在間隙結束),我們將總共獲得 40 個中斷,以便輪子完成一個完整的旋轉。因此,我們在實際計算車輪速度之前等待 40 次中斷。相同的代碼如下所示
if(rotation》=40)
{
timetaken = millis()-pevtime; //以毫秒為單位的時間
rpm=(1000/timetaken)*60; //計算轉速的公式
pevtime = millis();
旋轉=0;
}
這種方法的另一個缺點是,速度值不會下降到零,因為中斷將始終等待車輪完成一個旋轉來計算 rpm 值。這個缺點可以通過添加一個簡單的代碼來監控兩個中斷之間的時間間隔來輕松克服,如果它超過正常值,那么我們可以強制 rpm 和速度的值為零。鏈接在下面的代碼中,我們使用變量dtime來檢查時間差異,如果超過 500 毫秒,則速度和 rpm 的值被強制為零。
/*如果車輛停止則降為零*/
if(millis()-dtime》500) //500ms 內沒有發現 inetrrupt
{
rpm= v = 0; // 使 rpm 和速度為零
dtime=millis();
}
測量車輪行駛距離背后的邏輯
我們已經知道,當車輪轉一圈時,Arduino 會感應到 40 次中斷。因此,對于輪子每轉一圈,輪子行進的距離顯然等于輪子的周長。由于我們已經知道車輪的半徑,我們可以使用以下公式輕松計算所覆蓋的距離
距離 = 2πr * 轉數
距離 = (2*3.141*radius_of_wheel) * (left_intr/40)
使用公式 2πr 計算車輪的周長,然后乘以車輪的轉數。
測量機器人角度背后的邏輯
確定機器人角度的方法有很多種。加速度計和陀螺儀通常用于確定這些值。但另一種便宜的方法是在兩個車輪上都使用 H206 傳感器。這樣我們就可以知道每個輪子轉了多少圈。下圖說明了如何計算角度。
當機器人初始化時,它所面對的角度被認為是 0°。從那里它向左旋轉,角度增加為負,如果它向右旋轉,角度增加為正。為了便于理解,讓我們考慮如圖所示的 -90 到 +90 的范圍。在這樣的布置中,由于兩個輪子具有相同的直徑,如果任何一個輪子完全旋轉,我們就會以 90° 的角度轉動機器人。
例如,如果左輪完成一整圈(80 次中斷),那么機器人將向左轉 90°,類似地,如果右輪完成一整圈(80 次中斷),那么機器人將向右轉 -90°?,F在我們知道,如果 Arduino 在一個輪子上檢測到 80 個中斷,那么機器人已經轉動了 90°,我們可以根據哪個輪子判斷機器人是正轉(右)還是負(左)轉。所以左右角可以用下面的公式計算
int angle_left = (left_intr % 360) * (90/80) ;
int angle_right = (right_intr % 360) * (90/80) ;
其中 90 是進行 80 度中斷時所覆蓋的角度。結果值是中斷次數的乘積。我們還使用了 360 的模數,因此結果值永遠不會超過 36。一旦我們計算了左角和右角,機器人面對的有效角度可以簡單地通過從右角中減去左角來獲得。
角度 = 角度右 - 角度左;
Arduino機器人代碼
此速度和角度測量機器人的完整 Arduino 代碼可在本頁末尾找到。該程序的目的是使用上述邏輯計算機器人的速度、距離和角度,并將其顯示在 LCD 屏幕上。除此之外,它應該提供一個使用操縱桿控制機器人的選項。
我們通過定義兩個電機的數字 I/O 引腳來啟動程序。請注意,我們還必須控制電機的速度,因此我們必須使用 Arduino 上的 PWM 引腳來控制電機。在這里,我們使用了引腳 8、9、10 和 11。
#define LM_pos 9 // 左電機
#define LM_neg 8 // 左電機
#define RM_pos 10 // 右電機
#define RM_neg 11 // 右電機
#define joyX A2
#define joyY A3
要測量所覆蓋的速度和距離,我們需要知道車輪的半徑,測量值并以米為單位輸入,如下所示。對于我的機器人,半徑為 0.033 米,但根據你的機器人,它可能會有所不同。
浮動radius_of_wheel = 0.033;//測量你的輪子的半徑并在這里輸入厘米
在setup函數中,我們將所有值初始化為零,然后在 LCD 上顯示 Intro Text。我們還初始化了串行監視器以進行調試。然后我們提到速度傳感器 H206 連接到引腳 2 和 3 作為外部中斷。這就是檢測到中斷的地方,ISR 函數Left_ISR和Right_ISR將相應地執行。
void setup()
{
旋轉 = rpm = pevtime = 0; //將所有變量初始化為零
Serial.begin(9600);
lcd.begin(16, 2); //初始化 16*2 LCD
lcd.print("Bot Monitor"); //介紹消息行 1
lcd.setCursor(0, 1);
lcd.print("-CircuitDigest"); //介紹消息第 2 行
延遲(2000);
lcd.clear();
lcd.print("Lt: Rt:");
lcd.setCursor(0, 1);
lcd.print("S:D:A:");
pinMode(LM_pos,輸出);
pinMode(LM_neg,輸出);
pinMode(RM_pos,輸出);
pinMode(RM_neg,輸出);
數字寫入(LM_neg,低);
數字寫入(RM_neg,低);
attachInterrupt(digitalPinToInterrupt(2), Left_ISR, CHANGE); //左輪傳感器觸發時
調用Left_ISR attachInterrupt(digitalPinToInterrupt(3), Right_ISR, CHANGE);//右輪傳感器觸發時調用Right_ISR
}
在 Left_ISR 例程中,我們簡單地增加一個名為 left_intr 的變量,稍后將用于測量機器人的角度。在 Right_ISR 中,我們做同樣的事情,但另外我們也在此處計算速度。每次中斷都會增加變量旋轉,然后使用上述邏輯來計算速度。
void Left_ISR()
{
left_intr++;delay(10);
}
無效 Right_ISR()
{
right_intr++; 延遲(10);
旋轉++;
dtime=毫秒();
if(rotation>=40)
{
timetaken = millis()-pevtime; //以毫秒為單位的時間
rpm=(1000/timetaken)*60; //計算轉速的公式
pevtime = millis();
旋轉=0;
}
}
在主無限循環函數中,我們通過操縱桿監控 X 和 Y 的值。如果操縱桿移動,我們會根據該值控制機器人。機器人的速度取決于操縱桿被推多遠。
int xValue = 模擬讀?。╦oyX );
int yValue = 模擬讀?。╦oyY );
int 加速度 = 地圖 (xValue, 500, 0, 0, 200);
如果(xValue<500)
{
模擬寫入(LM_pos,加速度);
模擬寫入(RM_pos,加速度);
}
否則
{
類比寫入(LM_pos,0);
模擬寫入(RM_pos,0);
}
如果(yValue>550)
模擬寫入(RM_pos,80);
如果(yValue<500)
analogWrite(LM_pos,100);
這將幫助用戶移動機器人并檢查獲得的值是否符合預期。最后,我們可以使用上述邏輯計算機器人的速度、距離和角度,并使用以下代碼將其顯示在 LCD 上。
v = radius_of_wheel * rpm * 0.104;//0.033 是以米為單位的車輪半徑
= (2*3.141*radius_of_wheel) * (left_intr/40);
int angle_left = (left_intr % 360) * (90/80) ;
int angle_right = (right_intr % 360) * (90/80) ;
角度 = 角度右 - 角度左;
lcd.setCursor(3, 0); lcd.print(""); lcd.setCursor(3, 0); lcd.print(left_intr);
lcd.setCursor(11, 0); lcd.print(""); lcd.setCursor(11, 0);lcd.print(right_intr);
lcd.setCursor(2, 1); lcd.print(""); lcd.setCursor(2, 1);lcd.print(v);
lcd.setCursor(9, 1); lcd.print(""); lcd.setCursor(9, 1);lcd.print(距離);
lcd.setCursor(13, 1); lcd.print(""); lcd.setCursor(13, 1);lcd.print(角度);
測試 Arduino 機器人以測量距離、速度和角度
準備好硬件后,將代碼上傳到 Arduino 并使用操縱桿移動機器人。機器人的速度、距離和角度將顯示在 LCD 中,如下所示。
在 LCD 上,術語 Lt 和 Rt 分別代表左中斷計數和右中斷計數。您會發現這些值隨著傳感器檢測到的每個間隙而增加。項S 表示機器人的速度,以米/秒為單位,項 D 表示以米為單位的距離。機器人的角度顯示在末端,其中 0° 表示直線,逆時針旋轉為負,順時針旋轉為正。
/*
* Arduino 車速、距離和角度計算器
*/
/*-------定義引腳------*/
#define LM_pos 9 // 左電機
#define LM_neg 8 // 左電機
#define RM_pos 10 // 右電機
#define RM_neg 11 // 右電機
#define joyX A2
#define joyY A3
#include
const int rs = 14, en = 15, d4 = 4, d5 = 5, d6 = 6, d7 = 7; //注明LCD連接的管腳號
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
int left_intr = 0;
int right_intr = 0;
int 角度 = 0;
/*硬件細節*/
float radius_of_wheel = 0.033; //測量你的輪子的半徑并在這里輸入厘米
易失字節輪換;// 中斷樂趣的變量必須是 volatile
float timetaken,rpm,dtime;
浮動 v;
整數距離;
無符號長 pevtime;
void setup()
{
旋轉 = rpm = pevtime = 0; //將所有變量初始化為零
Serial.begin(9600);
lcd.begin(16, 2); //初始化16*2 LCD
lcd.print("Vechile Monitor"); //介紹消息行 1
lcd.setCursor(0, 1);
lcd.print("-CircuitDigest"); //介紹消息第 2 行
延遲(2000);
lcd.clear();
lcd.print("Lt: Rt:");
lcd.setCursor(0, 1);
lcd.print("S:D:A:");
pinMode(LM_pos,輸出);
pinMode(LM_neg,輸出);
pinMode(RM_pos,輸出);
pinMode(RM_neg,輸出);
數字寫入(LM_neg,低);
數字寫入(RM_neg,低);
attachInterrupt(digitalPinToInterrupt(2), Left_ISR, CHANGE); //左輪傳感器觸發時
調用Left_ISR attachInterrupt(digitalPinToInterrupt(3), Right_ISR, CHANGE);//右輪傳感器觸發時調用Right_ISR
}
無效循環()
{
int xValue = 模擬讀?。╦oyX);
int yValue = 模擬讀?。╦oyY);
int 加速度 = 地圖 (xValue, 500, 0, 0, 200);
如果(xValue<500)
{
模擬寫入(LM_pos,加速度);
模擬寫入(RM_pos,加速度);
}
其他
{
類比寫入(LM_pos,0);
模擬寫入(RM_pos,0);
}
如果(yValue>550)
模擬寫入(RM_pos,80);
如果(yValue<500)
analogWrite(LM_pos,100);
/*如果車輛停止則降為零*/
if(millis()-dtime>500) //500ms 內沒有發現 inetrrupt
{
rpm= v = 0; // 使 rpm 和速度為零
dtime=millis();
}
v = radius_of_wheel * rpm * 0.104;//0.033 是以米為單位的車輪半徑
= (2*3.141*radius_of_wheel) * (left_intr/40);
int angle_left = (left_intr % 360) * (90/80) ;
int angle_right = (right_intr % 360) * (90/80) ;
角度 = 角度右 - 角度左;
lcd.setCursor(3, 0); lcd.print(""); lcd.setCursor(3, 0); lcd.print(left_intr);
lcd.setCursor(11, 0); lcd.print(""); lcd.setCursor(11, 0);lcd.print(right_intr);
lcd.setCursor(2, 1); lcd.print(""); lcd.setCursor(2, 1);lcd.print(v);
lcd.setCursor(9, 1); lcd.print(""); lcd.setCursor(9, 1);lcd.print(距離);
lcd.setCursor(13, 1); lcd.print(""); lcd.setCursor(13, 1);lcd.print(角度);
延遲(100);
}
void Left_ISR()
{
left_intr++;delay(10);
}
無效 Right_ISR()
{
right_intr++; 延遲(10);
旋轉++;
dtime=毫秒();
if(rotation>=40)
{
timetaken = millis()-pevtime; //以毫秒為單位的時間
rpm=(1000/timetaken)*60; //計算轉速的公式
pevtime = millis();
旋轉=0;
}
}
?
評論
查看更多