電子發(fā)燒友App

硬聲App

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示
創(chuàng)作
電子發(fā)燒友網(wǎng)>電子資料下載>電子資料>帶有PID控制的線跟隨機(jī)器人

帶有PID控制的線跟隨機(jī)器人

2022-11-08 | zip | 0.06 MB | 次下載 | 2積分

資料介紹

描述

該項(xiàng)目的目的是構(gòu)建一個(gè)帶有 PID 控制的線跟隨機(jī)器人。我們還將使用 Android 設(shè)備輕松設(shè)置主要控制參數(shù),以便更好、更快地進(jìn)行調(diào)整。

這個(gè)項(xiàng)目是一個(gè)由兩部分組成的更復(fù)雜項(xiàng)目中的第一個(gè),我的目的是探索 Line Follower Robots 的潛力。第二部分:迷宮求解機(jī)器人,使用 Arduino人工智能,機(jī)器人將使用簡(jiǎn)單的人工智能技術(shù)探索和解決迷宮。

第 1 步:物料清單

所需材料清單非常簡(jiǎn)單,最終的機(jī)器人非常便宜(約 75.00 美元):

車身(可根據(jù)您的需要進(jìn)行調(diào)整):

  • 2個(gè)木方格(80X80mm)
  • 3 個(gè)活頁(yè)夾
  • 2個(gè)木輪(直徑:50mm)
  • 1個(gè)球腳輪
  • 9 松緊帶
  • 3M 命令框條
  • 面包板和接線
  • 2組4XNi金屬氫化物電池(每組5V)
  • 2 X SM-S4303R 連續(xù)旋轉(zhuǎn) 360 度塑料伺服
  • Arduino納米
  • 5 X 線傳感器(TCRT5000 4CH 紅外線跟蹤傳感器模塊 + 1 個(gè)獨(dú)立的跟蹤傳感器)
  • 1 個(gè) LED
  • 1 個(gè)按鈕

第 2 步:設(shè)置電機(jī)

?
?
?
?
pYYBAGNooiSAIPOGAAAXANEbatA804.jpg
?
1 / 4
?

對(duì)于電機(jī),使用了 2 個(gè)連續(xù)伺服系統(tǒng) (SM-S4303R)。正如您在照片中看到的那樣,它們將被“粘合”在一起,形成一個(gè)單一的實(shí)心塊(使用 3M 命令條、膠水或雙面膠帶)。這些伺服系統(tǒng)將以給定的速度運(yùn)行,由其數(shù)據(jù)輸入上接收到的脈沖寬度定義。對(duì)于這個(gè)特定的伺服,脈沖寬度從 1.0ms(1,000 微秒)到 2.0ms(2,000 微秒)。其他伺服系統(tǒng)可以使用不同的脈沖寬度。

細(xì)看:

  • 1.5ms 的脈沖將伺服定位在中性位置,或“停止”。
  • 1.0ms 的脈沖將命令伺服在一個(gè)方向上全速(約 70 RPM)
  • 反方向的 2.0ms 全速脈沖。
  • 1.0 到 1.5ms 或 1.5ms 到 2.0ms 之間的脈沖,將產(chǎn)生比例速度。

將兩個(gè)伺服系統(tǒng)物理連接后,按照上面的繪圖電路為它們提供源(外部 5V 或 6V),并為它們提供 Arduino 的信號(hào)

  • 左舵機(jī):Arduino Pin 5
  • 右舵機(jī):Arduino Pin 3

全部連接后,必須做的第一件事是發(fā)送一個(gè) 1.5 毫秒的脈沖來(lái)驗(yàn)證電機(jī)是否“停止”(未運(yùn)行)。如果不是,則必須將伺服系統(tǒng)調(diào)整到完全停止(尋找黃色螺栓,在伺服系統(tǒng)下方)。

注意:如果您的舵機(jī)沒(méi)有此物理調(diào)整,請(qǐng)嘗試更改函數(shù)內(nèi)部的參數(shù)“1500”微秒(向上或向下),直到完全停止。

下面的 Arduino 代碼可以完成這項(xiàng)工作:

#include  // Servo library 
Servo leftServo;
Servo rightServo;
Void setup()
{
  leftServo.attach(5);
  rightServo.attach(3);
  leftServo.writeMicroseconds(1500);
  rightServo.writeMicroseconds(1500);
}
void loop()
{
}

第 3 步:組裝車身和電機(jī)進(jìn)行運(yùn)動(dòng)測(cè)試

