STM32循迹小车系列教程(二)—— 使用编码器获取小车速度

这篇具有很好参考价值的文章主要介绍了STM32循迹小车系列教程(二)—— 使用编码器获取小车速度。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本章节主要介绍编码器的原理,获取编码器脉冲值以及如何计算小车速度和路程

前言

1.软件准备:STM32CubeMx、Keil5_ MDK

2.硬件准备:STM32F103C8T6核心板、带编码器电机、TB6612电机驱动模块/L298N电机驱动、18650锂电池3节/3S航模电池、杜邦线若干

编码器简介

如图 3-1 左所示是市场上常用的编码器图片,这样编码器精度较高,但价格较高,而且体积较大,我们寻迹车用到的编码器图片如图 3-1 右所示。我们可以把编码器看做是一个能够测量小车轮子所转圈数的传感器,能够测量出轮子转的圈数便可知道小车行驶的里程。我们通过计算 1秒时间内轮子转的圈数再结合寻迹车轮子的半径, 即可计算出寻迹车的速度。获取到小车行走速度和行驶里程后我们便可通过传感器获取到的行驶里程或者小车速度控制小车的行驶里程和行驶速度。

stm32小车编码器,stm32,单片机,嵌入式硬件

我们用到寻迹车上的编码器一般有霍尔编码器和光电编码器,两者原理差不多,都是测量小车轮子转一圈编码器输出的脉冲数,光电编码器相比霍尔编码器精度会高些。一般我们常用的编码器都是分为 AB 双相的,双相的比单相的相比分辨率更高,而且可以获取到轮子转的方向。 

stm32小车编码器,stm32,单片机,嵌入式硬件

编码器原理

如图 3-2 所示为编码器的原理,我们可以看到图中轮子转一圈 A 相输出 8 个跳边沿,单片机通过外部中断每个跳边沿计数器加 1 的话,轮子转一圈会计数到 8。如果用 AB 双相的话每个相都输出 8个跳边沿,单片机通过外部中断每个跳边沿计数器加 1 的话,轮子转一圈会计数到 8。如果用 AB 双相的话每个相都输出 8 个跳边沿,双相就输出 16 个跳边沿,精度也就会相应提高 2 倍。我们同时可以发现当 B 相上升沿的时候 A 相处于高电平状态,此时电机处于正转状态。相反,A 相上升沿的时候 B 相处于高电平状态,此时电机处于反转状态,我们便可由此判别电机的正转和反转状态。

stm32小车编码器,stm32,单片机,嵌入式硬件

编码器电路

 如图 3-3 所示为带编码器电机的接口图,也就是图 3-1 右所示的编码器电机,读取编码器的数据本质上就是读取编码器输出的脉冲数据, 就是通过单片机定时器和外部中断获取编码器输出的上升沿和下降沿。一般高级些的单片机内部都会有编码器读取的硬件资源,我们所使用的STM32F103C8T6 单片机就有,每个基本定时器和高级定时器都可以配置成编码器模式。如图 3-4所示,STM32F103C8T6 PA0 和 PA1 对应定时器 2 的通道 1 和通道 2,PA6 和 PA7 对应定时器 3 的通道 1 和通道 2,将定时器1 和定时器 2 配置成编码器模式即可读取到寻迹车左右两轮的速度和行驶里程。

stm32小车编码器,stm32,单片机,嵌入式硬件

stm32小车编码器,stm32,单片机,嵌入式硬件

stm32小车编码器,stm32,单片机,嵌入式硬件

编码器测速程序实现

CubeMx配置:

stm32小车编码器,stm32,单片机,嵌入式硬件

PWM配置

stm32小车编码器,stm32,单片机,嵌入式硬件

编码器模式配置 

stm32小车编码器,stm32,单片机,嵌入式硬件

 stm32小车编码器,stm32,单片机,嵌入式硬件

GPIO配置

void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, IN4_Pin|IN3_Pin|IN2_Pin|IN1_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pins : PBPin PBPin PBPin PBPin */
  GPIO_InitStruct.Pin = IN4_Pin|IN3_Pin|IN2_Pin|IN1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

定时器配置

