编码电机测速(stm32f1/HAL库/CubeMX/编码器模式/平衡小车/直流减速电机/超详细)_stm32 直流无刷 增量式编码器_想要亿只独角兽的博客-程序员宅基地

技术标签: stm32  STM32常见外设的使用  各种STM32小车  arm  单片机  

系列文章目录(STM32常用外设/HAL库版)

一、HC-SR04超声波模块的使用
二、OLED的HAL库代码介绍及使用
三、直流减速电机的测速以及电机驱动的使用(本篇)



前言

由于之后要着手开始做一些闭环的小项目,比如常见的两轮平衡小车,那就必须使用编码器来测量直流减速电机的转速,本文将介绍如何使用stm32f103c8t6的编码器模式测量带15线霍尔编码器的直流减速电机的空载转速。


先放上最终效果展示吧

使用STM32的编码器模式测量直流减速电机的转速


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

提示:以下是本篇文章正文内容,下面案例可供参考

一、所用的器材模块介绍

  1. stm32f103c8t6最小系统板
  2. 12V锂电池
  3. DC-DC可调降压模块(LM2596S)
  4. 0.96寸OLED(IIC接口)
  5. HC-08蓝牙模块
  6. 两路直流电机驱动(这里用的是DRV8848而不是TB6612,因为TB6612已经停产)
  7. 直流减速电机(电机型号为GM25-370,空载转速12V12000RPM,减速比为34:1,减速后350转/分)
  8. 15线霍尔编码器(编码器单圈15脉冲,减速后单圈为510脉冲每圈,可以通过stm32编码器模式4倍频至2040脉冲每圈)

所用的带15线霍尔编码器的GM25-370直流减速电机及其参数见下图

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

所用模块的具体作用:
蓝牙模块:通过手机蓝牙直接改变电机转速
OLED:实时显示电机的转速以及读取到的脉冲数

二、接线说明

特别注意:这步至关重要,稍有不慎就会烧坏单片机

下面给出原理图:(最好不要把电机驱动板上所有的GND都与单片机共地,VCC下面的GND可以不与单片机共地,还有就是STM32只外接信号线,不要用它给电机驱动板的VCC供电,STM32接一些感性负载(比如电机)时最好加光耦隔离,我之前也是用了光耦隔离,但是要想完全隔离只能用双电源,最终就没加)
在这里插入图片描述

三、CubeMX配置

为了进行测速,我们一共需要3个定时器,作用分别是:①输出PWM;②编码器模式进行脉冲计数;③计时,确定每次测速的时间间隔;

3.1. 时钟树的配置

(1)点击RCC ,开启HSE,并选择RC或晶体作为时钟源

在这里插入图片描述

(2)配置时钟树

在这里插入图片描述

3.2. PWMA配置(TIM4)

(1)点击TIM4,在Mode选项中设置Clock Source为Internal Clock。设置Channel1为PWM Generation CH1,其余默认即可。

在这里插入图片描述

(2)设置Configuration选项中Parameter Settings的参数

将PWM设置为10KHz
设置频率最好在20Hz~20000Hz以内,因为这个频率内的PWM波不会让电机发出明显的电流声

在这里插入图片描述

(3)TIM4_CH1 的GPIO参数设置

PB6参数设置

在这里插入图片描述

3.3. 编码器模式配置(TIM3)

(1)点击TIM3,在Mode选项中设置Combined Channels为编码器模式。

在这里插入图片描述

(2)设置Configuration选项中Parameter Settings的参数

注意:将Encoder Mode 设置为Encoder Mode TI1 and TI2,使得编码器模式为4倍频模式,得到的脉冲值X4

编码器模式中Polarity是用来设置触发的信号是否反向,即用来匹配编码器与电机的旋转方向,而不是像“输入捕获”功能那样用来设置触发的边沿

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

(3)GPIO参数设置

在这里插入图片描述

3.4. 定时器配置(TIM1)

配置定时器,配置为0.1S定时中断一次读取TIM3编码器模式记录的脉冲值

在这里插入图片描述