?
?
?
?
pYYBAGNoojiAXlxwAAGL-6CnkRg260.jpg
?
1 / 7
?
  • 使用 3M Command 框架條,將 2 個(gè)舵機(jī)固定到其中一個(gè)方形木片上。
  • 使用活頁(yè)夾將第二塊方形木頭固定在上面的木頭上。根據(jù)您的需要調(diào)整平臺(tái)的長(zhǎng)度。
  • 使用活頁(yè)夾固定球腳輪。
  • 電機(jī)的電源將來(lái)自一組 5V 電池。這套電池將安裝在面包板和車身框架之間。
  • 連接舵機(jī)使用的電池:左側(cè)一側(cè)電網(wǎng)專用于舵機(jī)源
  • 將 Arduino Nano 連接到面包板
  • 將電網(wǎng)的 GND 連接到 Arduino GND。
  • 將伺服系統(tǒng)連接到 Arduino:左 ==> 引腳 5;右 ==> 引腳 3
  • 將 LED 連接到 Arduino 引腳 13
  • 將按鈕連接到 Arduino 引腳 9

請(qǐng)注意,由于伺服系統(tǒng)的安裝方式(相反),速度范圍為:

  • 右舵機(jī)前進(jìn)速度從 1,500us(停止)到 2,000us(全速)
  • 左舵機(jī)前進(jìn)速度從 1,500us(停止)到 1,000(全速)

一個(gè)外部 LED 被添加到 pin13,用于信號(hào)化和測(cè)試目的(如果需要,您可以使用內(nèi)部 Arduino LED,而不是外部 LED,但考慮到在電纜中間很難看到它)。

還有一個(gè)按鈕連接到引腳 9。這個(gè)按鈕對(duì)于測(cè)試目的和機(jī)器人的啟動(dòng)非常有用。

例如:

while(digitalRead(buttonPin)) 
{ 
}
motorTurn (LEFT, 500);
motorTurn (RIGHT, 500);

請(qǐng)注意,將命令機(jī)器人向左轉(zhuǎn)、等待 500 毫秒并向右轉(zhuǎn)的 2 行僅在您按下按鈕 (buttonPin = 0) 后才會(huì)發(fā)生。在此之前,程序?qū)⒃跓o(wú)限循環(huán)中停止。

