当前位置:   article > 正文

关于编码器测速的问题总结_编码器的极对数旋转一圈多少个脉冲

编码器的极对数旋转一圈多少个脉冲

最近接触到的问题用到编码器,所以还是学了一段时间这方面的知识,如果有问题欢迎各位朋友指教:
   所用的的器件为:
    STM32F407系列,电机型号为JGB37-520(带有霍尔编码器),电池为飞行电池,尤其要吐槽飞行电池的大电流烧了我几个LM298N电机驱动器,后面改成大功率驱动器。

    首先基本东西介绍:

  1. JBGB37-520是AB项的减速电机,每个编码器至少要用两个定时器。(关于ABZ的自行找资料)
    给出编码器原理:编码器原理

  2. 编码器的分类:
       按工作原理:光电式、磁电式和触点电刷式
       按码盘的刻孔方式:增量式和绝对式两类
       由于博主接触面还不是很广,一共就用过两个种类的编码器,都是属于光电编码器和霍尔编码器:一般由6线差分A+ A- B+ B- VCC 和GND;正交编码器:一般是5根线连接,信号线分别为A B Z VCC和GND
       编码器线数: 就是旋转一圈你的A(B)会输出多少个脉冲 ,这里的A B就是上面的输出脉冲信号线,它们转一圈发出的脉冲数一样的,不过存在90°相位差 通常都是360线的 线数越高代表编码器能够反应的位置精度越高

  3. 给出我在课题中用的电机参数
    电机参数
    霍尔编码器的基础原理1
    线速:线速度??? 基础脉冲11*减速比 我的理解是算出线速度然后除以减速比10,
    磁环触发极数: 我的理解是上边有个圆盘,里面有11个磁极,AB有两极所以22对极,参考图中给出的霍尔传感器原理。
    电机旋转一圈产生11个脉冲: what ’s the fuck ???是单极产生11个脉冲,还是两极一共产生11个脉冲,单片机的双边极性采集得到22或者44个脉冲!这就让我很迷,问过淘宝客服,他们也说不清白,简直了。刚开始计数计数清零,然后手动采集10多组旋转一圈的脉冲数值,发现脉冲数在214呈现正态分布,所以我最终取旋转一圈产生214个脉冲。
    后语:写到这214与22成10倍(减速比为10),这难道是巧合???希望有人解答。

  4. 关于F407定时器重装载值的的选取问题,这里我就比较迷,到目前为止看到了三种:
    (1)基于光电编码器:这里给出参考(光电编码器历程),之前看过一篇对原理介绍的更详细的博客,没有收藏。 拿360个栅格的光栅(线数)来举例子,一度一个光栅。因此AB两极,且程序通常又是双边采集,因此一个栅格会产生四个脉冲,360个栅格会产生360x4个脉冲,因此通常会写成:360x4-1,这样做的好处对求旋转的角度很方便:即编码器的旋转角度直接等于采集到的脉冲数除以4得到角度,然后微分得到角速度,然后由减速比得到车轮线速度(正比关系)。
    (2)基于霍尔编码器:参考这篇(霍尔编码器教程),也谢谢这位博客主给出了思路,我也是按照他的方法进行的测试,首先明确定时器计数器的最大计数值0XFFFF,这样才不会溢出,然后直接给到最大,我也是采用这种方式。(后面,发现其实也用不到那么多计数值)这位博客主给出的“齿数比”我也不知道怎么求,百度感觉就是减速比,但是与他的文章不符合,也问过淘宝客服,结果了无音讯———知道的朋友希望留言告知,哈哈!

        给出详细细节,也可以参考给出的博客主:F407的定时器描述
    编码器的总线位置
    (3)基于STM32CUEMX:目前用这个软件用来统计端口和查询端口,之前也研究过一段时间,会一点点,不过还是习惯于自己调库。给出这位博客主的博文:STM32CUBEMX的使用介绍,并没有介绍的很详细,只是串口输出的数据对我有启发。

  5. 代码部分:
       代码属于原来工程的下面的一部分,需要同时对车速度进行控制,所以对四个车轮的属性进行了采集,进行反馈,也利于后面换装麦克纳姆轮。代码有点乱,仅供参考

#include "encoder.h"
#include "sys.h"

 //使用的定时器
 //TIM1 3 4 8
