stm32项目平衡车详解(stm32F407)下

stm32项目平衡车详解(stm32F407)下

本文章学习借鉴于创客学院团队,以表感谢。教学视频

B站学习地址

HC-SRO4 超声波测距避障功能开发
TSL1401 CCD摄像头实现小车巡线功能
小车通信功能分析及ESP32模块介绍
oled 显示置入屏幕显示小车状态



前言

前面我们已经实现了平衡小车的直立环,平衡环,转向环,下面我们将实现小车平衡小车蔽障与巡线功能的开发。如下如所示:
在这里插入图片描述
在这里插入图片描述


一、HC-SRO4 超声波测距避障功能开发

HC-SRO4超声波测距模块?

在这里插入图片描述
在这里插入图片描述
HC- SR04是一种超声波接近传感器,可以告诉您物体是否在它前面,并且还提供传感器和物体之间的距离。这些传感能力使其特别适用于需要知道远离物体或障碍物的机器人,例如墙壁或不应撞击的家具。

点击查看,HC-SR04超声波传感器原理

超声波测距避障功能开发

cube 搭建工程项目
在这里插入图片描述
下面给中断使能
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
启动定时器TIM7 去计时

在这里插入图片描述

在这里插入图片描述

避障模式开发

避障模式原理就是通过超声波加测距离,通过转向来躲避障碍物。所以我们会用转向环来控制小车转向。

//启动超声波,检测距离


//启动超声波检测函数

void HC_SRC04_Start(void)
{
   
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0, GPIO_PIN_SET); //设置高电平启动
	
	delay_us(20); 
	
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0, GPIO_PIN_RESET); //设置高低平启动
}

调用定时器中毒阿女函数进行计数,利用声音传播速度和接收时间测算距离


/**
  * @brief This function handles TIM7 global interrupt.
  */
void TIM7_IRQHandler(void)
{
   
  /* USER CODE BEGIN TIM7_IRQn 0 */

  /* USER CODE END TIM7_IRQn 0 */
  HAL_TIM_IRQHandler(&htim7);
  /* USER CODE BEGIN TIM7_IRQn 1 */

  /* USER CODE END TIM7_IRQn 1 */
}

/* USER CODE BEGIN 1 */
uint8_t ECHO_IRQ_FLAG = 0;

uint8_t time_cnt = 0; //参数二,溢出次数
static uint8_t last_distence =0;


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
   
	int time = 0;
	if(GPIO_Pin == GPIO_PIN_1)
	{
   
		if(ECHO_IRQ_FLAG == 0) //上升沿中断
		{
   
			ECHO_IRQ_FLAG=1; 
			HAL_TIM_Base_Start_IT(&htim7); //开启定时器,开始计时
		}else{
   
			ECHO_IRQ_FLAG = 0;   //下降沿中断
			HAL_TIM_Base_Stop_IT(&htim7);//关闭定时器,计时结束
			
			time = time_cnt*1000 + TIM7->CNT / 2; //统计声(单次)音返回时间
			
			Distence = 340*100* time /1000000; //微妙转化为秒
			if(Distence == 0)  Distence = last_distence;
			else               last_distence = Distence;
				
		}
	}
	
}

配合pid 控制函数,使用超声波测距的距离,进行避障,小车达到避障距离就开始转弯避障,(避障距离建议超过小车直径即可)



int Balance_Pwm,Vertical_Pwm,Trun_Pwm;
int Motor1,Motor2;
int Encoder_left,Encoder_right;
float Movement = 0; //目标速度
int CCD; //目标角度

int FS_MODE;        //0 遥控模式1,避障模式  2巡线模式
int Distence;       //检测小车与障碍物的距离


//PID控制任务
void Car_Task_100HZ(void)
{
   
	//启动超声波检测模式
	HC_SRC04_Start();
	
	
	//1、确定直立环的PWM
	
	Balance_Pwm = Vertical_Ring_PD(OutMpu.pitch,OutMpu.gyro_x); //*形参:(float Angle):x轴的角度/(float Gyro):x轴的角速度
	
	//2、确定速度环的PWM
	Encoder_left = Read_Encoder(1); //左轮
	Encoder_right = -Read_Encoder(2); //右轮
	
	Vertical_Pwm = Vertical_speed_PI(Encoder_left,Encoder_right,OutMpu.pitch,Movement);
	//3、确定方向环的PWM
	
	if(FS_MODE == 0) //遥控模式
		Trun_Pwm = Vertical_turn_PD(CCD,OutMpu.yaw);
	else if(FS_MODE == 1) //避障模式
	{
   
		if(Distence < 20) //直线距离在20cm 直接转向 20度
			Trun_Pwm = Vertical_turn_PD(20,OutMpu.yaw); //直接转向 20度
		else
			Trun_Pwm = 0; //直行
			
	}
	else if(FS_MODE == 2) //巡线模式
	{
   
		
	}
	
	
	
	//4、确定最终电机的左右pwm 
	
	Motor1 = Balance_Pwm+Vertical_Pwm+Trun_Pwm;
	Motor2 = Balance_Pwm+Vertical_Pwm-Trun_Pwm;
	
	PWM_Limiting((int) Motor1,(int) Motor2);

	//4、设置电机
	Set_PWM(Motor1,Motor2); //*形参;(int motor1):电机1对应的PWM值/(int motor2):电机2对应的PWM值
			
}
			
}

二、TSL1401 CCD摄像头实现小车巡线功能

巡线就是小车按照轨迹进行一定的运动,我们通过设计头模块进项轨迹实施采集分析调整车辆运动方向。

在这里插入图片描述

TSL1401 CCD摄像头?

参考案例 STM32版CCD线性摄像头寻线寻迹小车