下面的代碼可用作完整電機(jī)測(cè)試(前進(jìn)、后退、句號(hào)、左轉(zhuǎn)、右轉(zhuǎn))的基礎(chǔ)。如有必要,您必須根據(jù)您的電機(jī)調(diào)整所需轉(zhuǎn)角的延遲(此外,有時(shí)左右脈沖值應(yīng)該略有不同,以補(bǔ)償電機(jī)的任何缺乏平衡。

?

第四步:藍(lán)牙模塊(可選)

?
?
?
?
poYBAGNoojuAA3FhAACYT4Z0fRU204.jpg
?
1 / 2
?

藍(lán)牙模塊 HC-06 應(yīng)安裝在面包板上,如圖所示。將使用 Arduino 庫(kù) SoftSerial。

HC-06 引腳連接下方:

  • Tx 引腳到 Arduino引腳 10 (Rx)
  • RX 引腳到 Arduino引腳 11 (Tx)
  • VCC/GND到 Arduino 5V/GND

機(jī)器人將使用或不使用藍(lán)牙。該代碼的構(gòu)建方式是,如果您不激活 BT,則默認(rèn)參數(shù)將是機(jī)器人使用的參數(shù)。因此,如果您不想安裝 HC-06 模塊,請(qǐng)不要擔(dān)心,代碼仍然可以正常工作。在本教程的最后一部分,我將探討如何使用 Android 應(yīng)用程序發(fā)送數(shù)據(jù)以更好地調(diào)整機(jī)器人參數(shù)和/或在手動(dòng)模式下移動(dòng)機(jī)器人。例如,如果有人想更多地探索使用 Line Follower Robot 進(jìn)行比賽,我會(huì)將藍(lán)牙和應(yīng)用程序的使用保留為可選項(xiàng)。

第 5 步:添加線傳感器

?
?
?
?
pYYBAGNooj-ATrypAADIjXGGs6I329.jpg
?
1 / 10
?

將電纜連接到 Arduino 引腳,如下所示:

  • 傳感器 0 = 12
  • 傳感器 1 = 18
  • 傳感器 2 = 17
  • 傳感器 3 = 16
  • 傳感器 4 = 19
  • 如圖所示,將 5 個(gè)傳感器固定在塑料條上
  • 建議對(duì)傳感器進(jìn)行標(biāo)記以進(jìn)行測(cè)試。傳感器名稱從“0”(更靠左)到“4”(更靠右)
  • 將電纜穿過(guò)框架下方,使用松緊帶固定它們。注意不要與輪子或腳輪混淆。
  • 固定第二組 5V 電池并將其連接到 Arduino Vin。

就我而言,我使用了一個(gè)集成了 4 個(gè)傳感器 + 1 個(gè)額外傳感器的模塊。它們都是兼容的。為簡(jiǎn)單起見(jiàn),在圖中我包括了 5 個(gè)連接在一起的獨(dú)立傳感器。兩種配置的最終結(jié)果相同。

第 6 步:實(shí)現(xiàn) IR 傳感器邏輯

?
?
?
?
poYBAGNookGAURd0AAA4OAat_z8626.jpg
?
1 / 5
?

IR 傳感器由一個(gè)單獨(dú)的 IR LED 和一個(gè) IR 光電二極管組成。LED 發(fā)出的紅外光照射到表面并反射回紅外光電二極管。然后,光電二極管產(chǎn)生與表面反射率水平成比例的輸出電壓(“亮表面”的值較高,“黑/暗表面”的值較低)。

在使用傳感器的情況下,模塊上的集成電路會(huì)生成一個(gè)簡(jiǎn)單的數(shù)字信號(hào)(HIGH:暗;LOW:亮)作為輸出。安裝在模塊上的電位器(見(jiàn)照片)將調(diào)整正確的光線水平以被認(rèn)為是“暗”或“亮”。它的工作方式是,當(dāng)反射光顏色為黑色/深色時(shí),在其輸出端生成一個(gè)高(“1”)數(shù)字電平,并為另一種較淺的顏色生成一個(gè)低(“0”)數(shù)字電平。我在這里使用了一個(gè)帶有 4 個(gè)傳感器的集成模塊和一個(gè)帶有唯一傳感器的額外模塊(不同的形狀,但相同的邏輯)。該組合是由 5 個(gè)傳感器組成的陣列,我發(fā)現(xiàn)它們有利于實(shí)現(xiàn)良好而平穩(wěn)的控制,如下所述。

5 個(gè)傳感器陣列的安裝方式是,如果只有一個(gè)傳感器相對(duì)于黑線居中,則只有該特定傳感器會(huì)產(chǎn)生 HIGH。另一方面,應(yīng)計(jì)算傳感器之間的空間,以允許 2 個(gè)傳感器可以同時(shí)覆蓋黑線的整個(gè)寬度,同時(shí)在兩個(gè)傳感器上產(chǎn)生一個(gè) HIGH(見(jiàn)上圖)。

跟隨線時(shí)可能的傳感器陣列輸出是:

  • 0 0 0 0 1
  • 0 0 0 1 1
  • 0 0 0 1 0
  • 0 0 1 1 0
  • 0 0 1 0 0
  • 0 1 1 0 0
  • 0 1 0 0 0
  • 1 1 0 0 0
  • 1 0 0 0 0

擁有 5 個(gè)傳感器,可以生成一個(gè)“誤差變量”,這將有助于控制機(jī)器人在線上的位置,如下所示。

讓我們考慮一下最佳條件是機(jī)器人居中時(shí),這條線正好位于“中間傳感器”(傳感器 2)下方。數(shù)組的輸出將是:0 0 1 0 0,在這種情況下,“錯(cuò)誤”將是“零”。如果機(jī)器人開(kāi)始向左移動(dòng)(線“似乎向右移動(dòng)”),則誤差必須隨著正信號(hào)而增加。如果機(jī)器人開(kāi)始向右移動(dòng)(線“似乎向左移動(dòng)”),在同樣,誤差必須增加,但現(xiàn)在是負(fù)信號(hào)。

與傳感器狀態(tài)相關(guān)的錯(cuò)誤變量將是:

0 0 1 0 0 ==> 錯(cuò)誤 = 0

  • 0 0 0 0 1 ==> 錯(cuò)誤 = 4
  • 0 0 0 1 1 ==> 錯(cuò)誤 = 3
  • 0 0 0 1 0 ==> 錯(cuò)誤 = 2
  • 0 0 1 1 0 ==> 錯(cuò)誤 = 1
  • 0 1 1 0 0 ==> 錯(cuò)誤 = -1
  • 0 1 0 0 0 ==> 錯(cuò)誤 = -2
  • 1 1 0 0 0 ==> 錯(cuò)誤 = -3
  • 1 0 0 0 0 ==> 錯(cuò)誤 = -4

查看 Arduino 代碼,每個(gè)傳感器都將定義一個(gè)特定的名稱(考慮到更靠左的 Line Follow Sensor 必須分配一個(gè)標(biāo)簽“0”):

const int lineFollowSensor0 = 12;
const int lineFollowSensor1 = 18;
const int lineFollowSensor2 = 17;
const int lineFollowSensor3 = 16;
const int lineFollowSensor4 = 19;

為了存儲(chǔ)每個(gè)傳感器的值,將創(chuàng)建一個(gè)數(shù)組變量:

int LFSensor[5]={0, 0, 0, 0, 0};

陣列的每個(gè)位置都將隨著每個(gè)傳感器的輸出不斷更新:

LFSensor[0] = digitalRead(lineFollowSensor0);
LFSensor[1] = digitalRead(lineFollowSensor1);
LFSensor[2] = digitalRead(lineFollowSensor2);
LFSensor[3] = digitalRead(lineFollowSensor3);
LFSensor[4] = digitalRead(lineFollowSensor4);

有了每個(gè)傳感器的值,必須實(shí)現(xiàn)一個(gè)邏輯來(lái)生成錯(cuò)誤變量:

if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 1 )) error = 4;
else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 1 )&&(LFSensor[4]== 1 )) error = 3; 
else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 1 )&&(LFSensor[4]== 0 )) error = 2;
else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 1 )&&(LFSensor[3]== 1 )&&(LFSensor[4]== 0 )) error = 1;
else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 1 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) error = 0;
else if((LFSensor[0]== 0 )&&(LFSensor[1]== 1 )&&(LFSensor[2]== 1 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) error =- 1;
else if((LFSensor[0]== 0 )&&(LFSensor[1]== 1 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) error = -2;
else if((LFSensor[0]== 1 )&&(LFSensor[1]== 1 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) error = -3;
else if((LFSensor[0]== 1 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) error = -4;

第 7 步:控制方向(比例控制 - P)

?
poYBAGNookWAIx1kAACr5K4TFJA971.jpg
?

完美的!至此,我們的機(jī)器人已經(jīng)組裝完畢并可以運(yùn)行了。您應(yīng)該對(duì)電機(jī)進(jìn)行一些基本測(cè)試,讀取傳感器的輸出并通過(guò)一條線對(duì)其進(jìn)行測(cè)試。缺少的是真正的“大腦”,即“人工智能”的第一步。我們將得到這一點(diǎn),實(shí)現(xiàn)一個(gè)控制邏輯,以保證機(jī)器人將保持跟隨線。

簡(jiǎn)單的比例控制:

假設(shè)機(jī)器人在一條線上運(yùn)行,傳感器陣列輸出為:“0 0 1 0 0” 。對(duì)應(yīng)錯(cuò)誤為“0”。在這種情況下,兩臺(tái)電機(jī)都應(yīng)該勻速向前運(yùn)行。

例如:

定義變量:iniMotorSpeed = 250 ; 表示左舵機(jī)將接收 1,250us 的脈沖,右舵機(jī)將接收 1,750us 的脈沖。使用這些參數(shù),機(jī)器人將以半速前進(jìn)。請(qǐng)記住,右舵機(jī)前進(jìn)速度的脈沖長(zhǎng)度范圍從 1,500us(停止)到 2,000us(全速),左舵機(jī)從 1,500us(停止)到 1,000us(全速)。

rightServo.writeMicroseconds(1500 + iniMotorPower);
leftServo.writeMicroseconds(1500 - iniMotorPower);

現(xiàn)在假設(shè)機(jī)器人向左行駛(就像“線向右”)并且還覆蓋了傳感器 3。陣列輸出將為:“0 0 1 1 0”并且錯(cuò)誤 = 1在這種情況下,您需要將機(jī)器人向右轉(zhuǎn)。為此,您必須降低 RIGHT 伺服的速度,這意味著減少脈沖的長(zhǎng)度。此外,左舵機(jī)的速度必須增加,這意味著減少左舵機(jī)脈沖的長(zhǎng)度。為此,我們需要更改電機(jī)控制功能:

rightServo.writeMicroseconds(1500 + iniMotorPower - error); ==> Positive error: decrease velocity
leftServo.writeMicroseconds(1500 - iniMotorPower - error); ==> Positive error: increase velocity

上述邏輯是正確的,但很容易理解,在脈沖長(zhǎng)度上添加或減去“1”微秒不會(huì)在實(shí)際時(shí)間產(chǎn)生所需的校正。很直觀,要加減的數(shù)字應(yīng)該更大,例如 50、100 等。為此,“誤差”必須乘以一個(gè)常數(shù)(我們稱其為“K”)。一旦這個(gè)常數(shù)的影響將與誤差成正比,我們將其命名為“比例常數(shù):Kp”

運(yùn)動(dòng)功能將是:

int Kp = 50;
rightServo.writeMicroseconds(1500 + iniMotorPower - Kp*error);
leftServo.writeMicroseconds(1500 - iniMotorPower - Kp*error);

我們可以恢復(fù)電機(jī)將發(fā)生的情況,如下所示:

  • 傳感器陣列:0 0 1 0 0 ==>錯(cuò)誤 = 0 ==> 右伺服脈沖長(zhǎng)度 = 1,750us ==> 左伺服脈沖長(zhǎng)度 = 1,250us(兩個(gè)電機(jī)速度相同)
  • 傳感器陣列:0 0 1 1 0 ==>錯(cuò)誤 = 1 ==> 右側(cè)伺服脈沖長(zhǎng)度 = 1,700us(較慢)==> 左側(cè)伺服脈沖長(zhǎng)度 = 1,200us(較快)

如果情況相反并且機(jī)器人向右驅(qū)動(dòng),則錯(cuò)誤將為“負(fù)”并且伺服系統(tǒng)的速度應(yīng)該改變:

  • 傳感器陣列:0 0 1 0 0 ==>錯(cuò)誤 = 0 ==> 右伺服脈沖長(zhǎng)度 = 1,750us ==> 左伺服脈沖長(zhǎng)度 = 1,250us(兩個(gè)電機(jī)速度相同)
  • 傳感器陣列:0 1 1 0 0 ==>錯(cuò)誤 = -1 ==> 右舵機(jī)脈沖長(zhǎng)度 = 1,800us(更快)==> 左舵機(jī)脈沖長(zhǎng)度 = 1,300us(更慢)

在這一點(diǎn)上,很明顯,機(jī)器人向一側(cè)行駛的次數(shù)越多,誤差越大,它必須更快地返回中心。機(jī)器人的速度將對(duì)誤差做出反應(yīng),與誤差成正比。這稱為“比例控制” ,即更復(fù)雜的控制網(wǎng)絡(luò) PDI(比例、微分、積分)的“P”組件。

第 8 步:PID 控制(可選)

?
?
?
?
pYYBAGNookeALq9QAABaEJsZ4cU603.jpg
?
1 / 3
?

如果你想跳過(guò)這部分,也可以。您可以繼續(xù)使用上一步解釋的比例控制,也可以燒一些腦筋在您的機(jī)器人中實(shí)現(xiàn)更復(fù)雜的控制系統(tǒng),這是您的選擇。

如果你下定決心,那就走吧!

PID(比例、微分和積分)是最常見(jiàn)的控制方案之一。大多數(shù)工業(yè)控制回路使用某種 PID 控制。調(diào)整 PID 回路的方法有很多,包括本例中使用的手動(dòng)技術(shù)。

將 PID 視為一個(gè)簡(jiǎn)單的彈簧。彈簧具有原始長(zhǎng)度,當(dāng)受到膨脹或收縮的干擾時(shí),它往往會(huì)在盡可能短的時(shí)間內(nèi)恢復(fù)其原始長(zhǎng)度。類似地,系統(tǒng)中的 PID 算法具有要控制的特定物理量的設(shè)定值,稱為“ set point ”,當(dāng)由于某種原因改變時(shí),系統(tǒng)控制其中的其他必要特征,以回到在盡可能短的時(shí)間內(nèi)達(dá)到初始設(shè)定點(diǎn)。PID 控制器用于需要控制物理量并使其等于指定值的任何地方。例如,汽車中的巡航控制器、機(jī)器人、溫度調(diào)節(jié)器、電壓調(diào)節(jié)器等。

PID是如何工作的?

系統(tǒng)通過(guò)使用傳感器測(cè)量該物理量的當(dāng)前值,從設(shè)定點(diǎn)計(jì)算物理量的“ error”或“ ”。deviation為了回到設(shè)定點(diǎn),這個(gè)' error'應(yīng)該被最小化,并且應(yīng)該理想地等于零。此外,這個(gè)過(guò)程應(yīng)該盡快發(fā)生。理想情況下,系統(tǒng)對(duì)其設(shè)定點(diǎn)變化的響應(yīng)應(yīng)該為零滯后。

更多信息可以在許多書(shū)籍和網(wǎng)站中找到,包括這里。

實(shí)施 PID

i) 誤差項(xiàng) (e):

這等于設(shè)定點(diǎn)與被控制量的當(dāng)前值之間的差值。Error = set_pointcurrent_value(在我們的例子中是從 Robot 線上的位置獲取的誤差變量

ii) 比例項(xiàng) (P):

該項(xiàng)與誤差成正比。

P = 錯(cuò)誤

該值負(fù)責(zé)物理量達(dá)到設(shè)定點(diǎn)所需的變化幅度。比例項(xiàng)決定了控制回路的上升時(shí)間或達(dá)到設(shè)定點(diǎn)的速度。

iii) 積分學(xué)期 (I):

該項(xiàng)是所有先前誤差值的總和。

我 = 我 + 錯(cuò)誤

該值負(fù)責(zé)系統(tǒng)對(duì)設(shè)定點(diǎn)變化的響應(yīng)速度。積分項(xiàng)用于消除比例項(xiàng)所需的穩(wěn)態(tài)誤差。通常,小型機(jī)器人不使用積分項(xiàng),因?yàn)槲覀儾魂P(guān)心穩(wěn)態(tài)誤差,它會(huì)使“ loop tuning”復(fù)雜化。

iv) 微分或微分項(xiàng) (D):

