电机编码器(Encoder)
宏定义
定时器的自动重装载值,不可大于65535 因为F103的定时器是16位的。
#define ENCODER_TIM_PERIOD (u16)(65535)
计算转速需要的参数
#define PI 3.14159265 //PI圆周率
#define Control_Frequency 200.0 //编码器读取频率
#define Diameter_67 67.0 //轮子直径67mm
#define EncoderMultiples 4.0 //编码器倍频数
#define Encoder_precision 11.0 //编码器精度 11线
#define Reduction_Ratio 30.0 //减速比30
#define Perimeter 210.4867 //周长,单位mm
Control_Frequency=200 意味着Read_Encoder()的取值周期为5ms
左右轮的ID
typedef enum {
MOTOR_ID_ML = 0,
MOTOR_ID_MR,
MAX_MOTOR
} Motor_ID;
方法
如果要使用电机Motor, 请确保初始化电机的函数要在初始化编码器定时器的函数之前调用!!
Encoder_Init_TIM3(void)
初始化TIM3定时器
| 设置项目 | 设置值 |
|---|---|
| 预分频器 | 0 |
| 自动重装值 | ENCODER_TIM_PERIOD(具体值需查看代码) |
| 时钟分频 | 不分频 (TIM_CKD_DIV1) |
| 计数模式 | 向上计数 (TIM_CounterMode_Up) |
| 输入捕获滤波 | 10 |
| GPIO引脚 | GPIO_Pin_6 和 GPIO_Pin_7 |
| GPIO模式 | 浮空输入 (GPIO_Mode_IN_FLOATING) |
| 定时器3时钟使能 | 使能定时器3的时钟 |
| PA端口时钟使能 | 使能PA端口时钟 |
| 编码器模式 | 编码器模式3 (TIM_EncoderMode_TI12) |
| 输入捕获极性 | 上升沿触发 (TIM_ICPolarity_Rising) |
| TIM更新标志位清除 | 清除TIM的更新标志位 |
| TIM更新中断使能 | 使能TIM更新中断 |
Encoder_Init_TIM4(void)
初始化TIM4定时器
| 设置项目 | 设置值 |
|---|---|
| 定时器结构体 | TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure |
| 输入捕获结构体 | TIM_ICInitTypeDef TIM_ICInitStructure |
| GPIO初始化结构体 | GPIO_InitTypeDef GPIO_InitStructure |
| 定时器4时钟使能 | 使能定时器4的时钟 (RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE)) |
| PB端口时钟使能 | 使能PB端口时钟 (RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE)) |
| GPIO引脚配置 | GPIO_Pin_6 | GPIO_Pin_7 |
| GPIO模式 | 浮空输入 (GPIO_Mode_IN_FLOATING) |
| GPIO初始化 | 根据设定参数初始化GPIOB (GPIO_Init(GPIOB, &GPIO_InitStructure)) |
| 定时器基础配置初始化 | TIM_TimeBaseStructInit(&TIM_TimeBaseStructure) |
| 预分频器 | 0x0 |
| 计数器自动重装值 | ENCODER_TIM_PERIOD |
| 时钟分频 | 不分频 (TIM_CKD_DIV1) |
| 计数模式 | 向上计数 (TIM_CounterMode_Up) |
| 定时器初始化 | TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure) |
| 编码器接口配置 | 使用编码器模式3 (TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising)) |
| 输入捕获结构体初始化 | TIM_ICStructInit(&TIM_ICInitStructure) |
| 输入捕获滤波 | 10 |
| 输入捕获初始化 | TIM_ICInit(TIM4, &TIM_ICInitStructure) |
| TIM更新标志位清除 | 清除TIM的更新标志位 (TIM_ClearFlag(TIM4, TIM_FLAG_Update)) |
| TIM更新中断使能 | 使能TIM更新中断 (TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE)) |
Read_Encoder(Motor_ID MYTIMX)
单位时间读取编码器计数
Read_Encoder() 读取到的是从上一次调用Read_Encoder()到这一次调用Read_Encoder()这段时间内编码器的计数
为了计算转速, 需要以固定的时间间隔调用Read_Encoder()
| 参数 | 类型 | 注释 |
|---|---|---|
| MYTIMX | Motor_ID | 选择一个电机读取 |
| Motor_ID可选参数 MOTOR_ID_ML/MOTOR_ID_MR | ||
| 返回值 | 类型 |
|---|---|
| 编码器计数 | int |
Get_Velocity_From_Encoder(int encoder_left, int encoder_right);
返回左右轮的转速, 单位为mm/s
此函数默认是以5ms作为测速周期, 对应着宏定义中的 Control_Frequency=200 (T=1/f)
| 参数 | 类型 | 注释 |
|---|---|---|
| encoder_left | int | 左电机编码器值 |
| encoder_right | int | 右电机编码器值 |
| 返回值 | 类型 |
|---|---|
| velocities | float* |
| 返回值为一个速度数组 velocities[0]是左电机速度 velocities[1]是右电机速度, 单位为mm/s | |
TIM3_IRQHandler(void);
定时器3中断处理函数
TIM4_IRQHandler(void);
定时器4中断处理函数
使用示例
// 导入部分代码省略
int main() {
Encoder_Init_TIM3();
Encoder_Init_TIM4();
int left_count = 0;
int right_count = 0;
while(1) {
// 取5ms作为测速周期, 对应着宏定义中的 Control_Frequency=200 (T=1/f)
delay_ms(5);
left_count += Read_Encoder(MOTOR_ID_ML);
right_count += Read_Encoder(MOTOR_ID_MR);
printf("L: %d, R: %d\n", left_count, right_count);
}
return 0;
}