void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_Encoder_InitTypeDef sConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 65535;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
  sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
  sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC1Filter = 0;
  sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
  sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC2Filter = 0;
  if (HAL_TIM_Encoder_Init(&htim2, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */

}
/* TIM4 init function */
void MX_TIM4_Init(void)
{

  /* USER CODE BEGIN TIM4_Init 0 */

  /* USER CODE END TIM4_Init 0 */

  TIM_Encoder_InitTypeDef sConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM4_Init 1 */

  /* USER CODE END TIM4_Init 1 */
  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 0;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 65535;
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
  sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
  sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC1Filter = 0;
  sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
  sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC2Filter = 0;
  if (HAL_TIM_Encoder_Init(&htim4, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM4_Init 2 */

  /* USER CODE END TIM4_Init 2 */

}

编码器程序

电机选取加速比为1:30。编码器线数为11。

轮胎转一圈产生30x11个脉冲,单片机编码器计数器计数为30x11x4。

电机速度为电机脉冲值x单片机编码器计数器计数。

/* USER CODE BEGIN PTD */
#define ABS(X) (X>0) ? (X=X) : (X=-X)

#define IN4(H) 	if(H)\
	                  HAL_GPIO_WritePin(IN4_GPIO_Port,IN4_Pin,GPIO_PIN_SET);\
                 else HAL_GPIO_WritePin(IN4_GPIO_Port,IN4_Pin, GPIO_PIN_RESET);
#define IN3(H)  if(H)\
	                   HAL_GPIO_WritePin(IN3_GPIO_Port,IN3_Pin,GPIO_PIN_SET);\
                 else HAL_GPIO_WritePin(IN3_GPIO_Port,IN3_Pin, GPIO_PIN_RESET);
#define IN2(H)  if(H)\
	                   HAL_GPIO_WritePin(IN2_GPIO_Port,IN2_Pin,GPIO_PIN_SET);\
                 else HAL_GPIO_WritePin(IN2_GPIO_Port,IN2_Pin, GPIO_PIN_RESET);
#define IN1(H)  if(H)\
	                   HAL_GPIO_WritePin(IN1_GPIO_Port,IN1_Pin,GPIO_PIN_SET);\
                 else HAL_GPIO_WritePin(IN1_GPIO_Port,IN1_Pin, GPIO_PIN_RESET);
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

int32_t Encoder1Count = 0;
int32_t Encoder2Count = 0;

int64_t total_EncCount1 = 0;
int64_t total_EncCount2 = 0;

float Motor1Speed = 0.0;
float Motor2Speed = 0.0;

uint32_t uwtick_8ms_delay = 0;

/* USER CODE END PM */
/***********************************************************************************************
 函 数 名:void Get_Encoder(void)
 功    能:
 说    明:获取编码器反馈 8ms采样 
************************************************************************************************/

void Get_Encoder(void) //获取编码器反馈
{
	Encoder1Count =  - (short)__HAL_TIM_GetCounter(&htim2);//获取电机脉冲值
	Encoder2Count =  - (short)__HAL_TIM_GetCounter(&htim4);//获取电机脉冲值
	
	total_EncCount1 += Encoder1Count;	//位置累加
  total_EncCount2 += Encoder2Count;
	
	__HAL_TIM_SetCounter(&htim2,0);			//清除编码器值
	__HAL_TIM_SetCounter(&htim4,0);			//清除编码器值
	
	
	Motor1Speed = (float)Encoder1Count*100/30.0/11/4;//计算速度
	Motor2Speed = (float)Encoder2Count*100/30.0/11/4;

}
/**************************************************************************
函 数 名:void set_speed(int16_t left_speed,int16_t right_speed)
功    能:速度设定函数
入口参数:左右轮速度
**************************************************************************/
void set_speed(int16_t left_speed,int16_t right_speed)//设定电机转速
{
	if(left_speed>0)   {IN1(1);IN2(0);}
	else 						   {IN1(0);IN2(1);}
	if(right_speed>0)  {IN3(0);IN4(1);}
	else 						   {IN3(1);IN4(0);}
	
	__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, ABS(left_speed));
	__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_4, ABS(right_speed));
}

主程序

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM2_Init();
  MX_TIM4_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
	//开启PWM
	HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
	HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);

	//开启Encoder
	HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL);
    HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL);
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		set_speed(500,500);
		if(uwTick - uwtick_8ms_delay > 8)
		{
			Get_Encoder();
			uwtick_8ms_delay = uwTick;
		}

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

具体实现 

正向转动轮子,编码器脉冲读取正常,速度转换正常。

编码器演示视频文章来源地址https://www.toymoban.com/news/detail-548218.html