該項(xiàng)是設(shè)定點(diǎn)的瞬時(shí)誤差與前一時(shí)刻的誤差之差。

D = 錯(cuò)誤 - previousError

當(dāng)物理量接近設(shè)定點(diǎn)時(shí),該值負(fù)責(zé)減慢物理量的變化率。微分項(xiàng)用于減少過(guò)沖或系統(tǒng)應(yīng)“ over correct”的程度。

方程:

PID 值 = (Kp*P) + (Ki*I) + (Kd*D)

在哪里:

Kp是用于改變達(dá)到設(shè)定點(diǎn)所需的變化幅度的常數(shù)。Ki是用于改變物理量的變化率以達(dá)到設(shè)定點(diǎn)的常數(shù)。Kd是用于改變系統(tǒng)穩(wěn)定性的常數(shù)。

調(diào)整循環(huán)的一種方法是Try-error tentative 方法

Kd 變量設(shè)置為 0并首先單獨(dú)調(diào)整 Kp 項(xiàng)。在我們的案例中, Kp 為 25是一個(gè)很好的起點(diǎn)。在最后一步,我們使用了 50 的 Kp,這與我的機(jī)器人非常配合。一旦機(jī)器人做出合理響應(yīng),調(diào)整控制回路的微分部分 ( Kd )。首先將 Kp 和 Kd 值分別設(shè)置為 Kp 值的 1/2。例如,如果機(jī)器人響應(yīng)合理,Kp = 50,則設(shè)置 Kp = 25 和 Kd = 25 開(kāi)始。增加 Kd(微分)增益以減少過(guò)沖,如果機(jī)器人變得不穩(wěn)定,則減少它。

  • 如果機(jī)器人反應(yīng)太慢,請(qǐng)?jiān)黾釉撝怠?/font>
  • 如果機(jī)器人似乎反應(yīng)迅速變得不穩(wěn)定,請(qǐng)減小該值。

