stm32使用HAL库快速编写智能寻迹避障小车(附代码)

最近学校安排了一节用stm32编写寻迹避障小车的课,但无奈学校老师教的方法让作者觉得无法理解,但课程答辩时间快到了,组内小组成员又做的磕磕绊绊,于是身为组长的我就决定尝试一下用刚学的cubemx工具,完整的写完一个小车寻迹避障代码。经过长达三天的编写搭车过程,作者终于做出了一个可以稳定寻迹的小车,过程虽然非常艰辛,但是也非常有趣。好了废话不多说,下面是具体思路。

本设计主要有三个模块,包括信号检测模块、主控模块、电机驱动模块。信号检测模块采用灰度传感器和超声波,用以对有无障碍与黑线进行检测。主控电路采用STM32单片机为控制芯片。用编码器cubemx等软件进行编程控制,电机驱动模块采用意法半导体的298N专用电机驱动芯片,单片控制与传统分立元件电路相比,使整个系统有很好的稳定性。信号检测模块将采集到的路况信号传入STM32单片机,经单片机处理过后对298N发出指令进行相应的调整。通过有无光线接收来控制电动小车的转向,从而实现自动循迹避障的功能。

需要的材料:

  • 电机2个和万向轮2个(也可以用4个电机)
  • 小车底板
  • 298n一个
  • stm32
  • 电池
  • 灰度传感器3个
  • 超声波传感器1个
  • 杜邦线若干

小车整体连接思路如下,

小车连线图

主要元件介绍:

1. 超声波

超声波测距器可应用于汽车倒车。建筑施工工地以及一些工业现场的位置监控,也可用于如液位、井深、管道长度、物体厚度等的测量。其测量范围为0.10~4.00m,测量精度为1cm。测量时与被测物体无直接接触,能够清晰、稳定地显示测量结果。
由于超声波指向性强,能量消耗慢,在介质中传播的距离较远,因而超声波经常用于距离的测量。利用超声波检测距离设计比较方便,计算处理也比较简单,并且在测量精度方面也能达到使用的要求。

在这里插入图片描述

VCC 供 3.3V-5 V电源,
GND 为地线,
TRIG 触发控制信号输入,
ECHO 回响信号输出

基本工作原理:
(1)采用 IO 口 TRIG 触发测距,给最少 10us 的高电平信号。
(2)模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回;
(3)有信号返回,通过 IO 口 ECHO 输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2;

超声波

2. 灰度传感器

灰度传感器是模拟传感器,与stm32结合使用,可以感知地面或桌面不同的颜色而产生相应的信号,可实现与颜色有相关的互动作品,也可以作为巡线小车的巡线传感器或者足球机器人的场地灰度识别。电源需要和控制器一致,通常为3.3V或5V。
在这里插入图片描述

接口定义:
out:信号输出
+:电源(VCC)
-:地(GND)

基本工作原理:
灰度传感器共引出三个引脚,分别是电源正Vcc、电源地GND、信号端out,实际使用时可以直接将传感器连接到stm32的模拟接口,传感器白色高亮 LED 亮起,将传感器扣放在灰度不同的纸张上,通过stm32自带的 AD 转换进行数据的读取,然后通过串口打印出测量的模拟量即可。

3. 电机

电机采用直流减速电机,直流减速电机转动力矩大,体积小,重量轻,装配简单,使用方便。由于其内部由高速电动机提供原始动力,带动变速(减速)齿轮组,可以产生较大扭力。
电机

4. 298n驱动模块

驱动模块采用专用芯片L298N 作为电机驱动芯片,L298N 是一个具有高电压大电流的全桥驱动芯片,其响应频率高,一片L298N可以分别控制两个直流电机。以下为L298N的引脚图和输入输出关系表。

298n
关系表

总体控制思路

在这里插入图片描述

主要代码:

1. 距离测算代码

uint16_t soner_gettime(void)
{
	uint32_t a;
	a=TIM2->CNT;
	return a;
}

float soner_getdistance(void)
{   
	uint16_t time_node1;
  uint16_t time_node2;
  uint16_t measure;
  soner_startrange();
  while(HAL_GPIO_ReadPin(SONER_PORT,SONER_ECHO_PIN)==RESET);
	time_node1=soner_gettime();
	while(HAL_GPIO_ReadPin(SONER_PORT,SONER_ECHO_PIN)==SET);
	time_node2=soner_gettime();
	measure=time_node2-time_node1;
	distance_temp = measure * 17.0/100;
	if(distance_last==0)
		distance_last = distance_temp;
	if(distance_last-distance_temp>100 || distance_temp-distance_last>100)
	{
		distance_result =distance_last;
		distance_last=distance_temp;
	}
	else
	{
		distance_result=distance_temp;
		distance_last=distance_temp;
	}
  return distance_result;
}