3.5. IIC和USART配置

这部分就是开启I2C1的I2C模式,开启USART2的异步模式

3.6. NVIC配置

开启TIM1 update interrupt,USART2 global interrupt 两个中断并将USART2 global interrupt的优先级设置的高于TIM1 update interrupt,因为要通过串口接收中断来改变转速,如果串口中断的优先级低于定时器中断的优先级,此时串口中断就不能立刻执行

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

3.7. 最终引脚图

在这里插入图片描述

四、程序代码及说明

提示:OLED代码见OLED的HAL库代码介绍及使用,这里就不再赘述
在这里插入图片描述

4.1. encoder.h

#ifndef ENCODER_ENCODER_H_
#define ENCODER_ENCODER_H_

#include "stm32f1xx_hal.h" //HAL库文件声明
#include <main.h>

extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim3;

void GET_NUM(void);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);

#endif /* ENCODER_ENCODER_H_ */

4.2. encoder.c

TIM3(编码器模式)的计数值为0-65535,采用short int类型对其强制类型转换;
若TIM3计数器值为 0 ~ 32767,则强制转化后的值仍为0 ~ 32767,电机正转;
若TIM3计数器值为32768 ~ 65535,则强制转化后的值为-32768 ~ -1,,电机反转;

#include"encoder.h"
#include"../oled/oled.h"

float  n=0;//转速,单位为:转/秒
short encoder_counter=0;//STM32编码器模式读取的总脉冲数

/**
 * @function: void GET_NUM(void)
 * @description: 使用STM32编码器模式,读取编码器产生的脉冲值
 * @param {*} 
 * @return {*}
 */
void GET_NUM(void)
{
    
	encoder_counter=(short) __HAL_TIM_GET_COUNTER(&htim3);
	__HAL_TIM_SET_COUNTER(&htim3,0);
}

/**
 * @function:void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
 * @description: 定时器中断回调函数,0.1S中断一次并计算转速,将电机转速以及编码器产生的脉冲数显示在OLED屏上
 * @param {TIM_HandleTypeDef *htim} 
 * @return {*}
 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    
	if(htim==&htim1)
	{
    
		 GET_NUM();//得到所记录的脉冲数
		 OLED_Showdecimal(0,6,encoder_counter,5,2,12,0);//在特定位置显示5位整数+2位小数的脉冲数
		 n=(float)encoder_counter/2040/0.1;//转速为n,r/s
		 //编码器单圈15脉冲,减速后单圈为510脉冲每圈,可以通过stm32编码器模式4倍频至2040脉冲每圈。定时器中断是0.1S执行一次
		 OLED_Showdecimal(0,4,n,2,2,12,0);//在特定位置显示2位整数+2位小数的电机转速
	}
}

4.3. motor.h

这个.h就是给电机驱动板AO1,AO2赋高低电位的

#ifndef MOTOR_MOTOR_H_
#define MOTOR_MOTOR_H_

#include "stm32f1xx_hal.h" //HAL库文件声明
#include <main.h>

#define MOTOR_GO HAL_GPIO_WritePin(GPIOA, AIN1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, AIN2_Pin, GPIO_PIN_SET)

#endif /* MOTOR_MOTOR_H_ */

4.4. main.c

/* USER CODE BEGIN Includes */
#include "../../icode/motor/motor.h"
#include "../../icode/usart/usart.h"
#include "../../icode/encoder/encoder.h"
#include "../../icode/oled/oled.h"
/* USER CODE END Includes */

  /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1); //开启TIM4 PWMA模式
  HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);//开启TIM3编码器模式
  HAL_UART_Receive_IT(&huart2,(uint8_t *)&USART2_NewData,1); //开启串口二的接收中断,用于蓝牙改变电机转速
  HAL_TIM_Base_Start_IT(&htim1);//开启TIM1的定时器中断

  OLED_Init();                           //OLED初始
  OLED_Clear();                         //清屏
  OLED_ShowString(0,0,"Rotational Speed:",12,0);
  OLED_ShowString(50,4,"rad/s",12,0);
    /* USER CODE END 2 */