要考慮的循環(huán)的另一個(gè)組成部分是實(shí)際的Sample/Loop Rate。加快或減慢此參數(shù)可以顯著提高機(jī)器人的性能。這是由代碼中的延遲語(yǔ)句設(shè)置的。這是一種嘗試錯(cuò)誤的嘗試方法,以獲得最佳結(jié)果。

基于上述方法,實(shí)現(xiàn)了以下功能:

void calculatePID()
{
  P = error;
  I = I + error;
  D = error-previousError;
  PIDvalue = (Kp*P) + (Ki*I) + (Kd*D);
  previousError = error;
}

最后一步使用的簡(jiǎn)單 Kp 常數(shù)將被替換為更完整PIDvalue

void motorPIDcontrol()
{
  int leftMotorSpeed = 1500 - iniMotorPower - PIDvalue;
  int rightMotorSpeed = 1500 + iniMotorPower - PIDvalue;
  
  leftServo.writeMicroseconds(leftMotorSpeed);
  rightServo.writeMicroseconds(rightMotorSpeed);
}

但請(qǐng)注意,如果您有 Kd 和Ki =0 ,PIDvalue 則僅在最后一步中使用 Kp*error。

第 9 步:最終代碼

?
?
?
?
pYYBAGNookqAD9tJAAFqvgi7ZjE223.jpg
?
1 / 2
?