到了这里,关于STM32循迹小车系列教程(二)—— 使用编码器获取小车速度的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • stm32通过编码器控制小车行驶指定的距离

    主控芯片为stm32f407,通过编码器计算行驶距离,pid闭环控制,程序源码中包含上一期的pid速度控制。使用本程序所需知道的条件:编码器一周几个脉冲,电机的减速比和车轮的直径。 (注:免费源码链接,请点赞关注私信) 视频介绍;行驶距离120厘米,换算编码器脉冲共3103个

    2024年04月23日
    浏览(19)
  • stm32循迹小车教程(保姆级教程)

                    我历时四周终于制作完成原理图设计,原件焊接,代码测试,赛道循迹。在此,我要十分感谢在我制作过程中给予过帮助的所有人。首先明确小车使用主控芯片为stm32f103c8t6。                 制作小车要用的软件有:嘉立创EDA                 首先明确一

    2024年02月02日
    浏览(32)
  • STM32智能小车循迹教程

    本篇文章将带大家学习STM32智能小车的循迹功能。 电路工作描述 以其中一路为例 TCRT5000传感器的红外发射二极管不断发射红外线,当发射的红外线没有被反射回来或者反射回的强度不够大时,红外接收管一直处于关闭状态,此时比较器LM393的2脚的电压低于3脚的电压,输出O

    2023年04月08日
    浏览(45)
  • 使用STM32 再实现循迹/跟随/摇头避障小车

    硬件介绍和接线 TCRT5000 使用方法和原理见89C52时期的介绍。 循迹小车需要使用两个TCRT5000, 左侧的DO接到PB3 ; 右侧的DO接到PB4 CubeMX 1. 在上节的基础上进行修改 + 配置两个传感器的GPIO 2. 惯例配置更新代码 Keil 注意, 如果要使用PWM调速就必须全部是PWM调速 ,因为一旦使用PW

    2024年02月15日
    浏览(33)
  • STM32:使用RS485和多摩川编码器通信

    本文主要讲使用STM32F767和绝对式多摩川TS5700N8501编码器通信的流程和注意事项。 TS5700N8501编码器推荐收发电路如下:  首先使用STM32CubeMX生成RS485驱动部分功能代码,注意该款编码器的波特率是2.5Mbps。   注意使能的GPIO可以使用其他管脚,我们的主控板使用的是PA8。前期可以这

    2024年02月11日
    浏览(59)
  • 【STM32】HAL库自学记录-旋转编码器的使用

    通过本文可学会两种实现判断旋转编码器正转反转的方法,可根据自己的应用场景来选择使用哪种方法。 1、芯片:STM32F103RCT6 2、STM32CubeMx软件 3、IDE: MDK-Keil软件 4、旋转编码器模块 5、XCOM V1.4串口软件 图中C端为GND。 方向 :A相和B相相差一个相位,一般来说是90°。A相信号在

    2024年02月11日
    浏览(42)
  • Stm32-使用TB6612驱动电机及编码器测速

    最近在 学习编码电机以及尝试使用编码电机测速 。遇到了很多问题,花费了很多时间,在这里做一个记录,对自己学习到的知识进行一个总结 找了很多资料,看了很多视频,这些太多了,以至于让我不知道究竟哪一个是正确的,今天看这个,明天看这个,导致自己的学习效

    2023年04月16日
    浏览(62)
  • 【嵌入式】STM32计时器编码器接口模式使用

    使用STM32调试电机或传感器时经常会使用到计数器的编码器接口模式,本文主要记录该模式的固件库配置方法,并给出使用该模式获取光栅测距值的实例。 硬件: STM32F103C8T6 光栅测距传感器 编码器接口模式为STM32计时器的一种特殊使用模式,该模式下可对编码器输出的脉冲信

    2024年02月20日
    浏览(39)
  • (STM32)PWM输出控制电机旋转并且使用编码器读取脉冲数

    目录  前言 一、pwm输出让电机转  1.电机的接线说明 2.驱动的接线说明 3.pwm输出代码  pwm.c pwm.h 4.输出pwm控制电机旋转 二、配置定时器编码器模式 1.定时器编码器模式 编码器原理 编码器相关的概念 2.编码器模式——代码部分 3.获取脉冲数 三、定时读取编码器读取的脉冲数

    2024年02月03日
    浏览(41)
  • 智能小车STM32——蓝牙循迹

    1、功能介绍 蓝牙切换功能:智能小车内置了蓝牙模块,可以通过手机或其他蓝牙设备与之连接。用户可以通过手机发送指令控制小车的运动方向,实现远程控制。 循迹功能:智能小车配备了红外线传感器,可以实现循迹功能。通过检测地面上的黑线或白线,小车能够自动沿着

    2024年01月19日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包