2025年5月25日 星期日 乙巳(蛇)年 二月廿七 设为首页 加入收藏
rss
您当前的位置:首页 > 电子 > 单片机

基于stm32单片机的红外遥控超声波避障小车(含附件)

时间:03-14来源:作者:点击数:61

简述

19年11月到12月,和同学一起在学校参加院电子设计大赛做的项目,看起来时间很长,但实际上我们拢共做的时间差不多是3天的样子。我在寒假,因为新型肺炎的原因,没有出门,就顺便捋捋这段经历。

板子是正点的,所以很多地方我们就直接扒的正点的例程,比如红外遥控的部分完整拿过来了,能直接用。

原本学校给的要求是

在这里插入图片描述
在这里插入图片描述

我们在做的时候又多加了测距显示和差速调节(让小车可以从完全停止到最高速度),后面我会分块尽量详细叙述小车的功能原理及代码介绍。

小车成果展示

小车正面

小车正面

在这里插入图片描述

小车侧面

在这里插入图片描述

小车背面

在这里插入图片描述

小车测距展示

视频演示

https://www.bilibili.com/video/av85501350/

电源

我们采用的是三节18650供电,三节电池就有12v,用来驱动小车绰绰有余,为了获得更稳定符合小车需求的电压,我们又采用了一个LM2596S降压模块,把12V的电压给降到3v给单片机供电。

在这里插入图片描述

在安装电源的时候,其实我们犯了一个错误,把电池给安装在了小车的第二层,这样在取放电池时就需要拆卸螺丝,比较麻烦。

驱动

驱动模块使用的是经典的L298N,主要是实验室一抓一大把,关于模块的详细说明可以搜索得到,不再赘述。

我们对于这个模块具体的使用如图

在这里插入图片描述

我们做的是4轮驱动,把轮子分左右用一个驱动模块进行驱动,为了用PWM对小车进行速度控制,所以我们需要调用时钟,这里调用TIM4,使能PB8对左电机进行方向控制,使能PB9作为左电机的PWM信号,使能PA6对右电机进行方向控制,使能PB10作为右电机的PWM信号。

一边有俩电机对应俩轮子,所以,这里还进行了映射,PB8映射到PB5和PB6,对应左边的in1和in2,进行方向控制。

PA6映射到PA5和PA6,对应左边的in3和in4,进行方向控制。

更多具体的配置都在函数里面。

驱动部分并不是由我完全负责,所以我会在大体完成后找机会请当时一起完成的小伙伴一起校验。

在驱动部分,我想再主要挑一部分详细谈谈。

当时我们在对于进行差速控制部分有一个想法,让它实现从零开始逐步加速或者最高速逐步减速,同时也完成要求的三挡速度。

对于要求的三挡速度,其他选了小车的组,据我观察,应该都是在函数里面写好了预先配置3个的PWM占空比,来实现。

