STM32HAL库电机开发-速度环-位置式PID-无刷直流电机

本文详细介绍了无刷电机的工作原理,包括霍尔传感器在电机换相中的作用,以及如何通过PID控制器实现电机速度的精确控制。在无刷电机的控制中,霍尔传感器的信号用于确定电机转子位置,进而通过调节PWM波形控制电机的转动。PID控制器根据电机的实际速度与目标速度的偏差进行调整,确保电机稳定运行。同时,文章还涉及了防止电机堵转的保护机制以及软件设计流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

工作原理

无刷电机和有刷电机不同,无刷电机采用三相控制,大概是这样,原理就是安培定则,也叫右手螺旋定则,电生磁来控制转子,也就是说我们需要输出的pwm波有三条通道。
在这里插入图片描述
无刷电机用到的传感器是霍尔传感器。霍尔传感器是根据霍尔效应制作的一种磁场传感器。霍尔效应:当电流垂直于外磁场通过半导体时, 载流子发生偏转,垂直于电流和磁场的方向会产生一附加电场,从而在半导体的两端产生电势差, 这一现象就是霍尔效应,这个电势差也被称为霍尔电势差。

在BLDC中一般采用3个开关型霍尔传感器测量转子的位置,由其输出的3位二进制编码去控制三相六臂全桥中的6 个MOS管的导通实现换相。如果将一只霍尔传感器安装在靠近转子的位置,当N极逐渐靠近霍尔传感器即磁感器达到一定值时, 其输出是导通状态;当N极逐渐离开霍尔传感器、磁感应逐渐小时,其输出仍然保持导通状态; 只有磁场转变为S极便达到一定值时,其输出才翻转为截止状态。在S和N交替变化下传感器输出波形占高、 低电平各占50%。如果转子是一对极,则电机旋转一周霍尔传感器输出一个周期的电压波形,如果转子是两对极, 则输出两个周期的波形。
在直流无刷电机中一般把3个霍尔传感器按间隔120度或60度的圆周分布来安装,如果按间隔120度来安装, 则3个霍尔传感器输出波形相差120度电度角,输出信号中高、低电平各占180度电度角。 如果规定输出信号高电平用“1”表示,低电平用“0”表示,则输出的三个信号可以用三位二进制码表示, 如下图所示。
在这里插入图片描述
转子每旋转一周可以输出6个不同的信号,这样正好可以满足我们条件。只要我们根据霍尔传感器输出的值来导通MOS管即可。 通常厂家也会给出真值表。一般有两个,一个是对应顺时针旋转,另一个对应的是逆时针旋转。配套电机的真值表如下。
在这里插入图片描述
上表的意思是:当检测到的3个霍尔传感器的值,则导通对应值的MOS管。例如,检测到霍尔a、 霍尔b和霍尔c分别为0、0和1,则导通B-和C+对应的MOS管,其他MOS管都要处于截止状态。 当导通对应的MOS管后电机就会旋转一个角度,旋转到下一个霍尔值改变为101,这时在关闭B-和C+, 导通A+和B-,这样电机有将会旋转一个角度直到下一个霍尔值改变, 只要我们按表中的霍尔值导通对应的MOS管电机就可按一定的方向旋转。

软件设计

  1. 基础定时器产生定时更新执行回调函数
    在这里插入图片描述

  2. 回调函数判断是否堵转保护电路

  3. 回调函数执行pid控制函数bldcm_pid_control()
    在这里插入图片描述

  4. pid控制函数获得电机转动速度,判断执行pid计算,判断运行方向,根据pid计算返回值设置电机速度函数set_bldcm_speed()
    在这里插入图片描述

  5. 电机控制函数输出pwm波控制函数set_pwm_pulse在这里插入图片描述

  6. pwm控制函数对通道进行占空比调整,再对三相进行换相HAL_TIM_TriggerCallback。

  7. 换相函数中调取函数get_hall_state获取霍尔传感器的状态作为换相的依据,判断正反转之后进行换相来,换相函数中进行pwm波输出。
    在这里插入图片描述

mian.c中的控制速度是调控pwm波占空比的多少。
在这里插入图片描述
霍尔传感器采用输入捕获模式,三个通道捕获。
无刷电机的多环控制是,类比于有刷电机的多环控制。采用双环,原因是野火无刷电机驱动板上没有电流检测。

