模块学习笔记—(1)编码器减速电机

2023-11-17

模块学习笔记—(1)编码器减速电机

编码器电机作用

编码器电机转动可以产生脉冲信号,根据脉冲信号,可以得出轮胎的转动速度、轮胎的位移,电机正反转等。

电机介绍

我的编码器电机是130TT减速电机,电机轴转一圈可以产生13个脉冲信号输出,电机减速比为1:120,所以减速电机的输出轴旋转一圈,实际可以产生的脉冲为13*120=1560个。在通过STM32F4编码器接口的4倍频就是6240个脉冲也即是轮子转一圈会有6240个脉冲。(4倍频就是一个脉冲可以被检测到4次,增大脉冲的检测精度)

在这里插入图片描述

测速实现方案

第一种测速方案是计算一定脉冲下所用时间来得出电机速度
第二种测速方案是是一定时间下所产生的脉冲数量来计算。这里选择第二种。

1.捕获脉冲:

使用一个定时器TIM4的编码器模式接收电机编码器的脉冲,另一个定时器TIM3负责在一定时间的读取编码器脉冲的值。这样,就可以得出一定时间下的电机的脉冲数了。我这里取100ms取值一次。

2. 脉冲处理:

那么知道了一定时间下的电机的脉冲数怎么可以测到电机的速度呢?这里我们已经知道了减速电机的输出轴旋转一圈会产生1560个脉冲,四倍频就是6240个,所以可以根据比例来求出轮子的位移(事先用尺子测出轮子一周的长度,比如说100ms有2000个脉冲,那么2000除6240得到比例,再用这个比例乘以轮子的长度求出位移,然后这是在100ms下走的路程,最后用位移除以时间100ms就可以得到电机的速度啦

3.代码实现(STM32F407)

TIM4(脉冲计数),TIM3(时间计数)初始化

#include "sys.h"
#include "delay.h"
#include "led.h"
#include "usart.h"
	u32 mcs;
	float cnt,cnts,speed;
  int g;
void TIM3_Int_Init(u16 arr,u16 psc)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  ///使能TIM3时钟
	
  TIM_TimeBaseInitStructure.TIM_Period = arr; 	//自动重装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  //定时器分频
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
	
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
	
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许定时器3更新中断
	TIM_Cmd(TIM3,ENABLE); //使能定时器3
	
	NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x00; //抢占优先级1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
}

void Encoder_Init_TIM4(void)
{
     GPIO_InitTypeDef         GPIO_InitStructure; 
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_ICInitTypeDef TIM_ICInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); 
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);//开启GPIOB时钟
  
    GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_TIM4);//PB6引脚复用
    GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_TIM4);//PB7引脚服用
	
	  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //GPIOB6,GPIOB7
	  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    //GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL ;
	  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_Init(GPIOB,&GPIO_InitStructure); 

//定时器设置-------------------------------------------------------------  
  
  TIM_TimeBaseInitStructure.TIM_Period = 60000;  //重装载值
    TIM_TimeBaseInitStructure.TIM_Prescaler=0x0;  //预分频
    TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数
    TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //时钟分割

    TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);//初始化TIM3

//编码器模式设置--------------------------------------------------------------                 

    TIM_EncoderInterfaceConfig(TIM4,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//计数模式3

    TIM_ICStructInit(&TIM_ICInitStructure); 
    TIM_ICInitStructure.TIM_ICFilter = 10;//滤波器值
    TIM_ICInit(TIM4, &TIM_ICInitStructure);
//溢出中断设置--------------------------------------------------------------  
    TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); //允许TIM3溢出中断

    NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn; 
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; 
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x01; 
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_InitStructure);

 //Reset counter-----------------------------------------------
  TIM_SetCounter(TIM4,0); //TIM3->CNT=0
  TIM_Cmd(TIM4, ENABLE); 


}

void TIM4_IRQHandler(void)
{
		if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET)//溢出中断
	{
	//这里为空,不需要处理    				   				     	    	
	}				   
	TIM_ClearITPendingBit(TIM4,TIM_IT_Update);  //清除中断标志位
}

//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
	

	 cnt=TIM_GetCounter(TIM4);
	TIM_SetCounter(TIM4,0);
	TIM_SetCounter(TIM3,0);
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
	{
		
 LED1=!LED1;//DS1翻转
	g=1;
	}	
	
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
	TIM_ClearITPendingBit(TIM4,TIM_IT_Update);  //清除中断标志位
}

下面的是主函数(串口检测数据)