当时是我负责的这个功能的实现,我觉得这样写只能单一完成那个要求,然后为了达成我们预想的差速调节,于是我在主函数设置一个变量来代表占空比,然后motor.c里面引进并在后面的调速函数和三挡预置速度函数调用,就能够实现这两个功能了。里面更改占空比的数值是我们测试调节修改出来的。

  • void speedchange(signed char flag)
  • {
  • if(flag==1)
  • {
  • i=2000;
  • TIM_SetCompare2(TIM4,i);
  • TIM_SetCompare4(TIM4,i);
  • }else if(flag==2)
  • {
  • i=1000;
  • TIM_SetCompare2(TIM4,i);
  • TIM_SetCompare4(TIM4,i);
  • }else if(flag==3)
  • {
  • i=1;
  • TIM_SetCompare2(TIM4,i);
  • TIM_SetCompare4(TIM4,i);
  • }
  • }
  • void speeddown(void)
  • {
  • i+=100;
  • TIM_SetCompare2(TIM4,i);
  • TIM_SetCompare4(TIM4,i);
  • }
  • void speedup(void)
  • {
  • if(1)
  • {
  • i-=100;
  • TIM_SetCompare2(TIM4,i);
  • TIM_SetCompare4(TIM4,i);
  • while(i<=0)
  • {
  • i=1;
  • break;
  • }
  • }

在控制方向上,我们有旋转和有一定精度的角度的旋转。功能完成也是依靠调节占空比,不再赘述。

下面是驱动的motor.h代码。

moto.h

  • #ifndef __MOTOR_H_
  • #define __MOTOR_H_
  • #include "stm32f10x.h"
  • void TIM4_PWM_Init(unsigned short arr,unsigned short psc);
  • //电机驱动IO定义
  • /*
  • LEFT_MOTOR_GO PB8 左电机方向控制
  • LEFT_MOTOR_PWM PB9 左电机PWM
  • RIGHT_MOTOR_GO PA6 右电机方向控制
  • RIGHT_MOTOR_PWM PB10 右电机电机PWM
  • */
  • #define LEFT_MOTOR_GOin1 GPIO_Pin_5
  • #define LEFT_MOTOR_GOin1_GPIO GPIOB
  • #define LEFT_MOTOR_GOin1_SET GPIO_SetBits(LEFT_MOTOR_GOin1_GPIO,LEFT_MOTOR_GOin1)
  • #define LEFT_MOTOR_GOin1_RESET GPIO_ResetBits(LEFT_MOTOR_GOin1_GPIO,LEFT_MOTOR_GOin1)
  • #define LEFT_MOTOR_GOin2 GPIO_Pin_6
  • #define LEFT_MOTOR_GOin2_GPIO GPIOB
  • #define LEFT_MOTOR_GOin2_SET GPIO_SetBits(LEFT_MOTOR_GOin2_GPIO,LEFT_MOTOR_GOin2)
  • #define LEFT_MOTOR_GOin2_RESET GPIO_ResetBits(LEFT_MOTOR_GOin2_GPIO,LEFT_MOTOR_GOin2)
  • #define LEFT_MOTOR_PWM GPIO_Pin_7
  • #define LEFT_MOTOR_PWM_GPIO GPIOB
  • #define LEFT_MOTOR_PWM_SET GPIO_SetBits(LEFT_MOTOR_PWM_GPIO,LEFT_MOTOR_PWM)
  • #define LEFT_MOTOR_PWM_RESET GPIO_ResetBits(LEFT_MOTOR_PWM_GPIO,LEFT_MOTOR_PWM)
  • #define RIGHT_MOTOR_GOin3 GPIO_Pin_4
  • #define RIGHT_MOTOR_GOin3_GPIO GPIOA
  • #define RIGHT_MOTOR_GOin3_SET GPIO_SetBits(RIGHT_MOTOR_GOin3_GPIO,RIGHT_MOTOR_GOin3)
  • #define RIGHT_MOTOR_GOin3_RESET GPIO_ResetBits(RIGHT_MOTOR_GOin3_GPIO,RIGHT_MOTOR_GOin3)
  • #define RIGHT_MOTOR_GOin4 GPIO_Pin_5
  • #define RIGHT_MOTOR_GOin4_GPIO GPIOA
  • #define RIGHT_MOTOR_GOin4_SET GPIO_SetBits(RIGHT_MOTOR_GOin4_GPIO,RIGHT_MOTOR_GOin4)
  • #define RIGHT_MOTOR_GOin4_RESET GPIO_ResetBits(RIGHT_MOTOR_GOin4_GPIO,RIGHT_MOTOR_GOin4)
  • #define RIGHT_MOTOR_PWM GPIO_Pin_9
  • #define RIGHT_MOTOR_PWM_GPIO GPIOB
  • #define RIGHT_MOTOR_PWM_SET GPIO_SetBits(RIGHT_MOTOR_PWM_GPIO,RIGHT_MOTOR_PWM)
  • #define RIGHT_MOTOR_PWM_RESET GPIO_ResetBits(RIGHT_MOTOR_PWM_GPIO,RIGHT_MOTOR_PWM)
  • #endif

红外遥控

红外遥控部分我们没有进行修改,直接用了正点原子的例程,不多赘述。

值得一提的是,我们在开始项目之前,没有好好查找资料,不知道板子上就有红外,在网上买了额外的红外接收模块HX1838,不过实际效果很好用,而且拉风,就是竖着的那个天线(我的设计,酷炫)。

下面的remote.h的代码

remote.h

  • #ifndef __RED_H
  • #define __RED_H
  • #include "sys.h"
  • #define RDATA PAin(1) //红外数据输入脚
  • //红外遥控识别码(ID),每款遥控器的该值基本都不一样,但也有一样的.
  • //我们选用的遥控器识别码为0
  • #define REMOTE_ID 0
  • extern u8 RmtCnt; //按键按下的次数
  • void Remote_Init(void); //红外传感器接收头引脚初始化
  • u8 Remote_Scan(void);
  • #endif

超声波

超声波部分我们采用的模块是HC-SR04,同样是一个比较经典的模块,这一部分比较搞的是什么,是超声波模块需要5v供电,及其重要,我们一开始代码调试好后,一直显示不出来正确的数据,一直为0(我们有加OLED显示模块,所以可以方便测试),从驱动做好后一直顺风顺水突然在这卡壳了,弄得我们自闭许久。后来在网上查到是5v供电后,一改立马成功。

在这里插入图片描述
在这里插入图片描述

下面是hcsr04.h的代码

hcsr04.h

  • #ifndef __CS_H
  • #define __CS_H
  • #include "stm32f10x.h"
  • #include "delay.h"
  • //使用了TIM3
  • #include "sys.h"
  • #define uint unsigned int
  • #define TRIG_Send PAout(6)
  • #define ECHO_Reci PAin(7)
  • void CH_SR04_Init(void); //超声波模块相关配置初始化
  • float Senor_Using(void); //测距函数,返回值即为距离
  • void NVIC_Config(void); //中断配置
  • #endif

OLED显示

我们用的0.96寸7针显示模块,代码部分也没什么好说的,网上找到读懂后直接调用就行了

在这里插入图片描述

oled.h

  • // ----------------------------------------------------------------
  • // GND 电源地
  • // VCC 接5V或3.3v电源
  • // D0 接PD6(SCL)
  • // D1 接PD7(SDA)
  • // RES 接PD4
  • // DC 接PD5
  • // CS 接PD3
  • #ifndef __OLED_H
  • #define __OLED_H
  • #include "sys.h"
  • #include "stdlib.h"
  • //OLED模式设置
  • //0:4线串行模式
  • //1:并行8080模式
  • #define OLED_MODE 0
  • #define SIZE 16
  • #define XLevelL 0x00
  • #define XLevelH 0x10
  • #define Max_Column 128
  • #define Max_Row 64
  • #define Brightness 0xFF
  • #define X_WIDTH 128
  • #define Y_WIDTH 64
  • //-----------------OLED端口定义----------------
  • #define OLED_CS_Clr() GPIO_ResetBits(GPIOD,GPIO_Pin_3)//CS
  • #define OLED_CS_Set() GPIO_SetBits(GPIOD,GPIO_Pin_3)
  • #define OLED_RST_Clr() GPIO_ResetBits(GPIOD,GPIO_Pin_4)//RES
  • #define OLED_RST_Set() GPIO_SetBits(GPIOD,GPIO_Pin_4)
  • #define OLED_DC_Clr() GPIO_ResetBits(GPIOD,GPIO_Pin_5)//DC
  • #define OLED_DC_Set() GPIO_SetBits(GPIOD,GPIO_Pin_5)
  • #define OLED_WR_Clr() GPIO_ResetBits(GPIOG,GPIO_Pin_14)
  • #define OLED_WR_Set() GPIO_SetBits(GPIOG,GPIO_Pin_14)
  • #define OLED_RD_Clr() GPIO_ResetBits(GPIOG,GPIO_Pin_13)
  • #define OLED_RD_Set() GPIO_SetBits(GPIOG,GPIO_Pin_13)
  • //PC0~7,作为数据线
  • #define DATAOUT(x) GPIO_Write(GPIOC,x);//输出
  • //使用4线串行接口时使用
  • #define OLED_SCLK_Clr() GPIO_ResetBits(GPIOD,GPIO_Pin_6)//CLK
  • #define OLED_SCLK_Set() GPIO_SetBits(GPIOD,GPIO_Pin_6)
  • #define OLED_SDIN_Clr() GPIO_ResetBits(GPIOD,GPIO_Pin_7)//DIN
  • #define OLED_SDIN_Set() GPIO_SetBits(GPIOD,GPIO_Pin_7)
  • #define OLED_CMD 0 //写命令
  • #define OLED_DATA 1 //写数据
  • //OLED控制用函数
  • void OLED_WR_Byte(u8 dat,u8 cmd);
  • void OLED_Display_On(void);
  • void OLED_Display_Off(void);
  • void OLED_Init(void);
  • void OLED_Clear(void);
  • void OLED_DrawPoint(u8 x,u8 y,u8 t);
  • void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot);
  • void OLED_ShowChar(u8 x,u8 y,u8 chr);
  • void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size);
  • void OLED_ShowString(u8 x,u8 y, u8 *p);
  • void OLED_Set_Pos(unsigned char x, unsigned char y);
  • void OLED_ShowCHinese(u8 x,u8 y,u8 no);
  • void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[]);
  • #endif

