基於STM32微控制器的簡單紅外循跡的實現
此次紅外循跡是我在做畢設過程無意中實現的,所有有些地方不夠精確完美,還請各位友友們多多指點校正。這篇部落格也是小弟第一篇部落格,
小弟不才,文筆不怎麼行,可能有些語句不太通順的地方,只能讓各位將就一下了。那麼接下來就進入正題吧。
一、硬體選擇
①首先我們需要一個微控制器開發板,在這裡我使用的是STM32F103RCT6型號的微控制器,這個大家也可以自己買其他的型別;②然後就是電機和電機
驅動模組,市面上的電機有很多種,有帶編碼器的,也有不帶編碼器的,由於此次循跡只是簡單的巡線操作,所以我用的是不帶編碼器的直流減速
電機,大部分的小車其實都夠用了,而驅動模組選的是L298N模組,這個應該大家還是比較熟悉吧,後續我也會詳細介紹的;③
你可以選擇分開給驅動模組和微控制器單獨供電,也可以用一個電源就行了,我在這裡用的兩節18650的鋰電池給驅動模組供電,然後用了一個移動
電源給微控制器供電;④循跡模組我用的是紅外感測器,這個其實也有很多型別的,有數字訊號的,也有模擬訊號的,我用的是簡單的輸出數字訊號
的TCRT5000感測器,這個在某寶上也便宜,大家可以根據自己需要自行選擇。這差不多就是全部硬體了,後面我會分享給大家如何去實現紅外循跡
的具體實現過程。
二、循跡原理介紹
其實紅外循跡還是比較簡單的,當然這裡我指的是我自己實現的功能,本次循跡我只用了兩路循跡模組,所以你們在視訊中看到的循跡效果可能不是
很穩定,但是至少還是沒有出現什麼意外,小車成功的在軌道上跑動起來了。紅外感測器的工作原理是這樣的,它上面有兩個管子,一個發射管,用
來向外發射紅外線,還有一個接收管,用來接收反射回來的紅外線,這個TCRT5000的有效範圍好像只有8mm到30mm,根據它的檢測距離以及它對不同
顏色的感應程度,就可以判斷地面上的軌跡了;如果地面上是黑色,由於紅外線會被黑色吸收,導致發出的光不能被反射回來,接收管就收不到訊號,
它的數字輸出引腳D0就會變為高電平,並且模組上的訊號燈也處於熄滅狀態,這個時候我們就知道小車已經到黑線上了,就可以讓小車轉彎;而當地
面上是白色的時候,紅外線發出後會被反射回來,接收到反射訊號後,模組的數字輸出訊號就會變為低電平,這個時候模組上的訊號燈就會亮起來,
我們就讓小車直走就行了。這就是紅外循跡的整個原理,還是容易理解的,至於具體接線情況,我在這裡就不多囉嗦了,相信大家對微控制器和模組的
接線還是可以做到的,下面我們就可以進行程式的編寫了。
三、循跡程式介紹
我在這裡就直接給你們上循跡的程式吧,裡面有註釋應該也差不多看得明白,我把電機轉動程式也放在下面了,方便有些同學們可以更好的理解。
哦,對了,我用的是STM32庫函式版本寫的程式,如果有用51微控制器或者想用暫存器進行程式設計的朋友們也可以把相關思路轉換一下就行了。
①/***循跡模組初始化程式***/
GPIO_InitTypeDef initstruct; //這是定義一個GPIO的結構體,用於儲存循跡模組的引腳資訊
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE); //開啟GPIO的時鐘,這一步很關鍵,可以理解為一個開關
initstruct.GPIO_Pin = GPIO_Pin_0; //這裡我用到的是PB0引腳,你們可以對照自己的引腳改一下
initstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; //一般情況下接收引腳的訊號選擇浮空輸入模式就行了,你們也可以試著用上拉或者下拉模式
GPIO_Init(GPIOB,&initstruct); //這是對剛才你天的資訊進行初始化儲存的一個函式
initstruct.GPIO_Pin = GPIO_Pin_7; //同理
initstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; //同理
GPIO_Init(GPIOA,&initstruct); //同理
②/***小車開始循跡的程式***/
#define XJLEFT GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) //這兩個是我在標頭檔案裡面的巨集定義,其實也可以不用只有寫,我只是為了後面方便管理
#define XJRIGHT GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7)
XJleft = XJLEFT; //這是我定義的兩個變數,用來記錄循跡模組輸出引腳上的電平值
XJright = XJRIGHT;
if((XJleft==0) && (XJright==0)) //這種情況就是小車兩個循跡模組都沒有檢測到黑線,所以我讓小車直走
car_go(60);
if((XJleft==0) && (XJright==1)) //這種情況是右邊循跡模組感應到黑線,也就是要向右邊拐彎了
{
car_right_two(80); //這其實就是一個向右轉彎的函式,你們可以根據自己的情況來寫
delay_ms(70); //我在這裡加一點延時,是因為我之前測試的時候小車有點卡頓的感覺,加點延時就會好一些
if((XJleft==0) && (XJright==0)) //這裡再巢狀一個 if 判斷,是為了讓小車迴轉過後可以繼續向前跑,讓它更穩定一點,也是為了防止小車亂晃
car_go(60);
}
if((XJleft==1) && (XJright==0)) //這個情況是左邊的循跡模組感應到黑線,也就是要向左邊拐彎了
{
car_left_two(80); //後面的其實和上面原理差不多
delay_ms(70);
if((XJleft==0) && (XJright==0))
car_go(60);
}
if((XJleft==1) && (XJright==1)) //這種情況是左右兩個循跡模組都感應到黑線,不過這個沒有運用到巡線操作中,是我用來把小車拿起來讓它停止的
car_stop();
這下面就是小車電機轉動的程式了,我就把PWM控制電機速度的部分拿來了,具體的原理就不再介紹了,大家對著程式參考一下應該也能理解,
其實就是一些固定的格式於步驟。
③/***電機PWM初始化程式***/
TIM_TimeBaseInitTypeDef time4initstruct; //這和前面GPIO的一樣,也是定義一個結構體,用來儲存定時器的資訊
TIM_OCInitTypeDef ocinitstruct; //定義一個結構體,用來儲存定時器通道的資訊
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); //開啟定時器時鐘 (其實開啟時鐘就是一個開關,因為微控制器設定了預設把裝置關掉來節省電源
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //開啟GPIO的時鐘 所以如果我們要使用定時器,GPIO埠或者像串列埠等一些其他的外設的時候
//就要先把這個時鐘開關開啟,這樣裝置才能正常工作)
time4initstruct.TIM_Period = 200; //這裡可能你們有疑惑,其實這個是設定定時器的重灌載值
time4initstruct.TIM_Prescaler = 7200-1; //這裡是設定定時器的預分頻係數
//以上兩個引數聯合起來使用,是用來設定定時器的計時週期的,比如重灌載值我設定為200,預分頻係數我設定為7200,至於為什麼
//這裡要減一,可以百度搜索一下,我在這就不過多贅述了;由於STM32微控制器的時鐘頻率是72MHz,分頻係數為7200,那麼分頻後,
//時鐘頻率就是10KHz,那麼計時一個數的時間就是10KHz分之1秒,也就是十分之一毫秒,而重灌載值我設定的是200,那麼整個定時
//的週期就是20ms,整個定時器頻率就是50Hz,至於為什麼我要設定為50Hz,因為網上說的好像是PWM波控制電機差不多要這個頻率
time4initstruct.TIM_CounterMode = TIM_CounterMode_Up; //這裡是配置計數模式,有向上模式,向下模式,向上向下模式,這裡我選擇向上計數
time4initstruct.TIM_ClockDivision = TIM_CKD_DIV1; //這裡是設定時鐘分頻因子,這個引數我沒怎麼用過,這裡設定為不分頻就行了
TIM_TimeBaseInit(TIM4,&time4initstruct); //然後把配置好的資訊進行初始化儲存
ocinitstruct.TIM_OCMode = TIM_OCMode_PWM1; //這裡是配置定時器通道的模式,即PWM波產生模式,一般有PWM1、PWM2兩種,這裡我選擇PWM1,兩種
//模式具體什麼含義可以自行百度搜一下
ocinitstruct.TIM_OCPolarity = TIM_OCPolarity_High; //這是設定通道的有效電平極性,這裡設定為高電平有效
ocinitstruct.TIM_OutputState = TIM_OutputState_Enable; //這是一個使能開關,即開啟通道使能,讓其可以產生PWM波
TIM_OC3Init(TIM4,&ocinitstruct); //把配置好的資訊進行初始化儲存
TIM_OC4Init(TIM4,&ocinitstruct); //同理
TIM_Cmd(TIM4,ENABLE); //使能定時器,讓其開始工作
TIM_OC3PreloadConfig(TIM4,TIM_OCPreload_Enable); //至於這後面的三個函式是開啟定時器和通道上的預裝載使能位,說白了就是讓定時器可以重新載入計時
TIM_OC4PreloadConfig(TIM4,TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM4,ENABLE);
④/***電機速度控制程式***/
這裡我只列出一個小車前進的程式,至於小車後退,轉彎原理是一樣的,大家可以參照根據自己情況進行修改
GPIO_ResetBits(GPIOB,GPIO_Pin_7); //給左邊電機一個低電平,左邊電機正轉 相反,給它高電平就反轉
GPIO_ResetBits(GPIOA,GPIO_Pin_4); //給右邊電機一個低電平,右邊電機正轉
TIM_SetCompare3(TIM4,100); //設定左邊電機的速度,這裡的數值100要與前面定時器那裡的重灌載值要對應上,速度值為0到200範圍內,數值越大,電機轉動越快
TIM_SetCompare4(TIM4,100);
好了,以上就是本偏部落格的所有內容了,由於本人初次接觸STM32,加上第一次寫部落格沒有太多經驗,還有不好的地方望各位夥伴們指點校正,
以後我也會將更多的好玩有意義的內容分享給大家的,希望小夥伴們喜歡(❤ ω ❤)