int main(void)
{ 
 
//	u8 t;
//	u8 len;	
//	u16 times=0;

    Encoder_Init_TIM4();
    TIM3_Int_Init(1000,8400);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);		//延时初始化 
	uart_init(115200);	//串口初始化波特率为115200
	LED_Init();		  		//初始化与LED连接的硬件接口  
	En_Init();
    pwm_Init(7200-1,0);
	
		
	while(1)
	{
		
		LED0=!LED0;
		if(g==1)
		{
				if(cnt<30000)
   cnt=cnt/6240;	
        else if(cnt>30000)
		{
		cnt=60000-cnt;
		cnt=cnt/6420;
		}
	 	cnt=0.2*cnt;
		 speed=cnt/0.1;	
			printf("%f\n", cnt);
		    printf(" ");
		    printf("%f\r\n",speed);
			g=0;
		}
		IN1=0;
		IN2=1;
		IN3=1;
		IN4=0;
		TIM_SetCompare3(TIM5,5000);
		TIM_SetCompare4(TIM5,5000);
	//	printf("%d\r\n", mcs);
		
		

	}
}
注意的地方
1

这里有个要注意的地方是定时器中断函数中尽可能短,不要太多代码,而且定时器中断函数中不要用printf函数,可能会造成卡死。因为printf本身就用到中断函数。

2

还有一点是电机正转的话编码器模式是从0开始计数,如果反转的话从设置的重装载开始递减计数,我这里就是从60000开始,如何有2000个脉冲,则计数器CNT的值为58000。为了判断出正反转,我的解决方法是CNT在1至30000为正转,30000~60000为反转(因为我这个项目中100ms内正转不会有30000个脉冲产生)。缺点是都是牺牲数据范围来读取。还有一种办法是读取DIR来判断 但有小概率误判现象。用DIR在极端情况下会出现误判,比如一直处于正反转。

3

TIM4中的中断函数要写出来,不然可能会卡死。当然,也可以禁止TIM4的中断,这样就不需要写中断函数了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

模块学习笔记—(1)编码器减速电机 的相关文章

  • windows系统下ftp上传下载和一些常用命令

    windows系统下ftp上传下载和一些常用命令 先假设一个ftp地址 用户名 密码 FTP Server home4u at china com User yepanghuang Password abc123 打开windows的开始菜
  • Android动画系列之帧动画详解

    Android动画系列之帧动画详解 官方文档链接 Animate drawable 简介 逐帧动画就是一个接一个地加载一系列可绘制的资源来创建一个动画 这是一种传统的动画 从某种意义上说 它是由一系列不同的图像组成的 按照顺序播放 就像一卷
  • Fiddler抓包教程 ---> Fiddler如何证书配置与开启抓包完整详解

    一 安装fiddler和配置证书 fiddler默认是只抓取http协议 如下图 如果会话列表中的Host列中出现Tunnel to 字样都说明是证书的问题 这种就不能抓取到我们想要的会话 要想抓https协议 需要配置一下 操作方法如下
  • 重启:HTML的开始

    HTML 是一种文本标记语言 它的全称是 Hpyter Text Markup Labguage 文档声明 声明当前网页的版本 eg 这里不区分大小写 用于声明文档采用哪个版本的HTML进行编写 这里代表的是html5 注意 声明必须要放在
  • 一文读懂什么是进程、线程、协程

    进程 我们都知道计算机的核心是CPU 它承担了所有的计算任务 而操作系统是计算机的管理者 它负责任务的调度 资源的分配和管理 统领整个计算机硬件 应用程序则是具有某种功能的程序 程序是运行于操作系统之上的 进程是一个具有一定独立功能的程序在
  • fanuc机器人四边形编程_Fanuc焊接机器人编程小例子

    摘要 某个美国专家编的焊接程序 小例子 PROG PIPE 2SS1CC ATTR OWNER MNEDITOR COMMENT START STOP PROG SIZE 8121 CREATE DATE 10 11 25 TIME 14

