赞
踩
小车怎么通过读取编码器数值计算车轮速度?
编码器固定在车轮上,随车轮转动而产生脉冲信号。每转动一定角度,编码器输出一定数量的脉冲。通过测量一定时间内编码器产生的脉冲数量,可以得到车轮的转速。
不同的车型或安装方式可能会导致编码器读数的正负方向不同。因此,需要根据小车的具体情况,调整编码器数值的极性,以确保计算出的速度方向正确。
将编码器的脉冲数转换为车轮的旋转角度或转速。通常,编码器的规格会说明每转一圈对应的脉冲数,通过这个信息可以计算车轮的转速。
这里转速的计算为M法(频率测量法):这种方法是在一个固定的定时时间内(以秒为单位),统计这段时间的编码器脉冲数,计算速度值。设编码器单圈总脉冲数为C(编码器精度,编码器精度通常指的是编码器每转一圈产生的脉冲数), 在时间T0内,统计到的编码器脉冲数为M0,则转速n的计算公式为:
转轴转速 = 单位时间内的计数值 / 编码器总分辨率
如果是减速电机
输出轴转速 = 转轴转速 / 减速比
最后,根据车轮的直径或周长,可以将车轮的转速转换为车轮的线速度,也就是车轮的移动速度。速度的计算公式为:速度 = 转速 × 车轮周长。其中,车轮周长 = π × 车轮直径。
具体到代码实现中,首先通过读取编码器的函数(如Read_Encoder()
)获取各个车轮的编码器原始数据。然后,根据小车的型号和安装方式,适当调整数值的极性。最后,利用控制频率(CONTROL_FREQUENCY
)、车轮周长(Wheel_perimeter
)和编码器精度(Encoder_precision
)来计算每个车轮的速度。
MOTOR_A.Encoder=Encoder_A_pr*CONTROL_FREQUENCY*Wheel_perimeter/Encoder_precision;
这里Encoder_A_pr是测量得到的脉冲数,CONTROL_FREQUENCY=100(这里是因为读取脉冲数的时间为10ms读取一次,所以需要将10ms得到的脉冲数*100得到1s内的脉冲数),Wheel_perimeter是车辆轮子的周长,Encoder_precision是编码器倍频后的总分辨率(实际是编码器总分辨率 *减速比)
- void Balance_task(void *pvParameters)
- {
- u32 lastWakeTime = getSysTickCnt();
- while(1)
- {
- // This task runs at a frequency of 100Hz (10ms control once)
- //此任务以100Hz的频率运行(10ms控制一次)
- vTaskDelayUntil(&lastWakeTime, F2T(RATE_100_HZ));
-
- //Get the encoder data, that is, the real time wheel speed,
- //and convert to transposition international units
- //获取编码器数据,即车轮实时速度,并转换位国际单位
- Get_Velocity_Form_Encoder();
-
- .....
-
- }
- }
- void Get_Velocity_Form_Encoder(void)
- {
- //Retrieves the original data of the encoder
- //获取编码器的原始数据
- float Encoder_A_pr,Encoder_B_pr,Encoder_C_pr,Encoder_D_pr;
- OriginalEncoder.A=Read_Encoder(2);
- OriginalEncoder.B=Read_Encoder(3);
- OriginalEncoder.C=Read_Encoder(4);
- OriginalEncoder.D=Read_Encoder(5);
-
- //Decide the encoder numerical polarity according to different car models
- //根据不同小车型号决定编码器数值极性
- switch(Car_Mode)
- {
- case Mec_Car: Encoder_A_pr=-OriginalEncoder.A; Encoder_B_pr=-OriginalEncoder.B; Encoder_C_pr= OriginalEncoder.C; Encoder_D_pr= OriginalEncoder.D; break;
- case Omni_Car: Encoder_A_pr= OriginalEncoder.A; Encoder_B_pr= OriginalEncoder.B; Encoder_C_pr= OriginalEncoder.C; Encoder_D_pr= OriginalEncoder.D; break;
- case Akm_Car: Encoder_A_pr=-OriginalEncoder.A; Encoder_B_pr= OriginalEncoder.B; Encoder_C_pr= OriginalEncoder.C; Encoder_D_pr= OriginalEncoder.D; break;
- case Diff_Car: Encoder_A_pr=-OriginalEncoder.A; Encoder_B_pr= OriginalEncoder.B; Encoder_C_pr= OriginalEncoder.C; Encoder_D_pr= OriginalEncoder.D; break;
- case FourWheel_Car: Encoder_A_pr=-OriginalEncoder.A; Encoder_B_pr=-OriginalEncoder.B; Encoder_C_pr= OriginalEncoder.C; Encoder_D_pr= OriginalEncoder.D; break;
- case Tank_Car: Encoder_A_pr=-OriginalEncoder.A; Encoder_B_pr= OriginalEncoder.B; Encoder_C_pr= OriginalEncoder.C; Encoder_D_pr= OriginalEncoder.D; break;
- }
-
- //The encoder converts the raw data to wheel speed in m/s
- //编码器原始数据转换为车轮速度,单位m/s
- MOTOR_A.Encoder= Encoder_A_pr*CONTROL_FREQUENCY*Wheel_perimeter/Encoder_precision;
- MOTOR_B.Encoder= Encoder_B_pr*CONTROL_FREQUENCY*Wheel_perimeter/Encoder_precision;
- MOTOR_C.Encoder= Encoder_C_pr*CONTROL_FREQUENCY*Wheel_perimeter/Encoder_precision;
- MOTOR_D.Encoder= Encoder_D_pr*CONTROL_FREQUENCY*Wheel_perimeter/Encoder_precision;
- }
- //Encoder data reading frequency
- //编码器数据读取频率
- #define CONTROL_FREQUENCY 100
-
- //The encoder octave depends on the encoder initialization Settings
- //编码器倍频数,取决于编码器初始化设置
- #define EncoderMultiples 4
-
-
- //Black tire, tank_car wheel diameter
- //黑色轮胎、履带车轮直径
- #define Black_WheelDiameter 0.065
- //#define Tank_WheelDiameter 0.047
- #define Tank_WheelDiameter 0.043
-
- //Motor_gear_ratio
- //电机减速比
- #define HALL_30F 30
-
-
- //Number_of_encoder_lines
- //编码器精度
- #define Photoelectric_500 500
由于
Encoder_precision=EncoderMultiples*Robot_Parament.EncoderAccuracy*Robot_Parament.GearRatio;
结合上面参数可以知道Encoder_precision=4*500*30((经过倍频后的总分辨率)编码器精度=编码器倍频数*(物理)编码器精度(这里应该是码盘上透光线槽的数目其实就等于分辨率,也叫多少线,较为常见的有5-6000 线)*电机减速比)
经过倍频后的总分辨率)编码器精度=编码器倍频数*(物理)编码器精度(这里应该是码盘上透光线槽的数目其实就等于分辨率,也叫多少线,较为常见的有5-6000 线)。但是这里把电机的减速比也加入进来,其实是由
转轴转速 = 单位时间内的计数值 / 编码器总分辨率
输出轴转速 = 转轴转速 / 减速比
输出轴转速=单位时间内的计数值 / (编码器总分辨率 *减速比)
- void Robot_Select(void)
- {
- //The ADC value is variable in segments, depending on the number of car models. Currently there are 6 car models, CAR_NUMBER=6
- //ADC值分段变量,取决于小车型号数量,目前有6种小车型号,CAR_NUMBER=6
- Divisor_Mode=2048/CAR_NUMBER+5;
- Car_Mode=(int) ((Get_adc_Average(Potentiometer,10))/Divisor_Mode); //Collect the pin information of potentiometer //采集电位器引脚信息
- if(Car_Mode>5)Car_Mode=5;
-
- switch(Car_Mode)
- {
- case Mec_Car: Robot_Init(MEC_wheelspacing, MEC_axlespacing, 0, HALL_30F, Photoelectric_500, Mecanum_75); break; //麦克纳姆轮小车
- case Omni_Car: Robot_Init(0, 0, Omni_Turn_Radiaus_109, HALL_30F, Photoelectric_500, FullDirecion_60); break; //全向轮小车
- case Akm_Car: Robot_Init(Akm_wheelspacing, Akm_axlespacing, 0, HALL_30F, Photoelectric_500, Black_WheelDiameter); break; //阿克曼小车
- case Diff_Car: Robot_Init(Diff_wheelSpacing, 0, 0, HALL_30F, Photoelectric_500, Black_WheelDiameter); break; //两轮差速小车
- case FourWheel_Car: Robot_Init(Four_Mortor_wheelSpacing, Four_Mortor_axlespacing, 0, HALL_30F, Photoelectric_500, Black_WheelDiameter); break; //四驱车
- case Tank_Car: Robot_Init(Tank_wheelSpacing, 0, 0, HALL_30F, Photoelectric_500, Tank_WheelDiameter); break; //履带车
- }
-
-
- //Check the parameters//自检相关参数
- switch(Car_Mode)
- {
- case Mec_Car: CheckPhrase1=8, CheckPhrase2=14; break; //麦克纳姆轮小车
- case Omni_Car: CheckPhrase1=6, CheckPhrase2=10; break; //全向轮小车
- case Akm_Car: CheckPhrase1=4, CheckPhrase2=7; break; //阿克曼小车
- case Diff_Car: CheckPhrase1=4, CheckPhrase2=7; break; //两轮差速小车
- case FourWheel_Car: CheckPhrase1=8, CheckPhrase2=11; break; //四驱车
- case Tank_Car: CheckPhrase1=4, CheckPhrase2=7; break; //履带车
- }
- }
-
-
- void Robot_Init(double wheelspacing, float axlespacing, float omni_turn_radiaus, float gearratio,float Accuracy,float tyre_diameter)
- {
-
- ....
-
- //motor_gear_ratio
- //电机减速比
- Robot_Parament.GearRatio=gearratio;
- //Number_of_encoder_lines
- //编码器精度(编码器线数)
- Robot_Parament.EncoderAccuracy=Accuracy;
- //Encoder value corresponding to 1 turn of motor (wheel)
- //电机(车轮)转1圈对应的编码器数值
- Encoder_precision=EncoderMultiples*Robot_Parament.EncoderAccuracy*Robot_Parament.GearRatio;
-
- ...
-
- }
车轮周长=pi*车轮直径
- void Robot_Init(double wheelspacing, float axlespacing, float omni_turn_radiaus, float gearratio,float Accuracy,float tyre_diameter) //
- {
-
- //Diameter of driving wheel
- //主动轮直径
- Robot_Parament.WheelDiameter=tyre_diameter;
-
-
- //Driving wheel circumference
- //主动轮周长
- Wheel_perimeter=Robot_Parament.WheelDiameter*PI;
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。