在這一步,機(jī)器人可以遵循一個(gè)恒定的循環(huán),并且不會(huì)停止。循環(huán)程序?qū)⑹牵?/font>

void loop ()
{
  readLFSsensors(); // read sensors, storage values at Sensor Array and calculate "error"
  calculatePID(); 
  motorPIDcontrol();
}

但是為了更完整和真實(shí)的操作,添加至少幾個(gè)基礎(chǔ)commands “完成”是很重要的with the line 。例如,讓我們引入一個(gè)新變量:“ mode ”。我們將為這個(gè)變量定義 3 個(gè)狀態(tài):

模式:

  • #define STOPPED 0
  • #define FOLLOWING_LINE 1
  • #define NO_LINE 2

如果所有傳感器都找到一條黑線,則傳感器陣列輸出將為:1 1 1 1 1。在這種情況下,我們可以將模式定義為“STOPPED”,機(jī)器人應(yīng)該執(zhí)行“ full stop”。

if((LFSensor[0]== 1 )&&(LFSensor[1]== 1 )&&(LFSensor[2]== 1 )&&(LFSensor[3]== 1 )&&(LFSensor[4]== 1 )) 
{ 
  mode = STOPPED;
}

Follower Line Robots 的其他常見(jiàn)情況是它找到“ no line ”的位置,或者 Sensor Array 輸出為:0 0 0 0 0。在這種情況下,我們可以將其編程為返回 180o 或以小角度轉(zhuǎn)動(dòng),直到找到一條線并且恢復(fù)正常的線路跟隨條件。