void encoder_Init(void)
{
    GPIO_InitTypeDef         GPIO_InitStructure; 
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_ICInitTypeDef        TIM_ICInitStructure;
 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//开启TIM4时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);//开启GPIOB时钟
	
	  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//开启TIM3时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//开启GPIOB时钟
	
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);//开启TIM3时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);//开启GPIOB时钟
	
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8,ENABLE);//开启TIM3时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);//开启GPIOB时钟
  
    GPIO_PinAFConfig(GPIOD,GPIO_PinSource12,GPIO_AF_TIM4);//PB0引脚复用
    GPIO_PinAFConfig(GPIOD,GPIO_PinSource13,GPIO_AF_TIM4);//PB1引脚服用
	
	  GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_TIM3);//PB0引脚复用
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_TIM3);//PB1引脚服用
	
	  GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_TIM1);//PB0引脚复用
    GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_TIM1);//PB1引脚服用
		
		GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_TIM8);//PB0引脚复用
    GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_TIM8);//PB1引脚服用
  /*--------------------------------------------------------------*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13; //GPIOD12,GPIOD13
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP ;
    GPIO_Init(GPIOD,&GPIO_InitStructure); 
		
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //GPIOB0,GPIOB1
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP ;
    GPIO_Init(GPIOA,&GPIO_InitStructure); 
		
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_11; //GPIOB0,GPIOB1
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP ;
    GPIO_Init(GPIOE,&GPIO_InitStructure); 
		
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //GPIOB0,GPIOB1
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP ;
    GPIO_Init(GPIOC,&GPIO_InitStructure); 

  /*--------------------------------------------------------------*/
	
    TIM_TimeBaseStructure.TIM_Period = 65535; //设置下一个更新事件装入活动的自动重装载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler = 0; //设置用来作为TIMx时钟频率除数的预分频值  不分频
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); 
 
    TIM_TimeBaseStructure.TIM_Period =65535; //设置下一个更新事件装入活动的自动重装载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler = 0; //设置用来作为TIMx时钟频率除数的预分频值  不分频
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); 
 
    TIM_TimeBaseStructure.TIM_Period =65535; //设置下一个更新事件装入活动的自动重装载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler = 0; //设置用来作为TIMx时钟频率除数的预分频值  不分频
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); 
		
		TIM_TimeBaseStructure.TIM_Period = 65535; //设置下一个更新事件装入活动的自动重装载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler = 0; //设置用来作为TIMx时钟频率除数的预分频值  不分频
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);
/*--------------------------------------------------------------*/
    TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12,TIM_ICPolarity_BothEdge,TIM_ICPolarity_BothEdge);
    TIM_ICStructInit(&TIM_ICInitStructure);
    TIM_ICInitStructure.TIM_ICFilter = 10;  //输入滤波器
    TIM_ICInit(TIM4, &TIM_ICInitStructure);
    TIM_ClearFlag(TIM4, TIM_FLAG_Update);  //清楚所有标志位
    TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE); //允许中断更新
    TIM4->CNT = 0;
    TIM_Cmd(TIM4, ENABLE);  //使能TIM3
		
		TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12,TIM_ICPolarity_BothEdge,TIM_ICPolarity_BothEdge);
    TIM_ICStructInit(&TIM_ICInitStructure);
    TIM_ICInitStructure.TIM_ICFilter = 10;  //输入滤波器
    TIM_ICInit(TIM3, &TIM_ICInitStructure);
    TIM_ClearFlag(TIM3, TIM_FLAG_Update);  //清楚所有标志位
    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); //允许中断更新
    TIM3->CNT = 0;
    TIM_Cmd(TIM3, ENABLE);  //使能TIM3
		
		TIM_EncoderInterfaceConfig(TIM1, TIM_EncoderMode_TI12,TIM_ICPolarity_BothEdge,TIM_ICPolarity_BothEdge);
    TIM_ICStructInit(&TIM_ICInitStructure);
    TIM_ICInitStructure.TIM_ICFilter = 10;  //输入滤波器
    TIM_ICInit(TIM1, &TIM_ICInitStructure);
    TIM_ClearFlag(TIM1, TIM_FLAG_Update);  //清楚所有标志位
    TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); //允许中断更新
    TIM1->CNT = 0;
    TIM_Cmd(TIM1, ENABLE);  //使能TIM3
		
		TIM_EncoderInterfaceConfig(TIM8, TIM_EncoderMode_TI12,TIM_ICPolarity_BothEdge,TIM_ICPolarity_BothEdge);
    TIM_ICStructInit(&TIM_ICInitStructure);
    TIM_ICInitStructure.TIM_ICFilter = 10;  //输入滤波器
    TIM_ICInit(TIM8, &TIM_ICInitStructure);
    TIM_ClearFlag(TIM8, TIM_FLAG_Update);  //清楚所有标志位
    TIM_ITConfig(TIM8, TIM_IT_Update, ENABLE); //允许中断更新
    TIM8->CNT = 0;
    TIM_Cmd(TIM8, ENABLE);  //使能TIM3
}


