一、引言
2014年10月18日開始接觸到自平衡小車,于是就有了DIY自平衡小車的沖動了,于是在網上看到很多有關自平衡小車的帖子,在淘寶上也發現有很多現成的套件或相應的部件,這些豐富的資源極為凌亂,讓新入行的人很難決策、不知如何下手。正如當下的社會一樣,專家太多,而且各種專家的見解相同,甚至意見相左,弄得新入行的人更不知道怎么辦了。
首先聲明,我不是什么專家,只是一個過來人,走過的路多一些、時間長一些,遇到的挫折也多一些而已,所以有點自己的體會。特別是接觸到現在的很多年輕人,再加上我自己也是剛剛接觸自平衡小車,就有些想要說的話了,但確沒有要說的具體對象,于是就在此瞎說一通,有不對的地方,請廣大的“xx友”予以斧正!
做自平衡小車是要花錢、花精力的,很多新人還是學生,還沒有收入,所以在花錢這方面就更猶豫了,特別是淘寶上介紹的什么價位的東西都有,好的東西貴,便宜的東西又怕不靠譜。其實,對于真正的發燒友來說,錢是次要的,他們的經驗都是靠前期花費的銀子積累起來的,別看他們有了經驗之后,往往花點小錢就能解決大問題。關于花錢我也是一樣,換個手機、吃頓飯很隨便,錢花得多了去了,但是要買點這些東西就算計來算計去,一點小錢都要花費幾個小時來回比較,哪怕運費貴兩塊錢都不愿意。我雖然做了一個這樣不起眼的小東西,現在來看直接成本能控制在100元以內,但我前期來回折騰的錢統計了一下有1121.15元。所以這里介紹一些東西的目的,也是讓還未有收入來源的學生們花點小錢積累更多一些的經驗,從而提高“投入產出”比,我就當作你們前面的探路者之一吧。
想做自平衡小車的我接觸的有下面幾類人群:
1、好奇,看到這個很神奇,而且有那么多人都做成了,我也是學了這么多年了,也會不少東西了,所以我也要做一個;
2、想通過這個自平衡小車學單片機;
3、自己學的專業與此相關,所以想拿他開刀,來練練手;
4、還有就是我這樣的人,沒事干,又有點“經驗”,拿它來消磨時間,填補自己的空虛。
無論是哪類人群,如果是第一次上手,請都不要輕敵,當然也不排除一次就蒙成功了的,東西是做出來了,但我想從中學到的東西是不會太多的。
還有很多新人都認為算法最復雜,也是最為困難的部分,其實我的看法是這部分恰恰是很簡單的部分,如果前期障礙都解決了(譬如,買了一套現成的小車底盤,和一些參考資料),剩下的還真就是簡單的編寫(其實大部分也是抄來的)程序、調整一下參數,就成功了,其結果就是照葫蘆畫了個瓢!
如果,沒解決前期問題,就像很多人一樣,怎么調參數都調不好,因為他們只知道程序和算法,不知道的就不去分析和想辦法知道,想辦法去解決,就在沒問題的部分瞎折騰。這是我想起一個寓言:就是燈下找鑰匙,一個人看到另外一個人晚上在路燈下找東西,就問他,你找什么東西啊?那個人說,我找鑰匙。你的鑰匙是掉在這兒嗎?他說不是掉在這兒。那你為什么要在這兒找呢,他說因為這兒有燈,看得見,別的地放沒亮光,我看不見。
想做還沒做的你們有些什么樣的想法和看法呢?
下面給新人如何交流技術問題提個建議:
技術問題交流不能像日常生活中大媽們對話那樣(這也是網絡聊天的模式),簡短的幾個詞就能表達的,就像我們單位的年輕人說話方式一樣,問他某項工作的情況,他就會說一句,沒問題或者說不行,話要是能這樣簡單說下就能很好交流的,要么是相當的高手,要么是在一起生活了幾十年的兩口子。
你們說行和不行,都要說清楚(注意這里的清楚二字,很多人話是說不清楚的),做了哪些工作,是怎么做的,現象是怎樣的,最好是有圖有數據,不要自己就給出一個結論來,因為之前的有些工作不到位,甚至有錯誤,這個結論是不靠譜的,結論是由聽者自己來下的,而不是由說者告訴聽者!!!
有些人,想問的問題也說不出來(的確有人知道,說不出來,還有些人能說出來,卻寫不出來),這時候你們最好上照片,上圖吧,圖文并茂的表達。
二、PID那點事
關于PID的算法,網絡上資料很多,也有各種通俗易懂的解釋,我這里想給大家一個只要具有初中數學、物理基礎的人,就能明白的一種不甚嚴謹的,但容易理解的一種解釋方法。
先給出一個典型的PID算法框圖,如下圖:
105134otuuzrjwcpipncuw.jpg (16.76 KB, 下載次數: 271)
下載附件
2016-4-11 15:06 上傳
我這里先將此圖簡化為僅剩P控制部分的框圖,至于其他的I和D部分,最后僅用兩句話解釋一下就行了,再也無需太多的解釋了。
105157obk4dz4443p7fgg3.jpg (12.77 KB, 下載次數: 232)
下載附件
2016-4-11 15:06 上傳
比例調節的公式是:u(t) = Kp * e(t),e(t) = r(t) – c(t)
其中:r(t) 是設定值,就是你想讓被控系統某個參數所要保持的狀態值; c(t)是系統的這個參數的實際狀態值。
比例調節的過程就是即時成比例地反應控制系統的偏差信號e(t),偏差一旦產生,通過 Kp * e(t) 產生控制作用以減小偏差。理想的情況是有多大的誤差,通過這個調節作用之后,就能將誤差消除。但實際情況并非都是那么理想,Kp小了,修正不到位,Kp大了就會出現矯枉過正的現象。
對于自平衡小車來說,要控制的這個參數就是小車的傾斜角度,就是想辦法讓這個小車停在你所設定的角度上,這樣小車就能穩定平衡了。
這樣我們就知道了,控制的作用就是想讓被控系統穩定在你所設定的某個值上。拿小車的平衡來說就是讓小車的傾斜角度與其物理(就是小車不控制時,能夠自然穩定)平衡角度一致,始終保持在這個傾斜狀態。
對于有些結構比較好的小車,僅比例這一項,在沒有大的擾動的情況下,的確就能穩定的控制小車平衡。但往往情況并非這么理想,所以還要用到積分項I或微分項D。那么實際會出現小車來回擺動,或者始終往某個方向傾斜,造成小車往一邊跑,最后控制不住就倒地了。
先說說來回擺動的問題吧,來回擺動是不是就是小車有一定的傾斜轉動角速度,角速度是什么呢?角速度是不是就是角度的微分(有點超出初中的知識范圍了,還是改成初中能理解的語言吧,也就是說速度是不是在單位時間內的位置差)。好了,我要不想讓他擺動,是不是控制這個角速度為0,是不是就不擺動了。那么,我們增加D項,就能達到這個目的,雖然不是絕對的解決,但還是明顯的改善了很多的。
下面接著說始終往一邊偏的問題,如果能不往一邊偏,僅來回擺動,也就是這個角度一會大、一會小,一會正、一會負,經過積分(又超出范圍了,長時間的角度求平均),這個角度平均值幾乎是0,如果往一邊偏的話,這個平均值就是某個不為0的值了,這是我們加上I項就能克服這個問題了。
啰里啰嗦的說多了,打字也打累了,趕緊總結一下結束吧。
PID控制:對于角度環來說:P是消除角度的誤差,I是消除角度累積的誤差,D是消除角度變化率(角速度)的誤差;同理,對于速度環來說:P是消除速度的誤差,I是消除速度累積(位置)的誤差,D是消除速度變化率(加速度)的誤差。
三、方案選擇
經歷過項目開發的人員都知道,第一個首要任務就是要進行需求分析,這個需求是要認真分析的,因為需求不是一個單一不變的變量,更不是一個不變的常量。他是在一定的范圍和一段時間內都要符合你的需求,滿足你的需要。在做這個小車時,個人的需求也符合馬斯洛的需求層次理論的。在需求分析中最重要的是要列出那些相互矛盾的方面,并且要根據自己的核心需求進行合理和有效的舍取。
那么我這里提出的自平衡小車入門,也是要滿足一組特定的需求,現將其羅列如下:
1、投入的經費要低;
2、小車要能很好的實現平衡,而且是要在一定的控制下實現的自平衡,而不是那種不倒翁式的平衡(結構本身就具有的能力);
3、盡量像那些大神們一樣,也能控制它前后運動和左右轉動;
4、門檻要低,就是容易成功,而不是折騰得“要死的心都有了”(有些網友在調試過程中發出的感慨);
5、從中能提高自己的動手能力、提高分析和解決問題的能力;
6、能對大家覺得神奇的PID有深刻的體會。
自平衡小車無論什么方案都有以下幾個部分:一是檢測平衡狀態所用的傳感器;二是控制核心的處理器;三是執行控制動作的電機。
傳感器有加速度、陀螺組合的,有用超聲波測距的,還有用紅外測距的;
處理器流行的有用STM32系列的,有用Arduino開源的,也還有人用最傳統的51系列的;
電機有用帶AB相測速輸出的強動力的電機,也有用步進電機,還有用舵機的,也有用低廉的TT馬達(俗稱香蕉電機)。
根據上述的入門需求,我這里提供的入門方案配置如下:超聲波測距傳感器 + Arduino Nano控制模塊 + TT馬達(L298N電機驅動模塊) + 7.4V/2200mAh鋰電池 + 藍牙串口無線模塊。
這個方案的核心優點(除了成本低之外)是超聲波測距模塊,抗干擾強,不像MPU6050極容易受干擾(電磁干擾和安裝位置敏感性的機械干擾),關于MPU6050的問題,大家可以在網絡上看看一些新手們的煩惱(死機、數據不穩定等等)。
這個方案遭人詬病的是,“超聲波測距的自平衡小車不能爬坡、不能在斜坡上平衡”,首先這里所說的不能爬坡和不能在斜坡上平衡說法本身就極為不準確,這是網絡上說話不靠譜的通病,其實他們想要表達的是在坡度變化的地方,超聲波測距方式的自平衡小車不是實現平衡控制。這種說法的人只是憑自己想當然的一種臆斷,沒有任何實際的根據,根據我的實踐,這個問題通過速度環的控制是完全能夠解決的。其實爬坡的關鍵點,是看你的電機性能如何,而不是別的什么。
在這里補充說明一點,有很多人想用這個作為學習單片機的平臺,這個想法我個人覺得有點反了,要學單片機,這個平臺太局限了,選擇別的可能要更合適一些。
前面這三節都是務虛的,從下面開始逐漸深入到實處,有些東西因為涉及到入門,可能寫得也啰嗦一些了,因為有些網友真的是一點基礎(概念)也沒有、從未動過手,但還是很執著的想做這個,為了照顧他們,會的人一是忍忍,另一方面也幫助幫助那些需要幫助的人吧!
150733f35cv9ohrvbhrvts.jpg (80.69 KB, 下載次數: 274)
下載附件
2016-4-11 15:06 上傳
四、硬件設計
根據方案的框圖,首先分別介紹各模塊,由于這里主要是討論自平衡小車,而不是學習單片機,所以與自平衡小車關系不大的單片機使用以及程序部分就不擬討論了。按照框圖順序和硬件調試步驟,首先介紹的是超聲波測距模塊。
4.1、超聲波測距模塊
我們選擇的超聲波測距模塊型號是:新款HC-SR04超聲波測距模塊。
這個模塊的淘寶鏈接是:
192144f6az1ryqz7rmyt1q.jpg (373.12 KB, 下載次數: 257)
下載附件
2016-4-11 15:06 上傳
192159ldelgb167m2ms6mg.jpg (385.86 KB, 下載次數: 232)
下載附件
2016-4-11 15:06 上傳
推薦用這種
192223pxiztx3okqxhlzr7.jpg (36.48 KB, 下載次數: 263)
下載附件
2016-4-11 15:06 上傳
不推薦用這種,就是圖中紅色區域有個4MHz的晶體
它的特點,我從賣家那里摘抄部分信息如下:
新款提升了IC性能,因晶振受低溫環境影響,頻率容易發生漂移。所以去掉了晶振。比帶晶振的穩定很多,此型號為原廠原裝型號,市場上大部分4塊多錢的HC-SR04帶晶振的那種,都是仿品性能不穩定!(通過我買的幾種對比,情況的確如此,有些精度更高的,近距離運用時,效果更差)
(1)主要技術參數
工作電壓:DC5V
靜態電流:小于2mA
電平輸出:高電平5V、低電平0V
感應角度:不大于15度
探測距離:2cm ~ 450cm
精度:可達0.3cm
(2)接線方式
VCC(電源正端)可用杜邦線接Arduino Nano模塊的5V端;
GND(地)接Arduino Nano模塊的GND;
Trig(控制端)接Arduino Nano模塊的D4;
Echo(接收端)接Arduino Nano模塊的D5。
(3)工作原理:
采用IO觸發測距,給Trip控制端至少10us的高電平信號;模塊自動發送8個40khz的方波,并自動檢測是否有信號返回;如有信號返回,通過Echo輸出一高電平,高電平持續的時間就是超聲波從發射到返回的時間。
測試距離 =(高電平時間 * 聲速)/ 2。
192328rs3uuxgan0anlg3n.jpg (82.24 KB, 下載次數: 274)
下載附件
2016-4-11 15:06 上傳
測試原理圖
192353xzmjgu04vjhgvjjn.jpg (177.07 KB, 下載次數: 239)
下載附件
2016-4-11 15:06 上傳
測試接線照片
//超聲波測距模塊測試程序
char val='z'; //調節與控制命令字
unsigned int TrigPin = 4, EchoPin = 5, Len_Echo = 0; //HC-SR04觸發信號,回波檢測,回波時間
unsigned long systime0; //上次系統時間,當前時間
//初始化
void setup() {
Serial.begin(115200);
pinMode(EchoPin, INPUT); //超聲波測距
pinMode(TrigPin, OUTPUT);
digitalWrite(TrigPin, LOW);
systime0 = millis(); //讀取系統時間
}
//主循環程序
void loop() {
if(millis() - systime0 >= 5){ //系統循環周期為5ms
systime0 = millis();
digitalWrite(TrigPin, HIGH); //發送超聲波測量觸發脈沖
delayMicroseconds(10);
digitalWrite(TrigPin, LOW);
Len_Echo = pulseIn(EchoPin, HIGH); //回波時間測量
if (Serial.available() > 0) {
val = Serial.read();
if(val == 'A') {
Serial.println(Len_Echo); //超聲波測距輸出
}
}
}
}
使用串口調試助手(sscom42.exe)發送字符“A”命令讀取超聲波的測距值。
sscom42.zip
(338.41 KB, 下載次數: 25)
2016-4-11 14:12 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
程序中超聲波的測量周期是5ms,一般超聲波測距的測量周期遠遠大于這個值,但在小車平衡中,這個值不能太大,否則是不能穩定控制住小車平衡的。
串口測試界面如下圖所示:
192605qg7g8g87nmgqz7ge.jpg (87.07 KB, 下載次數: 277)
下載附件
2016-4-11 15:06 上傳
注意:串口號選擇要正確,比特率要與程序中的一致(此處為115200),這里為了方便,串口輸出的是字符串,發送的命令是“A”,圖中用了100ms間隔的定時發送。
曬曬做自平衡小車過程中我所花費的清單:
081119pcse8erq5g8cv99c.jpg (385.7 KB, 下載次數: 261)
下載附件
2016-4-11 15:06 上傳
4.2、自平衡小車供電
本想講控制板輸出后的電機驅動模塊,后來一想,沒有電,這個模塊怎么驅動呀,所以接下來先說說自平衡小車的供電吧。
我們這里因為選用的是TT馬達,它的工作電壓網上給出的是DC3~6V,6V時的空載電流小于200mA,為了不頻繁的充電,我們選用容量大一點的7.4V鋰電池,其容量為2200mAh。在網上搜了一家性價比還不錯的淘寶店鋪,鏈接如下(注意,東西最好一次買齊,有備份的更好):
082049jivet17f6gt0wfvt.jpg (113.07 KB, 下載次數: 229)
下載附件
2016-4-11 15:06 上傳
充電器:
082126b2wmop2q2plpw2z2.jpg (101.82 KB, 下載次數: 239)
下載附件
2016-4-11 15:06 上傳
連接線:
082150mxnkubnlz9mvfyvz.jpg (102.71 KB, 下載次數: 254)
下載附件
2016-4-11 15:06 上傳
下面給出這個自平衡小車電池供電的電路原理圖。
082215ouu06o00uoj49kh0.jpg (185.66 KB, 下載次數: 224)
下載附件
2016-4-11 15:06 上傳
BT為7.4V鋰電池,CB為充電接口。電池通過開關S1分別給Arduino Nano模塊和L298N電機驅動模塊供電。這個原理圖沒什么可說明的,照著連接,別接錯了,正負別接反了就沒問題。
4.3、電機驅動模塊
電機驅動模塊,我們選擇最常用的,價格低廉的L298N電機驅動模塊,這個模塊可以同時驅動兩個電機,正好適用我們的需求。直接給出淘寶鏈接如下:
你們可能會發現,有很多東西,你怎么都推薦這家呢,首先聲明,我跟他們一點關系都沒有,我之所以選這家,是在價格合理的情況下,盡量在這一家把東西買齊,這樣你們就會少花費運費了,可以節約點小錢。
092415um1z0z7vtqv417fv.jpg (116.84 KB, 下載次數: 265)
下載附件
2016-4-11 15:06 上傳
092450wccddywutkidgkip.jpg (94.71 KB, 下載次數: 241)
下載附件
2016-4-11 15:06 上傳
092531y9xtjdbvjummd6ux.jpg (222.8 KB, 下載次數: 238)
下載附件
2016-4-11 15:06 上傳
該模塊是2路的H橋驅動,所以可以同時驅動兩個電機,在自平衡小車中通常利用ENA、ENB使能端輸入控制兩個電機的PWM信號,分別控制兩個電機的轉速;利用IN1、IN2輸入控制電機1的方向; 利用IN3、IN4輸入控制電機2的方向。其控制邏輯表如下:
092554upfiugkrbrgurrzx.jpg (66.27 KB, 下載次數: 240)
下載附件
2016-4-11 15:06 上傳
電路原理圖如下:
092623zq1tf21cqc1lelbc.jpg (212.64 KB, 下載次數: 274)
下載附件
2016-4-11 15:06 上傳
這個電路原理其實也沒什么可說的,但有些新手憑自己的想當然,要么用Arduino Nano模塊的5V接到L298N模塊的5V(看清楚,L298N的5V是輸出,不是輸入)。有明白不能接這里的,他接到L298N模塊的VIN,Arduino Nano模塊的5V提供不了大電流,這種接法如果是負載重點(電機工作電流比較大時),無異于將Arduino Nano模塊的5V短路(效果差不多,就是燒掉了)。再明白一點的人將L298N的Vin和GND接到7.4V的電池或其他外部獨立供電的電源上,但告訴我程序控制不了電機,電機不轉,其原因是什么呢?他的Arduino Nano模塊是通過USB接口供電的,Arduino Nano模塊與L298N模塊沒有共地,這一切看似簡單的問題,在有些新手那里就是百思不得其解,這些問題他們因為不知道原因,所以也提不出問題,好在看到現場接線的照片,還能幫著分析分析,有些問題你如果不在現場真是你想不到的狀況。
還有的人也會檢查,用電壓表測輸出給電機的電壓,但是怎么測的呢?他是分別測量OUT1~OUT4對GND的電壓。這個說明他們不知道H橋是怎么回事,也不知道電機上的電壓是什么。
L298N模塊拿到手后,在用程序測試之前,先直接加電測試確定模塊是否正常。測試方法是給VIN與GND之間加上工作電壓,IN1~IN4、ENA、ENB按照控制邏輯表加信號,看看OUT1-OUT2和OUT3-OUT4之間的電壓是否正常,不同的控制情況下,這個電壓的極性是否會反轉。如果一切正常進入程序測試階段。
下面給出測試程序,包含了前面的超聲測距的程序。
//藍牙遙控無碼盤,TT馬達超聲自平衡小車硬件單元測試程序
char val='z'; //調節與控制命令字
int Left_PWM, Right_PWM; //左右電機PWM輸出
unsigned int TrigPin = 4, EchoPin = 5, Len_Echo = 0; //HC-SR04觸發信號,回波檢測,回波時間
unsigned int M_IN1 = 6, M_IN2 = 7, M_IN3 = 8, M_IN4 = 9; // L298:IN1-IN4
unsigned int M_ENA = 10, M_ENB = 11; // L298:ENA-ENB
unsigned long systime0; //上次系統時間,當前時間
//電機輸出
void SetMotorVoltage(int Left_MotorVol, int Right_MotorVol) {
if(Left_MotorVol >= 0) {
digitalWrite(M_IN1, LOW);
digitalWrite(M_IN2, HIGH);
}else {
digitalWrite(M_IN1, HIGH);
digitalWrite(M_IN2, LOW);
Left_MotorVol = -Left_MotorVol;
}
if(Right_MotorVol >= 0) {
digitalWrite(M_IN3, LOW);
digitalWrite(M_IN4, HIGH);
}else {
digitalWrite(M_IN3, HIGH);
digitalWrite(M_IN4, LOW);
Right_MotorVol = -Right_MotorVol;
}
if(Left_MotorVol > 255) Left_MotorVol = 255; //防止PWM值超過255
if(Right_MotorVol > 255) Right_MotorVol = 255; //防止PWM值超過255
analogWrite(M_ENA, Left_MotorVol);
analogWrite(M_ENB, Right_MotorVol);
}
//初始化
void setup() {
Serial.begin(115200);
pinMode(M_ENA, OUTPUT); //電機控制
pinMode(M_IN1, OUTPUT);
pinMode(M_IN2, OUTPUT);
pinMode(M_ENB, OUTPUT);
pinMode(M_IN3, OUTPUT);
pinMode(M_IN4, OUTPUT);
pinMode(EchoPin, INPUT); //超聲波測距
pinMode(TrigPin, OUTPUT);
digitalWrite(TrigPin, LOW);
systime0 = millis(); //讀取系統時間
}
//主循環程序
void loop() {
if(millis() - systime0 >= 5){ //系統循環周期為5ms
systime0 = millis();
digitalWrite(TrigPin, HIGH); //發送超聲波測量觸發脈沖
delayMicroseconds(10);
digitalWrite(TrigPin, LOW);
Len_Echo = pulseIn(EchoPin, HIGH); //回波時間測量
SetMotorVoltage(Left_PWM, Right_PWM);
if (Serial.available() > 0) {
val = Serial.read();
if(val == 'A') {
Serial.println(Len_Echo); //超聲波測距輸出
}
if(val == 'B') {
Left_PWM ++; Serial.print(Left_PWM); Serial.print(" "); Serial.println(Right_PWM);//左電機加速
}
if(val == 'b') {
Left_PWM --; Serial.print(Left_PWM); Serial.print(" "); Serial.println(Right_PWM);//左電機減速
}
if(val == 'C') {
Right_PWM ++; Serial.print(Left_PWM); Serial.print(" "); Serial.println(Right_PWM);//右電機加速
}
if(val == 'c') {
Right_PWM --; Serial.print(Left_PWM); Serial.print(" "); Serial.println(Right_PWM);//右電機減速
}
}
}
}
4.4、藍牙串口模塊
藍牙串口模塊相對比較簡單,按照給的資料就能使用了,之所以選擇這款藍牙模塊,是因為連接過程中不出任何信息,這樣就不會產生各種干擾你程序的信息了。
095507n326u0nt32znnwf6.jpg (114.96 KB, 下載次數: 228)
下載附件
2016-4-11 15:06 上傳
賣家介紹也很詳細,我這里就不啰嗦了。賣家提供的資料和配置軟件(很好用)。
4 藍牙.zip
(1.38 MB, 下載次數: 14)
2016-4-11 14:15 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
下面給出與Arduino Nano模塊的接線原理圖。
095534nnynsv4baxgx85s3.jpg (126.79 KB, 下載次數: 259)
下載附件
2016-4-11 15:06 上傳
這里要說明的一點是,如果要用Arduino Nano模塊USB的串口,藍牙串口就不能用,二者只能用其一。所以藍牙串口也是用插座的,這樣不用時,就可拔下來。因為這兩者在硬件是用了單片機的同一個串口。
5、材料清單
101157i57n7jz7ygj26ijk.jpg (361.08 KB, 下載次數: 263)
下載附件
2016-4-11 15:06 上傳
超聲自平衡小車材料清單.zip
(10.49 KB, 下載次數: 16)
2016-4-11 14:16 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
這個材料清單不含手動遙控部分,如果簡單的控制,直接用手機就能控制,想做點復雜的控制可以用搖桿+Arduino模塊+藍牙+供電,自制一個兩通道比例遙控器,有需要的,以后再展開討論吧。
4.6、完整原理圖
101809pss3f3hrvw4vlvyl.jpg (237.3 KB, 下載次數: 228)
下載附件
2016-4-11 15:06 上傳
五、結構裝配
自平衡小車的裝配實際上很簡單,但關鍵是小車的結構設計,如果小車的本身結構設計得好,自身就很容易平衡在某個角度,那么自平衡小車的平衡控制效果也就好,如果本身極不容易平衡,那么其控制效果也就要差一截,也就是網上很多人抱怨,在設定的平衡點不能穩定不動的保持平衡,總在晃動或抖動。
新手關心的都是些電路、程序、算法、參數(程序里的參數)之類的東西,小車的結構也有很多參數,為什么就不關心呢?譬如重心、機械平衡點(這個詞我也不知道專業點怎么稱呼,意思是在沒有施加控制的情況下,小車平衡時的位置)。還有就是傳感器安裝的位置,因為傳感器安裝位置不同,它對平衡感知的精確度和靈敏性也不同。
這里先貼上幾張我最新版的藍牙超聲自平衡小車裝配過程中和完成后的幾張照片,供大家參考一下,這也沒有什么設計,只是憑著感覺做的,我這方面的知識幾乎是零,沒有設計能力,但我知道有一些因素是很重要的。網絡上這方面的介紹也很少,希望學機械的同學們在這方面多思考一些,給大家提供一套設計思路和方案。
142320zuh2vu3tvpnxbbbp.jpg (269.1 KB, 下載次數: 234)
下載附件
2016-4-11 15:06 上傳
142344hnnb54brny5yv8h8.jpg (57.87 KB, 下載次數: 253)
下載附件
2016-4-11 15:06 上傳
142417qr9rf01zzx9q85fb.jpg (129.8 KB, 下載次數: 261)
下載附件
2016-4-11 15:06 上傳
142431kb8222p1tpo2wwgq.jpg (93.62 KB, 下載次數: 239)
下載附件
2016-4-11 15:06 上傳
我這個加電的情況下,在某個角度是能勉強短時間內保持平衡的。
下面發兩張群里網友裝配的兩張照片,我不知道他這個平衡情況如何,我問他機械平衡角度大概是多少,他也不知道,有沒有人知道更通俗或更準確的這個術語,我也不知道是不是我表達得不準確,造成別人不理解。
143907vqa8mzg8ojaupazz.jpg (95.13 KB, 下載次數: 257)
下載附件
2016-4-11 15:06 上傳
六、軟件設計
軟件這里直接上程序吧,很多參數值我并沒有給出我調試好的參數,其目的是希望你們不要囫圇吞棗式的干這件事,你們要根據你們自己搭建的小車平臺來確定自己程序的參數。整個程序除了前面的宏定義,不到100行,這些程序你們先看,弄明白了,再去調試。
//利用超聲波測距傳感器實現小車平衡
#define L_max 200
#define L_min 150
#define L_a 0.5
#define filter_init 10
#define L_t 20
byte val = 0x00; //調節與控制命令字
int i, LoopCount = 0; //平衡點調整,PID各調整設定系數
int E_0 = 0, E_1 = 0, PWM_Out, Left_PWM, Right_PWM; //誤差,PWM輸出,左右電機PWM輸出
double Kp = 0.0, Kd = 0.0; //PID系數
double Len_filter = 0, Len_0 = 180; //測距濾波,機械平衡距離
unsigned int TrigPin = 4, EchoPin = 5, Len_Echo = 0; //HC-SR04觸發信號,回波檢測,回波時間
unsigned int M_IN1 = 6, M_IN2 = 7, M_IN3 = 8, M_IN4 = 9; // L298:IN1-IN4
unsigned int M_ENA = 10, M_ENB = 11; // L298:ENA-ENB
unsigned long systime0; //系統時間
//電機輸出
void SetMotorVoltage(int Left_MotorVol, int Right_MotorVol) {
if(Left_MotorVol >= 0) {
digitalWrite(M_IN1, LOW);
digitalWrite(M_IN2, HIGH);
}else {
digitalWrite(M_IN1, HIGH);
digitalWrite(M_IN2, LOW);
Left_MotorVol = -Left_MotorVol;
}
if(Right_MotorVol >= 0) {
digitalWrite(M_IN3, LOW);
digitalWrite(M_IN4, HIGH);
}else {
digitalWrite(M_IN3, HIGH);
digitalWrite(M_IN4, LOW);
Right_MotorVol = -Right_MotorVol;
}
if(Left_MotorVol > 255) Left_MotorVol = 255; //防止PWM值超過255
if(Right_MotorVol > 255) Right_MotorVol = 255; //防止PWM值超過255
analogWrite(M_ENA, Left_MotorVol);
analogWrite(M_ENB, Right_MotorVol);
}
//初始化
void setup() {
Serial.begin(115200);
pinMode(M_ENA, OUTPUT); //電機控制
pinMode(M_IN1, OUTPUT);
pinMode(M_IN2, OUTPUT);
pinMode(M_ENB, OUTPUT);
pinMode(M_IN3, OUTPUT);
pinMode(M_IN4, OUTPUT);
pinMode(EchoPin, INPUT); //超聲波測距
pinMode(TrigPin, OUTPUT);
digitalWrite(TrigPin, LOW);
i = 0;
systime0 = millis();
}
//主循環程序
void loop() {
if(millis() - systime0 >= L_t) {
systime0 = millis();
digitalWrite(TrigPin, HIGH); //發送超聲波測量觸發脈沖
delayMicroseconds(15);
digitalWrite(TrigPin, LOW);
Len_Echo = pulseIn(EchoPin, HIGH); //回波時間測量
if((Len_Echo < L_max) && (Len_Echo > L_min)) {
Len_filter *= L_a; //一階濾波
Len_filter += (1 - L_a) * Len_Echo;
i ++;
if(i > filter_init){
i = 100;
LoopCount ++;
E_0 = Len_0 - Len_filter;
PWM_Out = Kp * E_0 + Kd * (E_0 - E_1);
E_1 = E_0;
Left_PWM = PWM_Out;
Right_PWM = PWM_Out;
SetMotorVoltage(Left_PWM, Right_PWM);
}
}else {
SetMotorVoltage(0, 0); //超出平衡范圍,停止PWM輸出
i = 0; Len_filter = 0;
}
}
//處理串口指令,發送相應數據
if (Serial.available() > 0) {
val = Serial.read();
//參數調節
if(val == 0x01) Kp += 0.01;
if(val == 0x02) Kp -= 0.01;
if(val == 0x03) Kd += 0.01;
if(val == 0x04) Kd -= 0.01;
if(val == 0x05) Len_0 ++;
if(val == 0x06) Len_0 --;
if(val == 0x07) {
Serial.print(Len_0); Serial.print(" ");
Serial.print(Kp); Serial.print(" "); Serial.println(Kd); //查看設置參數
}
if(val == 0x08) {
Serial.print(Len_filter); Serial.print(" "); Serial.println(PWM_Out); //
}
}
}
源代碼下載:
v3.zip
(3.04 KB, 下載次數: 25)
2016-4-11 14:17 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
七、調試
有些人急著等我帖子發完,現在把主要的內容都發上來了,但剩下的卻是最為關鍵的調試,在調試之前你們一定要把前面的東西都消化吸收了,再進行調試。這一部分我先不急著寫,希望跟大家互動著一起來寫,這樣內容才豐富,才有更針對性。
平衡調試完成的,請大家上照片和視頻,做完的,我提供藍牙超聲自平衡小車的遙控版源代碼,這個代碼暫時不在這里給出了。
7.1 接地問題
很多網友在做自平衡車時都遇到各種干擾,無法解決,同樣的原理圖和程序,怎么就不行呢?!用人家現成的電路板沒問題,自己用模塊搭建就不行了。
今天就講講接地問題,網上有現成的,我直接抄過來(http://wenku.baidu.com/link?url= ... a_zHzlfXLHOrvhCXKDm)。
單點接地有兩種類型,一種是串聯單點接地,另一種是并聯單點接地。
串聯單點接地中,許多電路之間有公共阻抗,因此相互之間由公共阻抗耦合產生的干擾十分嚴重。
100747nalmplbtwukm8jo8.jpg (52.12 KB, 下載次數: 246)
下載附件
2016-4-11 15:06 上傳
串聯單點接地的干擾:
A點的電位是:VA = ( I1 + I2 + I3 ) R1
A點的電位是:VB = ( I1 + I2 + I3 ) R1 + ( I2 + I3 ) R2
C點的電位是: VC = ( I1 + I2 + I3 ) R1 + ( I2 + I3 ) R2 + I3 R3 從公式中可以看出,A、B、C各點的電位是受電路工作電流影響的,隨各電路的地線電流而變化。尤其是C點的電位,十分不穩定。
這種接地方式雖然有很大的問題,卻是實際中最常見的,因為它十分簡單。但在大功率和小功率電路混合的系統中,切忌使用,因為大功率電路中的地線電流會影響小功率電路的正常工作。另外,最敏感的電路要放在A點,這點電位是最穩定的。另外,從前面討論的放大器情況知道,功率輸出級要放在A點,前置放大器放在B、C點。
以上是網絡上直接復制的內容,下面說幾句多余的話,沒有動過手的新人,接觸實際的東西很少,這個時代更是如此,從小就在虛擬環境下成長,教育也是如此的一個虛擬環境,初中學習物理時,很多例子、練習題都有一個括號,(……忽略不計),這些忽略的經常有電池內阻、燈泡電阻不變、導線電阻忽略不計以及力學中一些摩擦力忽略不計等等,這些都是嚴重的誤導,導致現在很多大學生畢業工作多少年了,還問燈泡為什么不能串起來接(當然,你串起來接也不會死人的,也出不了什么大事)……
有些人還很固執,你告訴他原因了,他還不信,對于這種人你就自己接著折騰吧!
所以,在此告訴那些使用現成模塊的新人,確實很方便,但整體的(不是模塊單獨本身)電磁兼容方面是有很大隱患的。
回到做自平衡小車上來,電機的啟動以及正反轉的切換都會帶來很強的脈沖干擾(電機線圈的感應電動勢),對于那些高速器件,或者時序要求很嚴的器件來說就是一個很主要的干擾源。
藍牙串口調試助手,怎么使用,自己摸索!!!
藍牙串口 5.4.2.zip
(1.49 MB, 下載次數: 19)
2016-4-11 14:19 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
藍牙串口調試助手的使用與Arduino怎么編程沒有關系,只與你程序用了什么樣的命令有關系,這些命令集就是最簡單的一種通信協議。
八、測試總結
總結這部分,我就寫個說明,這個說明就是希望總結由實踐者們來寫吧!!! |