接线
编码器电机、电机驱动(这里用的L298n)、STM32、电源(可以是12V电池)的接线如下
3.3 代码编写
encoder.h中的内容
#ifndef _ENCODER_H_
#define _ENCODER_H_
#include "stm32f1xx.h"
//电机1的编码器输入引脚
#define MOTO1_ENCODER1_PORT GPIOA
#define MOTO1_ENCODER1_PIN GPIO_PIN_0
#define MOTO1_ENCODER2_PORT GPIOA
#define MOTO1_ENCODER2_PIN GPIO_PIN_1
//定时器号
#define ENCODER_TIM htim2
#define PWM_TIM htim3
#define GAP_TIM htim4
#define MOTOR_SPEED_RERATIO 45u //电机减速比
#define PULSE_PRE_ROUND 11 //一圈多少个脉冲
#define RADIUS_OF_TYRE 34 //轮胎半径,单位毫米
#define LINE_SPEED_C RADIUS_OF_TYRE * 2 * 3.14
#define RELOADVALUE __HAL_TIM_GetAutoreload(&ENCODER_TIM) //获取自动装载值,本例中为20000
#define COUNTERNUM __HAL_TIM_GetCounter(&ENCODER_TIM) //获取编码器定时器中的计数值
typedef struct _Motor
{
int32_t lastCount; //上一次计数值
int32_t totalCount; //总计数值
int16_t overflowNum; //溢出次数
float speed; //电机转速
uint8_t direct; //旋转方向
}Motor;
#endif
encoder.c中的内容
#include "encoder.h"
Motor motor1;
void Motor_Init(void)
{
HAL_TIM_Encoder_Start(&ENCODER_TIM, TIM_CHANNEL_ALL); //开启编码器定时器
__HAL_TIM_ENABLE_IT(&ENCODER_TIM,TIM_IT_UPDATE); //开启编码器定时器更新中断,防溢出处理
HAL_TIM_Base_Start_IT(&GAP_TIM); //开启100ms定时器中断
HAL_TIM_PWM_Start(&PWM_TIM, TIM_CHANNEL_2); //开启PWM
HAL_TIM_PWM_Start(&PWM_TIM, TIM_CHANNEL_1); //开启PWM
__HAL_TIM_SET_COUNTER(&ENCODER_TIM, 10000); //编码器定时器初始值设定为10000
motor1.lastCount = 0; //结构体内容初始化
motor1.totalCount = 0;
motor1.overflowNum = 0;
motor1.speed = 0;
motor1.direct = 0;
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定时器回调函数,用于计算速度
{
if(htim- >Instance==ENCODER_TIM.Instance)//编码器输入定时器溢出中断,用于防溢出
{
if(COUNTERNUM < 10000) motor1.overflowNum++; //如果是向上溢出
else if(COUNTERNUM >= 10000) motor1.overflowNum--; //如果是向下溢出
__HAL_TIM_SetCounter(&ENCODER_TIM, 10000); //重新设定初始值
}
else if(htim- >Instance==GAP_TIM.Instance)//间隔定时器中断,是时候计算速度了
{
motor1.direct = __HAL_TIM_IS_TIM_COUNTING_DOWN(&ENCODER_TIM);//如果向上计数(正转),返回值为0,否则返回值为1
motor1.totalCount = COUNTERNUM + motor1.overflowNum * RELOADVALUE;//一个周期内的总计数值等于目前计数值加上溢出的计数值
motor1.speed = (float)(motor1.totalCount - motor1.totalCount) / (4 * MOTOR_SPEED_RERATIO * PULSE_PRE_ROUND) * 10;//算得每秒多少转
//motor1.speed = (float)(motor1.totalCount - motor1.totalCount) / (4 * MOTOR_SPEED_RERATIO * PULSE_PRE_ROUND) * 10 * LINE_SPEED_C//算得车轮线速度每秒多少毫米
motor1.lastCount = motor1.totalCount; //记录这一次的计数值
}
}
使用时需要在main.c的循环之前调用Motor_Init函数进行初始化。
如果发现无法进入编码器中断导致totalCount经常溢出归零,可以尝试换一种防溢出的方法,代码如下
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定时器回调函数,用于计算速度
{
if(htim- >Instance==GAP_TIM.Instance)//间隔定时器中断,是时候计算速度了
{
motor1.direct = __HAL_TIM_IS_TIM_COUNTING_DOWN(&ENCODER_TIM);//如果向上计数(正转),返回值为0,否则返回值为1
motor1.totalCount = COUNTERNUM_1 + motor1.overflowNum * RELOADVALUE_1;//一个周期内的总计数值等于目前计数值加上溢出的计数值
if(motor1.lastCount - motor1.totalCount > 19000) // 在计数值溢出时进行防溢出处理
{
motor1.overflowNum++;
motor1.totalCount = COUNTERNUM_1 + motor1.overflowNum * RELOADVALUE_1;//一个周期内的总计数值等于目前计数值加上溢出的计数值
}
else if(motor1.totalCount - motor1.lastCount > 19000) // 在计数值溢出时进行防溢出处理
{
motor1.overflowNum--;
motor1.totalCount = COUNTERNUM_1 + motor1.overflowNum * RELOADVALUE_1;//一个周期内的总计数值等于目前计数值加上溢出的计数值
}
motor1.speed = (float)(motor1.totalCount - motor1.lastCount) / (4 * MOTOR_SPEED_RERATIO * PULSE_PRE_ROUND) * 3000;//算得每秒多少转,除以4是因为4倍频
motor1.lastCount = motor1.totalCount; //记录这一次的计数值
}
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。
举报投诉
-
编码器
+关注
关注
45文章
3679浏览量
135399 -
驱动
+关注
关注
12文章
1855浏览量
85742 -
电机
+关注
关注
142文章
9101浏览量
146584 -
STM32
+关注
关注
2274文章
10929浏览量
358009
发布评论请先 登录
相关推荐
AB相编码器-变M/T法测速,10ms定时,测6000转伺服电机!
本帖最后由 SXST_T 于 2017-9-13 12:11 编辑
适用所有线数编码器,此方法主要解决M法测低速分辨率不足,T法测高速分辨率高,
发表于 09-13 12:07
编码器常用测速方法
2.1 倍频技术 编码器会输出两路方波信号,如果只在通道A的上升沿计数,那就是1倍频;通道A的上升、下降沿计数,那就是2倍频;如果在通道A、B的上升、下降沿计数,那就是4倍频。 使用倍频可以最大程度
![<b class='flag-5'>编码器</b>常用<b class='flag-5'>测速</b>方法](https://file1.elecfans.com/web2/M00/AF/4A/wKgZomVN2hyAZn-iAAAkhUYpS60247.jpg)
评论