基於51微控制器的藍芽控制小車的簡單實現(有原始碼,無圖) (上篇)

lipeng08發表於2018-01-06

1. 簡介

這是2016年底兩週時間做的一個藍芽小車,它分為上下兩篇,本文是上篇。原本是發在了http://bbs.elecfans.com/ 的,不過由於我的部落格都在CSDN上,因此我就把它們重新複製到這裡來了。

1.1 相關的部落格和程式碼

原文地址
原始碼地址
小車手機端程式碼 — 下篇部落格,此為後續版本,實現了手機端的藍芽程式控制小車運動以及接收小車狀態並展示。

1.2 想法來源

最初的想法是做一個紅外遙控的裝置,連結地址。只需要前進和停止,二路遙控,想使用類比電路搭建,但最後也沒能完成,這個想法依然在,現在只能留帶以後是否有想法再做了。

第二個想法是想做一個小車,小車的功能如下: 前進,後退,轉彎,遙控控制,自主智慧運轉。 上某寶買了一個小車的底座(4驅動的,帶電機), 買了兩個L298N驅動模組用來驅動小車,買了藍芽模組(HC05)用來充當遙控。

2. 實踐篇

2.1 電路焊接

首先根據51微控制器的最小系統的電路圖,焊接了一個最小系統板,使用的STC89c52的微控制器(晶振6Mhz,帶復位電路,復位指示燈顯示),為了便於測試,又焊接了一個發光二極體連線一個I/O口,用於測試最小系統。

2.2 最小系統測試

開始測試最小系統,不過我很多年沒有用過keil和下載器了,就上網尋找了一下關於這方面的帖子,並作了總結。要測試最小系統,首先需要編譯程式碼的工具(我用的keil),下載程式碼到微控制器的工具(stc-isp),usb轉ttl硬體裝置(某寶上2塊多錢買的),串列埠除錯助手(使用的是微控制器多功能除錯助手PortHelper.exe),於是從網上下載了keil4破解版本,stc-isp下載軟體,微控制器多功能除錯助手三個軟體。

注意:
下面的步驟2.2.1和2.2.2是用於測試USB轉TTL裝置,而2.2.3-2.2.5是用於單純的最小系統測試。那為何需要用USB轉TTL裝置呢?在解釋之前,先介紹我們的小車總體控制路徑:

空氣
手機端按下方向按鈕
手機傳送命令到手機藍芽
微控制器串列埠藍芽裝置
從藍芽串列埠讀取
微控制器串列埠
微控制器處理程式接收到串列埠命令
微控制器處理命令

可以看出,上述的路徑無需USB轉TTL的參與,我們之所以要使用USB轉TTL是出於測試藍芽的需要。考慮一種情況:藍芽和微控制器的串列埠連線之後,若微控制器的控制程式無法驅動藍芽正常工作,我們將無法判斷是微控制器方面的問題(例如程式碼或者連線等),還是藍芽本身的問題。 因此,為了儘可能隔離錯誤域,我們可使用這個神奇的USB轉TTL裝置,使其直連藍芽模組,並使用電腦的串列埠除錯助手,驅動USB轉TTL,進而驅動藍芽模組,從而可確定藍芽模組的好壞。其測試流程:

USB口連線
導線相連線
電腦
串列埠除錯助手
USB轉TTL
藍芽串列埠模組

不過要使用以上的方案,我們首先要測試USB轉TTL模組是不是好的,好繞口。

2.2.1 USB轉TTL裝置連線電腦端是否可識別

測試usb轉ttl是否可用(就44個引腳,5VGNDTXRX)
開啟串列埠除錯助手,設定波特率,開啟,發現開啟失敗,比較鬱悶,為何呢? 極有可能是串列埠號不對,於是開啟我的電腦-》管理-》裝置管理器,找到串列埠的條目,檢視它的串列埠號,我的串列埠號竟然是12,在串列埠除錯助手中壓根沒有1212。於是電腦給裝置重新設定串列埠號,重新開啟,OK。 如何測試usb轉ttl呢? 我的想法是如果傳送資料的話,對應的tx引腳應該有訊號,如果將TX和RX連線到一起,那麼傳送出去的應該自己可以接收到。我沒有示波器,就簡單的使用萬用表量它的TX引腳的電壓,點選傳送按鈕,發現TX引腳的電壓有波動即可。

2.2.2 USB轉TTL與微控制器連線

將usb轉ttl的四個引腳接入到微控制器的對應引腳即可(其實就是VCC接VCC,GND接GND,TX接RX,RX接TX)。沒有采用外部供電,直接利用usb轉ttl進行的5v供電

2.2.3 在keil中寫程式碼,對微控制器的某一個I/O進行翻轉電平的操作