主函数

  • #include "usart.h"
  • #include "remote.h"
  • #include "oled.h"
  • #include "hcsr04.h"
  • /*
  • void ZYSTM32_run(int speed,int time); //前进函数
  • void ZYSTM32_brake(int time); //刹车函数
  • void ZYSTM32_Spin_Left(int speed,int time); //左旋转函数
  • void ZYSTM32_Spin_Right(int speed,int time);//右旋转函数
  • void ZYSTM32_back(int speed,int time); //后退函数
  • */
  • float length=0,sum=0;
  • u16 tim;
  • uint j=0;
  • int i=2000;
  • int main(void)
  • {
  • u8 key;
  • float distance;
  • delay_init();
  • TIM4_PWM_Init(7199,0); //初始化PWM
  • Remote_Init(); //红外接收初始化
  • CH_SR04_Init();
  • OLED_Init(); //初始化OLED
  • OLED_Clear();
  • ZYSTM32_brake(500);
  • NVIC_Config();
  • while(1)
  • {
  • key=Remote_Scan();
  • distance=Senor_Using();
  • OLED_ShowString(0,2,"distance is");
  • OLED_ShowNum(0,4,distance,8,20);
  • if(distance>30)
  • switch(key)
  • {
  • case 98:ZYSTM32_run(100);break;
  • case 2:ZYSTM32_brake(100);break;
  • case 34:ZYSTM32_Spin_Left(100);break;
  • case 168:ZYSTM32_back(100);break;
  • case 194:ZYSTM32_Spin_Right(100);break;
  • case 104:speedchange(1);break;
  • case 152:speedchange(2);break;
  • case 176:speedchange(3);break;
  • case 48:turnleft45(220);break; //4
  • case 24:turnright45(220);break; //5
  • case 16:turnleft45(50);break; //7
  • case 56:turnright45(50);break; //8
  • case 224:speeddown();break;
  • case 144:speedup();break;
  • }
  • else
  • {
  • ZYSTM32_back(100);
  • delay_us(50);
  • ZYSTM32_brake(100);
  • }
  • }
  • }

最后我把文件打包压缩的下载链接放在这里:

https://bbs.cdsy.xyz/thread-9974-1-1.html

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门