下面这部分main.c内容是通过蓝牙改变电机转速,与本文的重点>通过STM32编码器模式对直流减速电机测速的讲解关系不大

  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

	  if(USART2_RX_STA&0x8000)           //判断中断接收标志位(蓝牙模块使用USART2)
	  {
    
		 if((USART2_RX_STA&0x7FFF) ==4 	//判断接收数量是不是为四个
				&& USART2_RX_BUF[0]==0xA5 	//判断接收第一个数据是不是包头0xA5
				&& USART2_RX_BUF[3]==(USART2_RX_BUF[1]+USART2_RX_BUF[2])%0x100)	//判断接收校验码是不是原数据之和的低八位

		{
    
			 switch(USART2_RX_BUF[2])      //接收并读取蓝牙发送过来的第三个数,改变车速
			 {
       //ARR的在CubeMX中设置为20000

				 case(0x00):__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1,0);break;    //0%的speed

				 case(0x14):__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1,1440) ;break;//20%

				 case(0x28):__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1,2880) ;break;//40%

				 case(0x3C):__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1,4320);break;//60%

				 case(0x50):__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1,5760);break;//80%

				 case(0x64):__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1,7200);break;//100%

				 default:break;

			 }
		}
		USART2_RX_STA=0;//标志位清0
	  }

	  MOTOR_GO;
  }
  /* USER CODE END 3 */


总结

最终结果就是文章开头视频中显示的,还是测量的比较精准,和电机的参数十分接近,这部分内容对于之后的平衡小车至关重要,因为后续PID控制时要经常读取电机转速来对小车进行闭环控制。

码字不易,希望喜欢的小伙伴别忘了点赞+收藏+关注,你们的肯定就是我创作的动力

欢迎大家积极交流,本文未经允许谢绝转载!!!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/LYH6767/article/details/126310634

智能推荐

linux编译aborted,Ubuntu Linux上编译kernel出错__stack_chk_fail_铭信的博客-程序员宅基地

Ubuntu Linux上编译kernel出错__stack_chk_fail发布时间:2008-02-06 00:02:18来源:红联作者:SMuononinit/built-in.o: In function `try_name':do_mounts.c.text+0x5e3):对‘__stack_chk_fail’未定义的引用init/built-in.o: In function `nam...

Git学习总结(二)nothing added to commit but untracked files present-程序员宅基地

在执行git commit 命令时错误信息显示的是项目的文件没有“add”,需要先执行git add 文件名,然后再执行git commit -m "xxx",

智能驾驶 车牌检测和识别(四)《Android实现车牌检测和识别(可实时车牌识别)》_安卓车牌识别-程序员宅基地

这是项目《智能驾驶 车牌检测和识别》系列之《Android实现车牌检测和识别(可实时车牌识别)》;本项目将开发一个Android版本的车牌检测和识别APP;Android车牌检测,Android车牌识别,Android车牌检测和识别_安卓车牌识别

迅雷下载portal.php,迅雷:『已将宽带从 1000M 降速到 200M,请尽情享用』-程序员宅基地

问题上周把家里的网络从 200M 升级到 1000M,因为之前家里的猫已经是千兆猫,安装师傅说局端已经设置了 1000M,让晚上回去测试一下。晚上回家测试,发现网速只有 200M,难道是局端没有设置成功?上电信官网查看发现签约速度的确已经是 1000M。UBNT USG 背锅重启网关(UBNT USG),发现网关刚重启后网速可达 500+,稍后等几分钟会跌落到 200M。嗯,一定是网关的锅,于是查...

CustomCountDownTimer解决计时不准问题-程序员宅基地

项目中使用到了倒计时,在git上找到了https://github.com/iwgang/CountdownView。但是发现在项目中使用的时候出现倒计时不准的问题,后来自己在原来基础上进行了改写,除去了代码中SystemClock.elapsedRealtime();不会出现倒计时不准的问题。public abstract class CustomCountDownTimer { p...