程式碼如下

sbit LED=P0^0;
while(1){
    LED = !LED
    Delay10ms(100);
}

2.2.4 編譯程式,生成HEX檔案

使用keil建立相應的51工程,加入上述程式碼以及標頭檔案,並對程式進行編譯,生成相應的hex檔案。

2.2.5 燒錄程式

開啟stc-isp下載工具,選擇微控制器型號,hex程式位置,點選下載即可,如果識別了微控制器的話,會出現給MCU重新上電的字樣,這個時候只需要關閉再開啟MCU的電源開關即可,就會出現燒寫程式的過程。

2.2.6 用萬用表量P0^0口

檢視電壓是否1秒一次變化即可

2.3 最小系統測試篇遇到的問題,回憶篇

51微控制器的電源供電問題,忘了接微控制器的VCC引腳了(如果是這方面的問題,就檢查幾個關鍵地方,vcc和地接好了嗎,tx和rx接好了嗎,晶振接好了嗎,復位電路先不用管,我是使用的萬用表一個個的量的)
晶振的電路沒焊好(萬用表搞定)
usb轉ttl找不到串列埠(軟體問題的話,容易解決,也有可能是usb轉ttl硬體有問題,驅動沒有安裝成功,導致識別不了硬體)

3. 藍芽模組工作篇

從某寶上花了17大洋買了一個HC05藍芽主從模組,有6個引腳(VCC,GND,TX,RX,AT,STATUS),前4個引腳與usb轉ttl的接法相同(注意RX,TX交叉接線接入到微控制器),AT和STatus引腳是我自己命的名字。 AT引腳高電平有效,用於藍芽模組進入AT狀態(所謂AT狀態,即是其他程式可以通過它的引腳向藍芽模組傳送AT控制命令,例如設定波特率,檢視版本號,設定主從模式),AT引腳懸空預設為低電平。Status引腳用於顯示配對的狀態(配對成功輸出高電平,未配對輸出低電平)

3.1 藍芽模組測試篇

第一步:藍芽模組既然包含串列埠,那麼它應該可以跟usb轉ttl直接連線,使用電腦向藍芽模組傳送命令。於是連線藍芽模組與usb轉ttl的對應引腳。
第二步:將AT引腳懸空,使用手機搜尋周圍的藍芽裝置,發現有HC05的藍芽(因為這個藍芽模組預設是從模組,可以被收到)
第三步:將AT引腳拉高電平,使其進入AT狀態(按照文件描述,如果上電之後再置位AT,指示燈無變化,依舊是,如果上電之前拉高AT,指示燈轉為1秒一次),然後通過電腦串列埠傳送AT+VERSION?(注意需要換行)檢視版本號,使用AT+UART?檢視波特率(預設9600,不帶校驗)
此文件有用: ATK-HC05-V11使用者手冊_V1.0.pdf (請自行搜尋)
第四步:實驗了一下,我的模組有問題,就是上電之前拉高AT,模組不接受AT命令,只有上電後拉高AT才有用,不過不影響使用。
第五步:將藍芽模組和usb轉ttl連線後,AT保持懸空,即藍芽模組為從模組,手機安裝藍芽串列埠助手,開啟手機藍芽,然後搜尋HC05,配對,然後開啟手機端的藍芽串列埠助手軟體,向HC05傳送訊息,如果藍芽模組工作正常,那麼電腦端的串列埠除錯助手應該收到手機傳送的訊息。同樣的也可以通過電腦端傳送訊息,到手機端。

訊息傳遞流程如下:
手機端藍芽串列埠助手 -> 手機藍芽 ->空氣 -> HC05藍芽模組 -> USB轉ttl模組 -> 電腦的串列埠除錯助手,反過來也是可行的(注意線路連線方式都是RX與TX交叉連線)

3.2 藍芽模組與微控制器整合除錯篇

上面的測試已經證明了藍芽模組是可以傳送接收手機端訊息的,現在開始將藍芽模組與微控制器的TX,RX介面連線起來,通過程式控制藍芽模組與手機藍芽進行溝通,從而達到利用手機藍芽進行遙控的目的。

main函式如下,主要設定串列埠波特率,以及開啟串列埠中斷

//PCON:SMOD位預設為0,序列口波特率加倍位
PCON = 0x80;                //SMOD=1;

TMOD=0x20;          //8位自動載入計數器
//TH1=0xfd;  TL1=0xfd;   for 11.0592MHZ and SMOD=0, 
TH1 = 0xf3;//2400bps
TL1 = 0xf3;
TR1=1;    // T1
//SCON: 0x50=SM0=0, SM1=1,REN=1
REN=1;   
SM0=0;
SM1=1; //串列埠
EA=1; //中斷
ES=1; 

