三、代码实现
encoder.c
/* 此文件为编码器电机闭环调试,包括速度环和位置环
* 配置:TIM2(PA0、PA1):编码器模式
* TIM1-CH1(PE9):PWM输出
* IN1:PF1
* IN2: PF2
* ENABLE: PF0
* 使用方法:1、初始化Motor_Init()
* 2、发送电流SetCurrent()
*/
#include "encoder.h"
encoderMotor_t encoderMoto[ENCODER_MOTO_COUNT]; //编码器电机结构体
pid_t Encoder_Motor_Pid_Pos[ENCODER_MOTO_COUNT]; //编码器电机位置环PID结构体
pid_t Encoder_Motor_Pid_Spd[ENCODER_MOTO_COUNT]; //编码器电机速度环PID结构体
void Motor_Init(void)
{
HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL); //开启编码器定时器
__HAL_TIM_ENABLE_IT(&htim2,TIM_IT_UPDATE); //开启编码器定时器更新中断,防溢出处理
__HAL_TIM_SET_COUNTER(&htim2, 10000); //编码器定时器初始值设定为10000
encoderMoto[0].IOControl.htim_pwm = htim1;
encoderMoto[0].IOControl.IN1_Port = GPIOF;
encoderMoto[0].IOControl.IN2_Port = GPIOF;
encoderMoto[0].IOControl.IN1_Pin = GPIO_PIN_1;
encoderMoto[0].IOControl.IN2_Pin = GPIO_PIN_2;
}
//
/* 编码器电机发送电流函数
* motor:编码器电机参数结构体
* val:转动的速度或角度,SPEED最大为110,POSITION一圈为3960
* mode:模式选择:速度环:SPEED
* 位置环:POSITION
*/
void SetCurrent(encoderMotor_t *motor, int32_t val, uint32_t mode)
{
float pos_output,spd_output;
if(mode == 1)
spd_output = pid_calc(&Encoder_Motor_Pid_Spd[0], motor->speed, val);
else
{
pos_output = pid_calc(&Encoder_Motor_Pid_Pos[0], motor->totalAngle, val);
spd_output = pid_calc(&Encoder_Motor_Pid_Spd[0], motor->speed, pos_output);
}
if(spd_output > 0)
{
HAL_GPIO_WritePin(motor->IOControl.IN1_Port, motor->IOControl.IN1_Pin, GPIO_PIN_SET); //控制正反转
HAL_GPIO_WritePin(motor->IOControl.IN2_Port, motor->IOControl.IN2_Pin, GPIO_PIN_RESET);
__HAL_TIM_SET_COMPARE(&motor->IOControl.htim_pwm, TIM_CHANNEL_1, (uint32_t)(spd_output));
}
else
{
HAL_GPIO_WritePin(motor->IOControl.IN1_Port, motor->IOControl.IN1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(motor->IOControl.IN2_Port, motor->IOControl.IN2_Pin, GPIO_PIN_SET);
__HAL_TIM_SET_COMPARE(&motor->IOControl.htim_pwm, TIM_CHANNEL_1, (uint32_t)(-spd_output));
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static int16_t count = 0;
if(htim->Instance==htim6.Instance) //1ms中断
{
count++;
if(count >= 10)
{
count = 0;
int16_t pluse = COUNTERNUM - RELOADVALUE/2;
encoderMoto[0].totalAngle = pluse + encoderMoto[0].loopNum * RELOADVALUE/2;
encoderMoto[0].speed = (float)(encoderMoto[0].totalAngle - encoderMoto[0].lastAngle)/(4*PLUSE_OF_CIRCLE*RR)*6000; //进行速度计算,根据前文所说的,4倍频,编码器13位,减速比30,再乘以6000即为每分钟输出轴多少转
encoderMoto[0].lastAngle = encoderMoto[0].totalAngle; //更新转过的圈数
}
}
else if(htim->Instance == htim2.Instance) //如果是编码器更新中断,即10ms内,脉冲数超过了计数范围,需要进行处理
{
if(COUNTERNUM < 10000) encoderMoto[0].loopNum++;
else if(COUNTERNUM > 10000) encoderMoto[0].loopNum--;
__HAL_TIM_SetCounter(&htim2, 10000); //重新设定初始值
}
}
|