台式计算机怎么安装无线网卡,台式机无线网卡怎么用 台式机USB无线网卡安装使用教程..._张清北的博客-程序员宅基地

最近有小编台式机USB无线网卡怎么用啊?为什么将无线网卡插入电脑后,依然无法使用呢?对于此问题,小编本文将为大家带来详细的USB无线网卡安装使用教程。USB无线网卡安装使用步骤一如上图,在电脑设备管理器中的网络适配器中就可以看到有一个黄色感叹号的设备,这就是我们刚才插入电脑的无线网卡设备,如果没找到新网卡设备,那么请检查无线网卡与电脑的连接以及USB接口是否可用。上图中的无线网卡识别带有黄色感叹号..._台式机无线网卡模块

随便推点

IPv4 与 IPv6 的比较-程序员宅基地

米扑博客分享总结了一篇博客:IPv4 与 IPv6 的比较IPv4地址长度:32位地址数量:2^32(约4×10^9)IPv4 头结构IPv6地址长度:128位地址数量:2^128(约3.4×10^38)IPv6 头结构IPv6 与 IPv4 头部对比IPv4 与 IPv6 的比较描述IPv4IPv6..._::ffff:10.120.78.40

html中id自增长,Sql Server中如何取得刚刚插入的自增长的id值-程序员宅基地

我们知道,许多表的主键id是自增的,那么我们需要拿到插入过后那个插入的那条记录的id怎么办?我们先看网上这样一种办法:测试:1.新建一个表TBLINDEDITYCREATE TABLE [TBLINDEDITY] ([id] [int] IDENTITY (1, 1) NOT NULL ,[name] [char] (10) COLLATE Chinese_PRC_CI_AS NULL) ON ..._html sql 自增长

scala算子综合案例(二)----- 平均温度的多种实现_头歌scala算子综合案例-程序员宅基地

版权声明:本文为博主原创文章,未经博主允许不得转载!!欢迎访问:https://blog.csdn.net/qq_21439395/article/details/81023400交流QQ: 824203453 给定数据,城市和温度的数据, 求每个城市的平均温度值。数据如下:val d1 = Array(("bj", 28.1), ("sh", 28.7), ..._头歌scala算子综合案例

model中联合唯一unique_together-程序员宅基地

作用在Django model中会对一张表的几个字段进行联合约束和联合索引,例如在购物车表中,登录的用户和商品两个字段在一起表示唯一记录。用法建立联合约束:unique_together = ("user", "goods")建立联合索引:index_together = ("user", "goods")联合约束和联合索引的作用联合约束作用:意思为在这个表中,每一行的us..._unique_together

15年蓝桥杯第7题-程序员宅基地

题意:小明被劫持到X赌城,被迫与其他3人玩牌。 一副扑克牌(去掉大小王牌,共52张),均匀发给4个人,每个人13张。这时,小明脑子里突然冒出一个问题: 如果不考虑花色,只考虑点数,也不考虑自己得到的牌的先后顺序,自己手里能拿到的初始牌型组合一共有多少种呢? 请填写该整数,不要填写任何多余的内容或说明文字。 思路:这么机智的深搜当然不是我想出来的啊。dfs(a, b),a是当前牌的..._将扑克牌发给四个人,不考虑花色,只考虑点数

从0到1搭建精品电商项目(用于毕设、简历等)—— 项目介绍与初步搭建(1)_java电商项目简历_小王曾是少年的博客-程序员宅基地

文章目录1 设计与准备工作1.1 概述1.2 技术栈1.3 项目拆分与聚合1 设计与准备工作1.1 概述  不少的同学在正式找工作前肯定都接触过了Java著名的SSM框架,当然SpringBoot和SpringCloud相信很多人也都了解过,前一段时间我抽空完完整整的完成了一个基于这些主流技术的“项目”,并且体验了一把将项目部署到云服务器上,从此调试不再是localhost了而是我自己的域名,对于现阶段来讲确实是一件很酷的事情,幸运的是在完成的过程中我完整的保留了每一步开发的笔记,现做整理如下,希望可_java电商项目简历

推荐文章

热门文章

相关标签