串列埠中斷函式
void serial() interrupt 4
{
         char sbuf;
         sbuf=SBUF;
         switch (sbuf)
         {
                 case 'f': direc=4; break;
                 case 'b': direc=5; break;
                 case 'l': direc=6; break;
                 case 'r': direc=7; break;
                 case 's': direc=-1; break;
                 default : LED = !LED; //LED為一個I/O引腳,控制發光二極體
         }
         RI=0;
} 

3.3 遇到的問題:

利用手機給藍芽HC05傳送訊息,如果不是switch中的幾個case的話,那麼LED燈會明暗變化,但是剛開始的測試卻始終不如意。而後仔細檢視了程式碼,並沒有發現什麼錯誤,後來懷疑是波特率的問題,因為我的晶振是6Mhz的,藍芽模組的波特率是96009600

採用波特率倍頻,我手動計算了一下: 610000002/12/32/9600=3.2556*1000000*2 / 12 / 32 / 9600 = 3.255若對其取整為33. 然後使用3反代入到此式子中,我們有
610000002/12/32/3=10416.7 6*1000000*2 / 12 / 32 /3 = 10416.7 它與96009600的波特率相差14001400多,這個似乎差距太大了。我又嘗試了其他幾個引數,像48004800, 1920019200, 3840038400都相差挺大的,估計就是這個原因。於是繼續嘗試,發現24002400的話,相差不多。
610000002/12/32/2400=13.026*1000000*2/12/32/2400 = 13.02 ,然後使用1313代入進去,其波特率結果為2403.82403.8,與24002400的波特率相差很小,估計是可以用的,但是看藍芽模組的文件,發現它說不支援24002400的,我不甘心,就使用usb轉ttl模組(有沒有發現此模組是不是很有用?)設定了一下24002400,沒想到AT命令還真的返回OK了,微控制器程式也可以正常工作了。

4. 小車驅動篇

將兩個L298N模組與微控制器的P2口直接相連(小車4輪驅動,每個電機需要兩個輸入引腳,以及一個使能引腳,那就是12個引腳,我剛開始並不想支援調速的功能,因此使能引腳直接高電平了,就連線了8個I/O口)。注意L298N的GND引腳一定要和微控制器的GND共地。

關於L298N: 它的EN引腳用於使能,EN為高電平,才使能。另外兩個輸入引腳IN1,IN2根據電平的組合變化會有4種情況(00,10,01,11),電機相應的在00和11停止(這個停止是帶電的,類似於鎖死的感覺),在10正轉,01反轉。可以直接使用微控制器的VCC和GND連線L298N的IN1和IN2,同時將EN端接VCC,看電機轉不轉就可以測試L298N模組了。

編寫程式,控制輪子的正轉,翻轉,停止等。基本上就是以下的這種程式碼

void wheelForward(uchar which)
{
        switch(which)
        {
                case 1:
                {        
                        wheel_1_1 = 0;
                        wheel_1_2 = 1;
                        break;
                }
                case 2:
                {
                        wheel_2_1 = 0;
                        wheel_2_2 = 1;
                        break;
                }
                case 3:
                {
                        wheel_3_1 = 0;
                        wheel_3_2 = 1;
                        break;                
                }
                case 4:
                {
                        wheel_4_1 = 0;
                        wheel_4_2 = 1;
                        break;
                }
        }
}

4.2 遇到的問題

問題1: 剛開始L298N直接連線P0口,死活不轉,而直接引出高低電平到某一個電機的IN1,IN2口,電機正常運轉。於是猜測是I/O有問題,使用萬用表測量,發現P0的I/O在輸出高電平的時候,根本不是高電平,而後發了帖子,詢問了一下才知道P0口在高電平是呈現高阻態的,需要外部焊接電路加上拉電阻才可工作。我不想焊接過多的電路,就將其I/O換到P2口,可以正常工作,帖子連結地址

問題2: 我使用的是路由器的9v直流電源,使用其帶動兩個L298N,同時將L298N的輸出的一個5V高電平接到微控制器上給微控制器供電,啟動4輪驅動,電機只會翁的一聲,然後啥也沒有,二輪驅動也不轉。 上網檢視了不少資料,基本上都是電源功率過低,需要將微控制器與L298N分別供電才可以。 於是使用筆記本的usb口給微控制器供電,使用9v直流電源給電機供電,比剛才好了一些,兩輪可以轉,但是4個輪子還是轉不了。沒辦法,想到自己有一個小的卡片相機,有鎳氫電池8節,然後上網買了一個電池盒,裝上去,電機轉的吼吼叫,同時L298N給微控制器供電也沒問題。