在这里插入图片描述
在这里插入图片描述
CCD采集到外部像素,感应光线的强度通过AD 输出

在这里插入图片描述
不同的光线强度的灰度值是不一样的,通过信号传输给控制器,控制器根据灰度值来确定我们的条件。
在这里插入图片描述
上图所从左到右,由亮变暗在变亮,中间黑色区域是最暗大的,我们使用线性 就是横排采集一条线,判断内容。

在这里插入图片描述
上图看到SI由采集的到最后AD输出的电压值。
在这里插入图片描述

巡线小车功能开发(编写程序)

电路图如下:

在这里插入图片描述
在这里插入图片描述
CCD查看使用教程

TSL1401 示例代码如下:
/**
  ******************************************************************************
  * File Name          : main.c
  * Description        : Main program body
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2018 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f0xx_hal.h"
#include "adc.h"
#include "usart.h"
#include "gpio.h"

/* USER CODE BEGIN Includes */
#include "stdio.h"
#include <math.h>

#define CCD_MIDDLE 			0
#define CCD_THRESHOLD		1
#define CCD_LEFT				2
#define CCD_RIGHT				3

#define TSL_CLK_H HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_SET) 
#define TSL_CLK_L HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_RESET)

#define TSL_SI_H HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_SET) 
#define TSL_SI_L HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_RESET) 
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
   
HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */
uint16_t ADV[128]={
   0};  
uint8_t i;



struct tCCD
{
   
	uint16_t middle;      //中间位置值
	uint16_t threshold;   //像素ad阈值
	uint16_t left;        //左跳变的位置
	uint16_t right;       //右跳变的位置
};

struct tCCD  CCD;
/**************************************************************************************************
*函数名:abs()
*功能:将数进行绝对值处理
*形参:number 需要进行绝对值处理的数
*返回值:经过处理后绝对值
**************************************************************************************************/
int abs (int number)
{
   
	return( number>=0 ? number : -number );
}
/**************************************************************************************************
*函数名:Dly_us()
*功能:延时函数,用来调整CCD曝光
*形参:无
*返回值:无
***************************************************************************************************/
void Dly_us(void)
{
   
   int ii;    
   for(ii=0;ii<220;ii++);      
}
/**************************************************************************************************
*函数名:Get_Adc()
*功能:得到CCD数据
*形参:无
*返回值:读取到的电压值
***************************************************************************************************/
uint16_t Get_Adc(void)
{
   
	HAL_ADC_Start(&hadc);
	HAL_ADC_PollForConversion(&hadc, 50);
	if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc), HAL_ADC_STATE_REG_EOC))
	return 	HAL_ADC_GetValue(&hadc);
		else
			while(1);
}
/***************************************************************************************************
*函数名:RD_TSL()
*功能:读取CCD原始数据
*形参:无
*返回值:无
****************************************************************************************************/
 void RD_TSL(void) 
 {
   
	uint8_t i=0,tslp=0;
	TSL_CLK_H;
	TSL_SI_L;
	Dly_us();
	 
	TSL_SI_H;
	TSL_CLK_L;
	Dly_us();
	 
	TSL_CLK_H;
	TSL_SI_L;
	Dly_us();
	  for(i=0;i<128;i++){
   
			TSL_CLK_L;
			Dly_us();
			ADV[tslp]=(Get_Adc())>>4;
			++tslp;
			TSL_CLK_H;
			Dly_us();
		}			
 }
 /************************************************************************************************************************
 *函数名:Find_Middle_CCD()
 *功能:读取CCD中值
 *形参:无
 *返回值:CCD中值位置
 *************************************************************************************************************************/
 uint8_t Find_CCD_DATA(void)
 {
   
	 static uint8_t i,j;
	 //static uint8_t Last_Middle_CCD;
	 uint8_t Middle_CCD_Value;
	 static uint16_t  value1_max,value1_min;
	 value1_max=ADV[0];
	 //读取最大值
		for(i=5;i<123;i++){
   
        if(value1_max<=ADV[i])
        value1_max=ADV[i];
     }
	 value1_min=ADV[0]; 
		 //得到最小值
		for(i=5;i<123;i++){
   
       if(value1_min>=ADV[i])
       value1_min=ADV[i];
     } 
		//计算阈值
	 CCD.threshold=(value1_max+value1_min)/2;
		 //计算左跳变值
		for(i = 5;i<118; i++){
   
		if(ADV[i]>CCD.threshold&&ADV[i+1]>CCD.threshold&&ADV[i+2]>CCD.threshold&&ADV[i+3]<CCD.threshold&&ADV[i+4]<CCD.threshold&&ADV[i+5]<CCD.threshold){
   	
		  CCD.left=i;
		  break;	
		}
	}
		//计算右跳变值
		for(j = 118;j>5; j--){
   
		if(ADV[j]<CCD.threshold&&ADV[j+1]<CCD.threshold&&ADV[j+2]<CCD.threshold&&ADV[j+3]>CCD.threshold&&ADV[j+4]>CCD.threshold&&ADV[j+5]>CCD.threshold){
   	
		  CCD.right=j;
		  break;	
		}
  }
		//计算中值
		CCD.middle =(CCD.right+CCD.left)/2;
//		if(abs(Middle_CCD_Value-Last_Middle_CCD)>70){
   
//			Middle_CCD_Value=Last_Middle_CCD;
//			Last_Middle_CCD=Middle_CCD_Value;
//		}
		return Middle_CCD_Value;
 }
 
 /***************************************************************************************************************************/
 void ANO_Send_Data(void)
{
   
		 HAL_UART_Transmit(&huart1,(uint8_t *)&CCD,sizeof(CCD)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闰土小蒋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值