else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) 
{ 
  mode = NO_LINE;
}

完整的loop ()將是:

void loop() 
{
  readLFSsensors();
  switch (mode)
  {
    case STOPPED:
       motorStop();
       break;
    case NO_LINE:
       motorStop();
       motorTurn(LEFT, 180);
       break;
    case FOLLOWING_LINE:
       calculatePID();
       motorPIDcontrol();
       break;
  }
}

真正的最終代碼將集成一些額外的邏輯以及一些必須初始化的變量等。在上面的解釋中,為了簡(jiǎn)單起見(jiàn),我將它們省略了,但看最終代碼應(yīng)該一切都清楚。

下面是最終的 Arduino 代碼:

?
?
?
?
?

第 10 步:使用 Android 應(yīng)用程序調(diào)整 PID 控制

?
?
?
?
pYYBAGNookyAHlHIAACeYdDwLI0635.jpg
?
1 / 3
?

在前面的代碼中,您可以在“ robotDefines.h”選項(xiàng)卡中找到以下用于 PID 控制的常數(shù)定義:

float Kp=50;
float Ki=0;
float Kd=0;

如上一步所述,定義與 PID 控制器一起使用的正確常數(shù)的最佳方法是使用“試錯(cuò)”方法。不好的一面是每次必須更改程序時(shí)都必須重新編譯程序。加速該過(guò)程的一種方法是使用 Android 應(yīng)用程序在“設(shè)置階段”發(fā)送常量。

我專門為此開(kāi)發(fā)了一個(gè) Android 應(yīng)用程序。簡(jiǎn)而言之,有傳統(tǒng)的手動(dòng)命令:

  • FW、BW、Left、Right 和 Stop,應(yīng)用程序?qū)⒎謩e發(fā)送到 BT 模塊:'f'、'b'、'l'、'r' 和 's'。

還包括 3 個(gè)滑塊,每個(gè) PID 常數(shù)一個(gè):

  • Kd:“d/XXX”,其中“XXX”是一個(gè)從 0 到 100 的數(shù)字。
  • Kp:“p/XXX”
  • Ki:“我/XXX”

包括一個(gè)額外的按鈕,它與 Arduino Pin9 上連接的按鈕完全一樣。您可以使用其中一種,沒(méi)關(guān)系。

您可以在下面找到.aia 可以在MIT AppInventor修改的.apk 文件以及要直接安裝在您的 Android 設(shè)備中的文件。

?
?

第 11 步:更改 PID 遠(yuǎn)程調(diào)整的代碼

在設(shè)置過(guò)程中,我們將引入一個(gè)循環(huán),您可以在其中將 PID 參數(shù)發(fā)送給機(jī)器人,然后再將其置于線路上:

 while (digitalRead(buttonPin) && !mode)
  {  
    checkBTcmd();  // verify if a comand is received from BT remote control
    manualCmd ();    
    command = "";  
  }
  checkPIDvalues();
  mode = STOPPED;

手動(dòng)命令功能將是:

