模块学习笔记

您所在的位置:网站首页 编码器异常什么意思 模块学习笔记

模块学习笔记

2024-07-10 15:09:10| 来源: 网络整理| 查看: 265

模块学习笔记—(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(cnt30000) { 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的中断,这样就不需要写中断函数了。



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