2. 距离判断

		
		if(distance<15){
			
	  HAL_GPIO_WritePin(ele_l1_GPIO_Port, ele_l1_Pin, GPIO_PIN_SET);
	  HAL_GPIO_WritePin(ele_l2_GPIO_Port, ele_l2_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(ele_r1_GPIO_Port, ele_r1_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(ele_r2_GPIO_Port, ele_r2_Pin, GPIO_PIN_SET);
			
		}

3. ADC读取灰度传感器值:



		
		if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1),HAL_ADC_STATE_REG_EOC))
		{
			ADC1_Value = HAL_ADC_GetValue(&hadc1);
       
      lemon1=(ADC1_Value-3000);	
			if(lemon1<100){
				a1=1;
			}else{
				a1=0;
			}
		}
			
			//adc1
			
		
		HAL_ADC_PollForConversion(&hadc2,50);
		
		if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc2),HAL_ADC_STATE_REG_EOC))
		{
			ADC2_Value = HAL_ADC_GetValue(&hadc2);
       
      lemon2=(ADC2_Value-3300);
			
			if(lemon2<40){
				a2=1;
			}else{
				a2=0;
			}
		}
		
		//adc2
		

		HAL_ADC_PollForConversion(&hadc3,50);
		
		if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc3),HAL_ADC_STATE_REG_EOC))
		{
			ADC3_Value = HAL_ADC_GetValue(&hadc3);
       
      lemon3=(ADC3_Value-2180);
			
			if(lemon3<120){
				a3=1;
			}else{
				a3=0;
			}
			
		//adc3
			
		}

4. 灰度传感器驱动电机:

if(a2==1&&distance>15){
			
			HAL_GPIO_WritePin(ele_l1_GPIO_Port, ele_l1_Pin, GPIO_PIN_RESET);
			HAL_GPIO_WritePin(ele_l2_GPIO_Port, ele_l2_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(ele_r1_GPIO_Port, ele_r1_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(ele_r2_GPIO_Port, ele_r2_Pin, GPIO_PIN_SET);
			
			__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_3,25);
			__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,25);
			
		}
		
		if(a1==1&&distance>15){
			
			HAL_GPIO_WritePin(ele_l1_GPIO_Port, ele_l1_Pin, GPIO_PIN_RESET);
			HAL_GPIO_WritePin(ele_l2_GPIO_Port, ele_l2_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(ele_r1_GPIO_Port, ele_r1_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(ele_r2_GPIO_Port, ele_r2_Pin, GPIO_PIN_SET);
			
			__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_3,25);
			__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,0);
			
		}
			
		
		
		
		if(a3==1&&distance>15){
			
			HAL_GPIO_WritePin(ele_l1_GPIO_Port, ele_l1_Pin, GPIO_PIN_RESET);
			HAL_GPIO_WritePin(ele_l2_GPIO_Port, ele_l2_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(ele_r1_GPIO_Port, ele_r1_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(ele_r2_GPIO_Port, ele_r2_Pin, GPIO_PIN_SET);
			
			__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_3,0);
			__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,25);
			
		}





    

制作过程

小车的组装还比较简单,组装小车并没有花太长时间。我们用3D打印做了一个放灰度传感器的小架子。
在这里插入图片描述

因为采用了cubemx编写程序,使得代码简洁易懂。
在这里插入图片描述
经过多次测试与改进,作者的智能小车能很好的完成循迹和避障功能,小车能够用灰度传感器在测试场地上沿黑线前进并在转弯处转向。通过本次编程,作者理解了智能小车避障、寻迹与自动控制的基本原理,并且学习了使用cubemx编写stm32的keil代码,十分有趣,让我明白了电控的知识与过程,慢慢领悟了其重要性,在我们的生活中也可以用到,比如可自己制作自动扫地机器人,无人机等,激发了我学习的动力,也让我接触到了电机控制、灰度传感器、298n模块、超声波模块的使用,并学习了如何烧录芯片、编写代码以及串口调试。

  • 28
    点赞
  • 312
    收藏
    觉得还不错? 一键收藏
  • 29
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值