void manualCmd()
{
  switch (command[0])
  {
    case 'g':
      mode = FOLLOWING_LINE;
      break;
    
    case 's': 
      motorStop(); //turn off both motors
      break;
    case 'f':  
      motorForward();  
      break;
    case 'r':     
      motorTurn(RIGHT, 30);
      motorStop();
      
      break;
   case 'l': 
      motorTurn(LEFT, 30);
      motorStop();
      break;
    
    case 'b':  
      motorBackward();
      break;
      
    case 'p':
      Kp = command[2];
      break;
    
    case 'i':
      Ki = command[2];
      break; 
    
    case 'd':
      Kd = command[2];
      break;
  }
}

視頻中,您可以看到一些使用 Android 應(yīng)用程序的測(cè)試。在最終代碼下方,包括通過(guò) Android 設(shè)置的 PID:

?
?
?
?
?
?

第 12 步:結(jié)論

?
pYYBAGNVny-AfjK0AACej2Rcuno506.jpg
?

這是一個(gè)更復(fù)雜項(xiàng)目的第一部分,探索線跟隨機(jī)器人的潛力。在下一部分中,我將基于這個(gè)項(xiàng)目在這里開(kāi)發(fā)一個(gè)迷宮求解機(jī)器人。希望我可以為其他人做出貢獻(xiàn),以了解更多關(guān)于電子、機(jī)器人、Arduino 等的知識(shí)。

這個(gè)項(xiàng)目的更新文件可以在GITHUB找到。更多教程請(qǐng)?jiān)L問(wèn)我的博客:MJRoBot.org

?


下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評(píng)論

查看更多

下載排行

本周

  1. 1山景DSP芯片AP8248A2數(shù)據(jù)手冊(cè)
  2. 1.06 MB  |  532次下載  |  免費(fèi)
  3. 2RK3399完整板原理圖(支持平板,盒子VR)
  4. 3.28 MB  |  339次下載  |  免費(fèi)
  5. 3TC358743XBG評(píng)估板參考手冊(cè)
  6. 1.36 MB  |  330次下載  |  免費(fèi)
  7. 4DFM軟件使用教程
  8. 0.84 MB  |  295次下載  |  免費(fèi)
  9. 5元宇宙深度解析—未來(lái)的未來(lái)-風(fēng)口還是泡沫
  10. 6.40 MB  |  227次下載  |  免費(fèi)
  11. 6迪文DGUS開(kāi)發(fā)指南
  12. 31.67 MB  |  194次下載  |  免費(fèi)
  13. 7元宇宙底層硬件系列報(bào)告
  14. 13.42 MB  |  182次下載  |  免費(fèi)
  15. 8FP5207XR-G1中文應(yīng)用手冊(cè)
  16. 1.09 MB  |  178次下載  |  免費(fèi)

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234315次下載  |  免費(fèi)
  3. 2555集成電路應(yīng)用800例(新編版)
  4. 0.00 MB  |  33566次下載  |  免費(fèi)
  5. 3接口電路圖大全
  6. 未知  |  30323次下載  |  免費(fèi)
  7. 4開(kāi)關(guān)電源設(shè)計(jì)實(shí)例指南
  8. 未知  |  21549次下載  |  免費(fèi)
  9. 5電氣工程師手冊(cè)免費(fèi)下載(新編第二版pdf電子書(shū))
  10. 0.00 MB  |  15349次下載  |  免費(fèi)
  11. 6數(shù)字電路基礎(chǔ)pdf(下載)
  12. 未知  |  13750次下載  |  免費(fèi)
  13. 7電子制作實(shí)例集錦 下載
  14. 未知  |  8113次下載  |  免費(fèi)
  15. 8《LED驅(qū)動(dòng)電路設(shè)計(jì)》 溫德?tīng)栔?/a>
  16. 0.00 MB  |  6656次下載  |  免費(fèi)

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935054次下載  |  免費(fèi)
  3. 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
  4. 78.1 MB  |  537798次下載  |  免費(fèi)
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420027次下載  |  免費(fèi)
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234315次下載  |  免費(fèi)
  9. 5Altium DXP2002下載入口
  10. 未知  |  233046次下載  |  免費(fèi)
  11. 6電路仿真軟件multisim 10.0免費(fèi)下載
  12. 340992  |  191187次下載  |  免費(fèi)
  13. 7十天學(xué)會(huì)AVR單片機(jī)與C語(yǔ)言視頻教程 下載
  14. 158M  |  183279次下載  |  免費(fèi)
  15. 8proe5.0野火版下載(中文版免費(fèi)下載)
  16. 未知  |  138040次下載  |  免費(fèi)