利用STM32HAL库对AB编码器测量位置和速度

使用TIM5和TIM6进行AB相脉冲计数与电机位置与速度测量

一、实验目的

    对AB相脉冲信号计数并测量电机转过的位置和转速。

二、实验内容

2.1 引脚配置

    初始化配置:三件套

    配置TIM5为编码模式,通道一和通道二分别作为AB相脉冲的输入通道。

    编码器线数为2500,四倍频后电机转动一圈编码器发出1000个脉冲。设定计数周期为20000,后面程序中会在计数溢出中断中将计数值设置为10000,则电机正转时,向上计数10000 to 20000循环计数;电机反转时,向下计数10000 to 0循环计数。

    开启TIM5时钟中断,作为计数溢出判断标志。

    配置TIM6作为计时时钟,确定测速的时间间隔。

    设定测速频率为50Hz,fcs = 84M/(840-1)/2000 = 50Hz;开启时钟中断,在中断回调程序中计算速度。

2.2 测量位置和速度程序编写 

    开启TIM5时钟编码模式并使能定时器的更新中断;初始TIM5时钟计数值为10000。启动TIM6定时器并更新中断。

 HAL_TIM_Encoder_Start(&htim5,TIM_CHANNEL_ALL);      // start TIM5 encoder
 __HAL_TIM_ENABLE_IT(&htim5,TIM_IT_UPDATE);           //????????????,?????
 __HAL_TIM_SET_COUNTER(&htim5, 10000);                //????????????10000


HAL_TIM_Base_Start_IT(&htim6);  //20ms update interrupt measure speed

    在TIM5更新中断触发时,判断如果计数值<10000;则向上计数溢出,电机转动圈数加1;反之,电机转动圈数减1。

    在TIM6中断触发时(触发频率为50hz),测定电机转动方向motor1_direct,若direct = 0,则电机顺时针转,若direct = 1,则电机逆时针转;转速 motor1_speed单位rpm;电机转过的位置N:1/10000 r。

uint16_t motor1_speed = 0;
uint16_t motor1_direct = 0;
int motor1_count = 0;
int motor1_lastcount = 0;

int motor1_overflowNum = 0;
uint16_t PULSE_PRE_ROUND = 2500;
int N = 0;           //cycles

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
if(htim->Instance == TIM5)//????????????,?????                   
    {      
        if(TIM5->CNT < 10000) motor1_overflowNum++;       //???????
        else if(TIM5->CNT >= 10000) motor1_overflowNum--; //???????
        __HAL_TIM_SetCounter(&htim5, 10000);             //???????
    }
 if(htim->Instance == TIM6) //measure speed,direct    //else if will take error
{

	   motor1_direct = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim5);//??????(??),????0,??????1
	   motor1_count = TIM5->CNT  + motor1_overflowNum * (4 * PULSE_PRE_ROUND) ;

   if(abs(motor1_count - motor1_lastcount) <= 3333)   //rate rpm = 2000 2000/60/100*10000   100hz
  { 
	  if(motor1_direct == 0 )
	 {
		
	  motor1_speed = (float)(motor1_count - motor1_lastcount )/ ( 4 * PULSE_PRE_ROUND) * k  * fcs ;//unit: r/mim
		  
	 }
	  if(motor1_direct == 1)
	 {

	  motor1_speed = - (float)(motor1_count - motor1_lastcount )/ (4 * PULSE_PRE_ROUND) * k  * fcs ;//???????
     
	  }
  }
	if(motor1_count - motor1_lastcount == 0)         //电机停止转动后位置置零
	 {
		 __HAL_TIM_SetCounter(&htim5, 10000);   
	 }
	N = motor1_count - (4 * PULSE_PRE_ROUND); 
	motor1_lastcount =  motor1_count;
 	HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_6);	    
 }
}

### 使用 STM32 HAL 与 FreeRTOS 控制编码器电机的速度 在使用 STM32 HAL FreeRTOS 实现对编码器电机速度的控制时,需要完成以下几个关键部分:配置定时器用于 PWM 输出、配置编码器接口以读取电机转速、以及通过 PID 控制算法调节电机速度。以下是详细的实现方法: #### 1. 配置 PWM 输出 PWM 输出用于控制电机的速度。首先在 STM32CubeMX 中配置定时器作为 PWM 输出模块。选择一个通用定时器(如 TIM3),将其模式设置为 PWM 输出,并配置频率占空比。例如,配置 PWM 频率为 1kHz,满占空比对应的 CCR 值为 999[^1]。 ```c // 初始化PWM输出 __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pwm_duty_cycle); ``` #### 2. 配置编码器接口 编码器接口用于读取电机的实际转速。在 STM32CubeMX 中,配置定时器为编码器模式。例如,使用 TIM4 作为编码器输入定时器,并选择 AB 编码器模式。设置溢出值(如 8191),以确保计数值不会超出范围[^3]。 ```c // 读取编码器计数值 int32_t encoder_count = __HAL_TIM_GET_COUNTER(&htim4); // 手动补偿反向旋转的数据 if (motor_dir == 0) { encoder_count = -65535 + encoder_count; } ``` #### 3. 使用 FreeRTOS 创建任务 FreeRTOS 提供了多任务管理功能,可以创建独立的任务来处理不同的功能模块。例如,创建一个任务用于读取编码器数据,另一个任务用于调整 PWM 占空比。 ```c // 创建任务读取编码器数据 xTaskCreate(vReadEncoderTask, "ReadEncoder", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); // 创建任务调整PWM占空比 xTaskCreate(vAdjustPWMTask, "AdjustPWM", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL); ``` #### 4. 实现 PID 控制算法 PID 控制算法用于根据目标速度实际速度的误差调整 PWM 占空比。以下是一个简单的 PID 控制实现示例: ```c typedef struct { float Kp; float Ki; float Kd; float integral; float prev_error; } PID_Controller; void PID_Update(PID_Controller *pid, float setpoint, float process_variable, float *output) { float error = setpoint - process_variable; pid->integral += error; float derivative = error - pid->prev_error; *output = pid->Kp * error + pid->Ki * pid->integral + pid->Kd * derivative; pid->prev_error = error; } ``` #### 5. 主程序逻辑 在主程序中,结合上述模块实现完整的电机速度控制逻辑。 ```c int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM3_Init(); // PWM初始化 MX_TIM4_Init(); // 编码器初始化 MX_FREERTOS_Init(); PID_Controller pid = {1.0, 0.1, 0.01, 0, 0}; // 初始化PID参数 float pwm_output = 0; for (;;) { int32_t encoder_value = __HAL_TIM_GET_COUNTER(&htim4); // 获取编码器值 float speed = encoder_value / 100.0; // 转换为速度值 PID_Update(&pid, 800, speed, &pwm_output); // 更新PID输出 __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pwm_output); // 设置PWM占空比 vTaskDelay(pdMS_TO_TICKS(10)); // 延时10ms } } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值