基於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,加上第一次寫博客沒有太多經驗,還有不好的地方望各位伙伴們指點校正,

以后我也會將更多的好玩有意義的內容分享給大家的,希望小伙伴們喜歡([表情] ω [表情])

最后小車循跡的視頻點擊下方鏈接即可觀看:

https://www.bilibili.com/video/BV1h34y1x7AR?spm_id_from=333.999.0.0

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM