基于stm32的紅外巡線小車(基礎版)
資料介紹
基于stm32的紅外巡線小車(基礎版)
前兩天做了一個紅外巡線小車,想記錄一下整個過程,也讓自己掌握的更牢固,同時也分享給大家看看。在此要特別感謝實驗室的學長,幫我解決一些問題到晚上一點多,同時幫我優化了控制的邏輯。這個小車比較基礎,主要是分享給新手,同時我自己學的也不是很深入,如果文章有錯的地方,還請多指正。那么話不多說,我們來看制作過程。
- 硬件篇
- 軟件篇
一、硬件篇
1.stmf103c8t6最小系統板
2.l298n電機驅動模塊
將控制電機的4個io口接到L298N的邏輯輸入接口,輸出A和輸出B分別連接兩個電機。12V供電接電源正極,5V供電接單片機5V供電,gnd接電源負極和單片機gnd。
3.兩個紅外傳感器
紅外傳感器有三個接口,一個vcc一個gnd,另一個是返回數據。
4.鋰電池(7.4V~12V)
5.小車底盤(兩個電機)
相關的io口接線在函數中都有配置,在這就不寫了
二、軟件篇
制作紅外巡線小車主要需要紅外傳感器的函數和電機pwm驅動的函數,另外還需要添加正點原子的delay文件和sys文件。
1紅外傳感器
首先我們要明白紅外傳感器的原理,當紅外燈檢測到黑線時返回給io口的值是0,檢測到黑線外(亮光位置)時,返回的值是1。知道了這些,我們就只需要讀取io口的值,就可以判斷小車的巡線情況。
我在頭文件中定義了#define DO1 PAin(1)
#define DO2 PAin(2)
這兩句代碼就是讀取PA1,PA2兩個io口的值,這種定義是基于sys庫函數的,比較方便。
red.c
#include "red.h"
u8 redray1_findblack;
u8 redray2_findblack;
void REDRAY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void REDRAY_Scan(void)
{
if(DO1==0)redray1_findblack=1;
else redray1_findblack=0;
if(DO2==0)redray2_findblack=1;
else redray2_findblack=0;
}
2.電機驅動(pwm)
首先配置電機的io口,然后配置這些io口的pwm。pwm的配置這里就不降講了,可以看一下網上的stm32的基礎教程,這里講一下怎么計算pwm的占空比和頻率:
首先我們看motor.c中的TIM_SetCompare1(TIM4,pwm1);其中pwm1是捕獲比較寄存器值,TIM4_PWM_Init(u16 arr,u16 psc)函數中arr是自動重裝載寄存器周期的值,psc是時鐘頻率除數的預分頻值。
知道了這些我們就可以計算占空比和頻率,
占空比:pwm1/arr100%
頻率:72M / ((arr+1)(psc+1))(單位:Hz)這里主頻是72MHz
motor.c
#include "motor.h"
#include "stm32f10x.h"
void MOTOR_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9; //兩個輸出端
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void TIM4_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
//GPIO_PinRemapConfig(GPIO_Remap_TIM4, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
//初始化TIM4
TIM_TimeBaseStructure.TIM_Period = arr; //設置在下一個更新事件裝入活動的自動重裝載寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //設置用來作為TIMx時鐘頻率除數的預分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設置時鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的參數初始化TIMx的時間基數單位
//初始化TIM4 Channel1 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //選擇定時器模式:TIM脈沖寬度調制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC1Init(TIM4, &TIM_OCInitStructure); //根據T指定的參數初始化外設TIM4 OC1
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC2Init(TIM4, &TIM_OCInitStructure); //根據T指定的參數初始化外設TIM4 OC2
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC3Init(TIM4, &TIM_OCInitStructure); //根據T指定的參數初始化外設TIM4 OC3
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC4Init(TIM4, &TIM_OCInitStructure); //根據T指定的參數初始化外設TIM4 OC4
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable); //使能TIM4在CCR1上的預裝載寄存器
TIM_Cmd(TIM4, ENABLE); //使能TIM4
}
void motor_control(u16 pwm1,u16 pwm2,u16 pwm3,u16 pwm4)
{
TIM_SetCompare1(TIM4,pwm1);
TIM_SetCompare2(TIM4,pwm2);
TIM_SetCompare3(TIM4,pwm3);
TIM_SetCompare4(TIM4,pwm4);
}
3.主函數
main.c
小車行進時大致有4種情況,兩個紅外燈都檢測到光亮(直走或者超出黑線范圍),左光亮右黑線(前方右轉),右光亮左黑線(前方左轉),都是黑線(這種情況一般不會出現)。通過if else就可以將小車的基本邏輯表示出來,但是注意上面提到兩個紅外燈都檢測到光亮還可能是超出黑線范圍,也就是要拐彎時拐不過來,小車沖過了,所以我們還要考慮這種情況。
我們可以設置一個記錄上一次拐彎情況的功能,當超出了黑線范圍,但是記錄了上一刻的轉彎情況,讓小車繼續轉彎,這樣就可以回到黑線上。
#include "sys.h"
#include
#include "red.h"
#include "motor.h"
#include "stm32f10x.h"
#include "delay.h"
extern u8 redray1_findblack;
extern u8 redray2_findblack;
int main(void)
{
u8 stat = 0;
REDRAY_Init();//利用紅外對管來檢測黑線
delay_init(72); //延時函數初始化
TIM4_PWM_Init(1000-1,720-1);
while(1)
{
REDRAY_Scan();
if(redray1_findblack ==1&&redray2_findblack==0)
{
stat = 0;
motor_control(0,0,0,1000);
}
else if(redray1_findblack ==0&&redray2_findblack==1)
{
stat = 1;
motor_control(1000,0,0,0);
}
else if(redray1_findblack ==1&&redray2_findblack==1)
{
if(stat == 0)
{
motor_control(0,0,0,1000);
}
else
{
motor_control(1000,0,0,0);
}
}
else
{
motor_control(1000,0,0,1000);
}
}
}
另外還有delay函數和sys函數,在網上一搜就能收到,我就不寫了。
以上是比較基礎的控制邏輯,如果想要更好的控制,可以考慮一下下面這個圖
如果能實現小車的每一個狀態之間的變換邏輯,那么這個小車就很強大了。
下載地址
基于stm32的紅外巡線小車(基礎版)下載
本月熱點資料
最新資料
下載排行
本周
- STM32F407+ESP8266+SD卡進行遠程固件升級
- 單片機高級系列丨超聲波測距(數碼管顯示)
- STM32學習筆記(超詳細整理144個問題)--轉
- SSD1306 OLED驅動芯片 詳細介紹
- Arm Cortex-M4 MCU 以高速數據處理為目標
- PHILIPS>飛利浦>HX9352>電動牙刷>拆解+維修記錄
- 自動化專業大學生可以參加哪些競賽?
- 樹莓派有史以來首次漲價
- 不學51直接學stm32可以嗎?學stm32需要哪些基礎?
- 基于STM32的藍牙HC05調試程序 通過手機控制STM32單片機程序
本月
- 51單片機之邏輯運算指令ANL、ORL、XRL等
- macOS搭建51單片機開發環境
- 51單片機的定時器中斷(數碼管讀秒+LED閃爍)
- 第十二屆藍橋杯單片機省賽題目解析
- 基于51單片機的電子時鐘
- 單片機中斷問題30例及解決辦法
- VScode開發51單片機程序
- 51單片機的前世今世
- 單片機實驗:節日彩燈控制器
- 基于51單片機的LED呼吸燈設計(定時器)
用戶評論
查看全部 條評論
發表評論請先 登錄, 還沒有賬號?免費注冊。
發表評論