void bldcm_pid_control(void)
{
  int32_t location_actual = get_motor_location();   // 电机旋转的当前位置

	
  if (bldcm_data.is_enable)
  {
    float cont_val = 0;    // 当前控制值

		cont_val = location_pid_realize(&pid_location, location_actual);    // 进行 PID 计算
		
		/* 目标速度上限处理 */
		if (cont_val > TARGET_SPEED_MAX)
		{
			cont_val = TARGET_SPEED_MAX;
		}
		else if (cont_val < -TARGET_SPEED_MAX)
		{
			cont_val = -TARGET_SPEED_MAX;
		}
		
		set_pid_target(&pid_speed, cont_val);    // 设定位置的目标值
		
		#if defined(PID_ASSISTANT_EN)
			int32_t temp = cont_val;
			set_computer_value(SEND_TARGET_CMD, CURVES_CH2, &temp, 1);     // 给通道 2 发送目标值
		#endif
	
		
		int32_t actual_speed = get_motor_speed();
		cont_val = speed_pid_realize(&pid_speed, actual_speed);    // 进行 PID 计算
		if (cont_val < 0)
		{
				cont_val = -cont_val;
				bldcm_data.direction = MOTOR_REV;
		}
		else 
		{
				bldcm_data.direction = MOTOR_FWD;
		}

		cont_val = (cont_val > PWM_PERIOD_COUNT) ? PWM_PERIOD_COUNT : cont_val;  // 上限处理

		set_bldcm_speed(cont_val);
		
	#if defined(PID_ASSISTANT_EN)
		set_computer_value(SEND_FACT_CMD, CURVES_CH2, &actual_speed, 1);      // 给通道 2 发送实际值
		set_computer_value(SEND_FACT_CMD, CURVES_CH1, &location_actual, 1);     // 给通道 1 发送实际值
	#else
		printf("实际值:%d, 目标值: %.0f,控制值: %.0f\n", location_actual, get_pid_target(), cont_val);
	#endif
	}
	
}
### 使用 HAL 实现 STM32PID 速度控制 对于使用 HAL STM32 上实现 PID 速度控制的任务,可以构建一个基于定时器中断的框架,在其中执行 PID 计算并调整 PWM 输出以控制电机的速度。下面是一个简化版的例子。 #### 初始化部分 初始化阶段主要涉及配置 TIM 和 GPIO 来生成用于驱动电机的 PWM 波形以及设置 ADC 或其他方式获取实际转速反馈值。 ```c #include "stm32f1xx_hal.h" TIM_HandleTypeDef htimX; // 定义定时器句柄对象, X代表具体的定时器编号 ADC_HandleTypeDef hadcY; // 如果采用ADC采集速度反馈,则定义ADC句柄对象,Y代表具体ADC通道号 void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_TIMX_PWM_Init(void); // 配置PWM输出功能的定时器初始化函数 // 若有需要则加入ADC初始化函数声明 static void MX_ADCY_Init(void); int main(void){ HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIMX_PWM_Init(); // 如需ADC采样则调用MX_ADCY_Init(); while (1){ /* 用户代码区 */ } } ``` #### 中断服务程序中的 PID 处理逻辑 此部分展示了如何在一个定时器溢出中断内完成一次完整的 PID 运算过程,并据此调节 PWM 占空比从而改变电机运转状态。 ```c #define Kp 0.8f /*!< 比例系数 */ #define Ki 0.05f /*!< 积分系数 */ #define Kd 0.1f /*!< 微分系数 */ float setpoint = 1000.0f; // 设定目标转速(RPM), 可由外部输入设定 volatile float current_speed = 0; volatile float prev_error = 0; volatile float integral = 0; extern uint32_t __weak HAL_GetTick(void); void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ if(htim->Instance==htimX.Instance){ // 判断是否为指定定时器触发 int32_t adc_raw_data=0; HAL_ADC_Start(&hadcY); HAL_ADC_PollForConversion(&hadcY, HAL_MAX_DELAY); adc_raw_data = HAL_ADC_GetValue(&hadcY); // 将AD转换得到的数据转化为实际物理量(这里假设已经知道对应关系) current_speed=(float)(adc_raw_data)*conversion_factor; float error=setpoint-current_speed; integral+=error*Ki*(HAL_GetTick()/1000.0f); // 时间单位ms转s float derivative=(error-prev_error)/((HAL_GetTick())/1000.0f); float output=Kp*error+integral-Kd*derivative; // 对output做限幅处理防止过大过小影响系统稳定性和安全性 if(output>max_output) output=max_output; else if(output<min_output) output=min_output; // 更新PWM占空比 __HAL_TIM_SET_COMPARE(&htimX, TIM_CHANNEL_1,output/max_output*ARR_value); prev_error=error; } } ``` 上述代码片段展示了一个基本结构,但请注意这只是一个概念性的例子[^1]。 实际应用时还需要考虑更多细节如参数整定、异常情况下的保护措施等。 此外,由于不同型号MCU之间存在差异,因此建议参照官方手册针对特定芯片系列编写更精确的应用程序。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值