随机推荐

  • axios vue 加载效果动画_vue+axios+element ui 实现全局loading加载示例

    感兴趣的小伙伴 下面一起跟随512笔记的小编两巴掌来看看吧 实现全局loading加载 分析需求 我们只需要在请求发起的时候开始loading 响应结束的时候关闭loading 就这么简单 对不对 代码如下 import axios fro
  • oa项目经验描述_项目经验和总结

    去年 在一个大型项目 1500w 中用到Web Services 现在项目进入了尾声 所以对以前的开发经历做一个总结 我想大家一定会问 为什么你们项目中要用到Web Services 因为客户有如下需求 1 客户要求项目用C S架构 并且服
  • tomcat开启远程调试

    开启 tomcat 远程调试步骤如下 1 进入 tomcat 的 bin 目录 修改 catalina bat 脚本 添加如下语句 rem 开启远程调试 端口为 8000 SET CATALINA OPTS server Xdebug Xn
  • [1067]CDH6.3.2之Kerberos安全认证

    文章目录 Kerberos简介 Kerberos认证原理 Kerberos部署 Cloudera Manager平台上Kerberos的配置 在做此操作之前 请检查服务器时期是否正常 常用命令 登录Kerberos 创建Kerberos主体
  • 知识蒸馏论文翻译(9)—— Multi-level Knowledge Distillation via Knowledge Alignment and Correlation

    知识蒸馏论文翻译 9 Multi level Knowledge Distillation via Knowledge Alignment and Correlation 基于知识对齐和关联的多层次知识蒸馏 文章目录 知识蒸馏论文翻译 9
  • yum包管理器常见用法

    yum包管理器常见用法 yum源数据结构 yum源配置 yum config manager 快速添加 yum 源 自动寻找最快的yum源 仅支持Centos7 yum生成缓存 yum包管理器常用命令 RHEL8的yum yum软件仓库管理
  • 人脸识别从原理到实践

    目录 一 开箱即用 二 性能基线 三 训练 3 1 训练公开数据 3 2 训练自己的数据 四 视频教程 五 论文解读 引言 Loss 数据集 端上部署 人脸识别是目前深度学习领域应用最为广泛的领域之一 各大框架都有不错的开源项目 本文提供i
  • id注册

    直接在官网选择US就行了 然后就可以登陆
  • 剑指 Offer 07. 重建二叉树

    重建二叉树 思路 在前序遍历中找到根节点的值 然后在中序遍历中根据根节点的值划分左右子树 然后在左右子树里面递归调用同样的代码 再进行划分 package swordPointingToTheOffer import java util H
  • Centos设置nginx开机自启动

    第一步 进入到 lib systemd system 目录 root iz2z init d cd lib systemd system 第二步 创建nginx service文件 并编辑 vim nginx service 内如如下 Un
  • 抖音小程序实践四:实现小程序分享

    有时候我们要把一个小程序分享给别人 去看套餐 买东西之类的 是一个很常见的功能 但是在接入抖音小程序的时候 初始化右上角三个点并没有分享的入口 那看来不是要申请 就是有别的开发的口子了 下面我们一起了解下 从一个菜鸟的角度 我登录开发者后台
  • android 取消点击监听,Android中的活动中的软键盘打开和关闭监听...

    这仅适用于android 您的活动的windowSoftInputMode在清单中设置为adjustResize 您可以使用布局侦听器来查看键盘是否调整了活动的根布局 我为我的活动使用类似下面的基类 public class BaseAct
  • JetBrains :IDEA入门与使用技巧分享

    本文假设读者已掌握基础的开发方式 了解常见的概念 只是刚入手IDEA 不熟悉工具的使用方式而已 本文编写于 2019年7月27日 一 准备 以下是本文使用到的工具 工具与环境 IntelliJ IDEA Ultimate 2019 2 各个
  • DNS地址

    阿里云公共dns 223 5 5 5 223 6 6 6 腾讯公共dns 119 29 29 29 微步 拦截版 117 50 11 11 52 80 66 66 纯净版 117 50 10 10 52 80 52 52 360公共dns
  • 顺序表的定义及初始化代码实现(C语言)

    适合初学数据结构 不明白如何通过代码实现顺序表 超简洁代码如下 2020 10 16 第一次修改 顺序表结构定义的data是数组类型 应采用静态分配 模糊了静态分配与动态分配 已修改 错误程序L gt data 10 int malloc
  • 报错Description Resource Path Location Type Lifecycle mapping "org.eclipse.m2e.jdt.JarLifecycleMapping

    我这边是因为eclipse想做spring boot项目 因此想安装STS插件 结果装了几个版本 发现都没用 还导致POM XML文件报错 解决问题 1 卸载STS插件 help Install New Software 点击 what i
  • 一个矩阵乘以它本身的转置等于什么

    如果一个矩阵 A 乘以它本身的转置 AT 那么结果就是一个对角矩阵 对角线上的元素就是 A 矩阵中每一列的平方和 其余的元素都是 0 例如 如果 A 矩阵是 a11 a12 a21 a22 那么 A 乘以 AT 就是 a11 2 a21 2
  • 网道 JS教程 (第一天)

    地址 https wangdoc com javascript js 特点 单线程 事件驱动 非阻塞式设计 数据类型 数值 number 整数和小数 比如1和3 14 字符串 string 文本 比如Hello World 布尔值 bool
  • 关闭或者半关闭?!

    2017 05 20 LIBnids这个库 对于关闭的两个状态 理解的不是很清楚 就是 CLOSE算一个状态 CLOSE之前并不调用EXITING的语句 这就很尴尬 目前就当这两个是同一个状态 但是看着有些数据包是关闭的 结果显示不关闭 这
  • 模块学习笔记—(1)编码器减速电机

    模块学习笔记 1 编码器减速电机 编码器电机作用 编码器电机转动可以产生脉冲信号 根据脉冲信号 可以得出轮胎的转动速度 轮胎的位移 电机正反转等 电机介绍 我的编码器电机是130TT减速电机 电机轴转一圈可以产生13个脉冲信号输出 电机减速