問題3:關於L298N同時給微控制器供電的問題,大家可以在啟動輪子轉動的時候量一量微控制器的電源電壓,會發現在電機啟動的一剎那,微控制器的電壓有一個瞬時的拉低,這樣微控制器就會復位了。

5. 藍芽遙控小車彙總篇

第一步:部署小車,L298N,鎳氫電池盒,藍芽模組組裝到一起
第二步:編寫程式碼,本來可以使用EN口進行調速控制的,但是考慮到還需要使用額外的I/O口,就先不打算做了。

程式碼完成的功能:

小車前進,後退,停止,左轉,右轉
小車單個輪子的轉動(用於測試)
小車當前狀態的獲取(用於後期給小車增加其他模組的時候,例如溫度模組,就可以讀取溫度了)
小車命令幫助

程式碼思路:

首先完成單個輪子的控制
再完成小車的控制
再加入串列埠接收中斷,收到不同命令,設定方向變數
main程式讀取方向變數控制不同的方向

6. 思路篇

一些比較有特點的思路:
思路1:一個棘手的問題想實現這樣的功能: 使用者按鍵,小車才走,使用者鬆開按鍵,小車停止。
我的想法如下: 小車使用一個定時器T0,控制定時器的延時時間為100ms,使用者每傳送一個前進訊號,小車會前進100ms,但是這100ms內小車還需要能夠響應外部的命令。例如如果使用者在t=0ms傳送前進命令,然後在t=50ms傳送左轉命令,小車能夠立刻左轉,而不是繼續前進100ms,然後才執行左轉的命令。基本的程式碼思路是使用者的每一個命令,都會重置timer0,timer0的超時中斷函式會將小車停止。這樣使用者只要以連續的小於100ms間隔傳送前進命令,小車就會一直前進,也就是說timer0的中斷沒有執行,如果使用者間隔100ms還沒有傳送命令,那麼小車停止。 當前我使用的藍芽串列埠助手它的按鍵不支援連續傳送,只能按下鬆開手,才會傳送訊息,這樣我現在就把時間間隔設定為1000ms,使用者只要以小於1000ms的間隔連續按鍵,小車就會一直前進,如果不按鍵,小車會繼續前進1000ms才會停止。 後期打算找到藍芽串列埠除錯助手的原始碼,修改它的原始碼,設定成如果使用者按下不丟,小車前進命令能夠一直髮送。

思路2: 既然有了手機藍芽,那麼小車再想展示一些狀態資訊,就沒必要使用像1602,12864之類的東東了,直接定時發給手機藍芽模組就OK了。我現在並沒有實現定時傳送,不過支援了命令獲取的功能。 當使用者傳送命令h到微控制器,微控制器會返回一個幫助介面,告知如何控制小車,例如"f"控制小車前進,"b"控制小車後退,當使用者傳送命令i到微控制器,微控制器會返回小車的一些狀態資訊,我當前只返回了一些簡單的變數狀態(後面想加入距離,溫度,光敏都是可行的)。

思路3:有了藍芽,這個小車就可以被我們隨心所欲的控制了。你既可以推命令到微控制器,控制它,你又可以把微控制器內部的當前狀態拉出來。微控制器本身又可以定期將它的狀態向你的手機進行推送。這個我感覺還是很好玩的,有了這個程式碼的基本框架,後面有可能的話像實現一個小車的擴充套件功能,加上紅外對管讓它不撞牆,加上超聲波讓它測距,加上麥克風讓它向著聲音跑,加上人體感應讓它做一個跟屁蟲,甚至於加上一個智慧化點的程式,讓它能夠在一個屋子裡隨便的轉悠,然後記錄屋裡的情況。還想做的是加入一個wifi模組,能將它的狀態資訊上傳到路由器裡面(手裡有一個壞的路由器華為hg255d,正在修理中,還沒有摸清楚如何修),這樣遠在千里之外都可以訪問小車上面感測器的情況了。還想加的是一個攝像頭模組,不過微控制器的處理能力有限,攝像頭的解碼對它是個大問題,估計很難辦到(手頭有優龍fs2401開發板,剛修好它的電源模組,正在研究中,不過前天它突然bios引導不起來了,也不知道是什麼問題,關於這種arm的東西,還沒有接觸過,完全不懂刷bios,uboot等等的東西,看情況是要重新刷bios了)。

後記:
修改於2018年12月24日午飯後。此部落格原本是直接從電子愛好者中把自己寫過的內容貼上過來,也沒使用markdown,文章內容顯得很亂,今天突然看到了,就花了會簡單調整一下,希望能給大家一些更好的閱讀體驗。

相關文章