_EncoderStructure EncoderStructure;
void Read_Encoder(void)
{
int i;

	 EncoderStructure.Encoder_Value[0]=TIM1 -> CNT;	  //正数
	 EncoderStructure.Encoder_Value[1]=TIM3 -> CNT;	
	 EncoderStructure.Encoder_Value[2]=TIM4 -> CNT;	
	 EncoderStructure.Encoder_Value[3]=TIM8 -> CNT;
//清零
	TIM1 -> CNT=0;TIM3 -> CNT=0;
	TIM4 -> CNT=0;TIM8 -> CNT=0;
	
	for(i=0;i<=3;i++)
	{
		if(EncoderStructure.Encoder_Value[i]>6000)
		{
		  EncoderStructure.Encoder_Value[i]=EncoderStructure.Encoder_Value[i]-65535;  //负数
		}
	}
  // 屏蔽小波动
	for(i=0;i<=3;i++)
	{
		if(EncoderStructure.Encoder_Value[i]<=2&&EncoderStructure.Encoder_Value[i]>=-2)
		{EncoderStructure.Encoder_Value[i]=0;
		}
	}
}


 _WheelStructure  WheelStructure;

//10ms中断一次然后测速
//计数CNT  单项极对数为11对,产生11个脉冲 ,两个对极,双边检测,因此单旋转一圈产生44个脉冲
//实际测量旋转一圈旋转的脉冲数为
//217 214 216 214 214 215 214 212 212 218 取众数214


#define Dt_10ms 1e-3
void EnANWh_Velocity(void)
{
	u8 i;
  //读取编码器的值
	EncoderStructure.Encoder_Value[0]=TIM1 -> CNT; 
	EncoderStructure.Encoder_Value[1]=TIM3 -> CNT;
	EncoderStructure.Encoder_Value[2]=TIM4 -> CNT;
	EncoderStructure.Encoder_Value[3]=TIM8 -> CNT;
	
	//大端取反得负数
	for(i=0;i<=3;i++)
		{
			if(EncoderStructure.Encoder_Value[i]>6000)
			{
				EncoderStructure.Encoder_Value[i]=EncoderStructure.Encoder_Value[i]-65535;  
			}
		}	
	
	//清零
	TIM1 -> CNT=0;TIM3 -> CNT=0;
	TIM4 -> CNT=0;TIM8 -> CNT=0;
	
	// 屏蔽小波动
	for(i=0;i<=3;i++)
	{
		if(EncoderStructure.Encoder_Value[i]<=2&&EncoderStructure.Encoder_Value[i]>=-2)
		{
			EncoderStructure.Encoder_Value[i]=0;	
		}
	}
	
	
	//得到旋转的圈数
		for(i=0;i<=3;i++)
	{
	EncoderStructure.Motor_CylNum[i]=EncoderStructure.Encoder_Value[i]/214;
	
	//得到电机的角速度,车轮的角速度,减速比为10
  EncoderStructure.Motor_angVel[i]=EncoderStructure.Motor_CylNum[i]*200*pai; //单位(rad/s) 
  WheelStructure.Wheel_angVel[i]=EncoderStructure.Motor_angVel[i]/10	;	
	
  //得到车轮的线速度
  WheelStructure.Wheel_linVel[i]=WheelStructure.Wheel_angVel[i]*WheelStructure.wheel_R;
		
	//得到车轮的行驶距离
WheelStructure.Wheel_distance[i]=WheelStructure.wheel_perimeter*EncoderStructure.Motor_CylNum[i]/10;
	}
	
}

低通滤波器
//float L_filter(float value,float a)
//{
//	static float Last_value;
//	value=Last_value*(256-a)/256+a*value/256;
//	Last_value=value;
//	return value;
//}

#define TIM9_arr 839
#define TIM9_psc 999
//得到快关频率 100hz

//车轮速度专用解算定时器
//10ms中断一次

void TIM9_EnAnWh_Vel(void)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9,ENABLE);  ///使能TIM2时钟
	
  TIM_TimeBaseInitStructure.TIM_Period = TIM9_arr; 	//自动重装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler=TIM9_psc;  //定时器分频
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; 

	TIM_TimeBaseInit(TIM9,&TIM_TimeBaseInitStructure);//初始化TIM7
	
	TIM_ITConfig(TIM9,TIM_IT_Update,ENABLE); //允许定时器2更新中断
	TIM_Cmd(TIM9,ENABLE); //使能定时器9
	
	NVIC_InitStructure.NVIC_IRQChannel=TIM1_BRK_TIM9_IRQn; //定时器2中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=2; //子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
}

s16 TIM9_flag;
void  TIM1_BRK_TIM9_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM9,TIM_IT_Update)!=RESET)
    {  
			
			  EnANWh_Velocity();
			
		
			
       TIM_ClearITPendingBit(TIM9,TIM_IT_Update); 
		}
}



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273

测得的数据如下:
测得数据
差不多就这吧!

V12/12

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/966124
推荐阅读
相关标签
  

闽ICP备14008679号