☰
【电机控制】无刷直流电机BLDC控制-hall读取部分
2026/10/20 6:15:43 网站建设 项目流程

目录

文章目录

前言

一、BLDC控制

1. 六步换向法原理

2. 硬件组成

3. 软件控制流程

4. 速度控制方法

二、驱动代码

1. 电机平台

2. Hall 传感器初始化配置

2.1 定时器配置

2.2 分频与滤波配置

2.3 引脚配置

2.4 初始化代码

2.5 读取 Hall 状态

2.6 Hall 反馈驱动代码

2.7 Hall 序列学习

总结


提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、pandas是什么?
  • 二、使用步骤
    • 1.引入库
    • 2.读入数据
  • 总结

前言

BLDC(Brushless Direct Current Motor,无刷直流电机)是一种采用电子换向替代传统机械换向的直流电机。它通过控制器驱动逆变器,按照转子位置信号依次导通不同相绕组,使定子磁场与转子永磁体磁场保持同步,从而持续输出转矩。

与有刷直流电机相比,BLDC 电机没有电刷和换向器,因此具有以下显著优势:

  • 效率更高:消除了电刷摩擦损耗,电能到机械能的转换效率明显提升。
  • 寿命更长:无机械磨损部件,维护成本低,适合长期连续运行。
  • 噪音更低:运行平稳,电磁噪声和机械噪声均大幅降低。
  • 控制精度高:配合矢量控制或方波控制,可实现精确的速度和位置调节。

凭借这些优点,BLDC 电机被广泛应用于无人机、电动工具、机器人、新能源汽车、家电以及工业自动化等领域,成为现代电机驱动系统中的核心部件之一。


提示:以下是本篇文章正文内容,下面案例可供参考

一、BLDC控制

本节 BLDC 控制采用六步换向法(方波控制),通过控制逆变器中 MOS 管两两导通,配合霍尔传感器读取转子位置,实现电机的速度与换向控制。下面从控制原理、硬件组成和软件实现三个层面展开说明。

1. 六步换向法原理

六步换向法将电角度 360° 划分为 6 个扇区,每个扇区 60°。在每个扇区内,逆变器只导通上下桥臂中的两相绕组,第三相悬空。霍尔传感器每 60° 输出一次位置信号组合,控制器据此切换导通组合,使定子磁场始终超前转子磁场一定角度,从而持续产生转矩。

六个导通状态依次为:AB、AC、BC、BA、CA、CB(以三相 A、B、C 为例),每个状态持续 60° 电角度,一个完整电周期内完成六次换相。

2. 硬件组成

  • BLDC 电机:三相星形或三角形连接,内置霍尔传感器。
  • 三相逆变器:由 6 个 MOS 管组成,分为上桥臂(Q1、Q3、Q5)和下桥臂(Q2、Q4、Q6)。
  • 霍尔传感器:通常安装 3 个,间隔 120° 电角度,用于检测转子位置。
  • 控制器:MCU 或 DSP,负责读取霍尔信号、生成 PWM 驱动信号。

3. 软件控制流程

控制程序的核心流程如下:

  1. 读取霍尔传感器信号,确定当前转子所在扇区。
  2. 根据扇区查表,确定应导通的两相绕组及对应 MOS 管。
  3. 输出 PWM 信号驱动对应 MOS 管导通,另一相悬空。
  4. 通过调节 PWM 占空比控制电机转速。
  5. 等待下一次霍尔信号跳变,重复上述步骤完成换相。

4. 速度控制方法

速度控制通常采用闭环 PID 控制:霍尔传感器同时提供位置信息,通过计算单位时间内换相次数即可得到电机转速。将实际转速与目标转速比较,经 PID 调节器输出 PWM 占空比,从而动态调整电机转速。

二、驱动代码

1. 电机平台

本节控制 MCU 为 ST 的 STSPIN32F0,内含一个 M0 内核的 STM32F031C6 芯片以及栅极驱动芯片,电机为 120 度安装的霍尔传感器的 8 极无刷电机。

2. Hall 传感器初始化配置

Hall 传感器用于检测转子位置,是六步换向法控制的核心输入。本节基于 STM32 定时器 2 的霍尔捕获功能,完成 Hall 信号的采集与配置。

2.1 定时器配置

将定时器 2 开启,使用内部时钟,本次控制频率为 10Hz,属于低频控制。在这里打开定时器自带的霍尔捕获功能,使能 Hall 传感器模式,三路霍尔信号进行 XOR。

2.2 分频与滤波配置

配置分频系数为 47,将内部时钟分频调节为 4 分频;Hall 传感器极性改为下降沿触发,滤波系数改为 15,以滤除高频噪声干扰。

2.3 引脚配置

将 PA0、PA1、PA2 引脚配置为定时器 2 的捕获通道,并开启内部上拉,确保 Hall 信号在无输入时保持高电平。

2.4 初始化代码

Hall 传感器初始化代码如下:

/* Hall 传感器初始化 */ void HAL_Init(void) { /* 使能定时器2时钟 */ __HAL_RCC_TIM2_CLK_ENABLE(); /* 配置 PA0、PA1、PA2 为定时器2通道1/2/3 */ GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* 配置定时器2霍尔模式 */ TIM_HallSensor_InitTypeDef HallConfig = {0}; HallConfig.IC1Polarity = TIM_ICPOLARITY_FALLING; HallConfig.IC1Prescaler = TIM_ICPSC_DIV4; HallConfig.IC1Filter = 15; HAL_TIMEx_HallSensor_Init(&htim2, &HallConfig); /* 启动霍尔传感器捕获 */ HAL_TIMEx_HallSensor_Start(&htim2); }

2.5 读取 Hall 状态

通过读取定时器 2 的捕获寄存器,即可获得当前 Hall 传感器的组合状态,进而确定转子所在扇区:

/* 读取 Hall 状态,返回 0~7 的扇区编码 */ uint8_t Read_Hall_State(void) { uint8_t hall_state = 0; /* 读取三个通道的捕获值并组合为 3 位编码 */ hall_state = (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) ? 1 : 0); hall_state |= (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) ? 2 : 0); hall_state |= (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2) ? 4 : 0); return hall_state; }

根据返回的 Hall 状态值,即可在换向表中查找对应的导通组合,驱动逆变器完成换相。

2.6 Hall 反馈驱动代码

下面给出完整的 Hall 反馈驱动实现,包含扇区索引、环形缓冲、转速计算、超时处理以及 Hall 序列学习等核心逻辑。该代码基于 STM32F0 系列,使用 LL 库进行 GPIO 读取。

#include "../motor_build_config.h" #include "hall_feedback.h" #include "../motor_config.h" #include "main.h" #include "stm32f0xx_ll_gpio.h" #if MOTOR_CONTROL_METHOD == MOTOR_CONTROL_BLDC volatile HALL_Struct hall1; static const uint8_t sector_codes[6] = MOTOR_HALL_SEQUENCE_INIT; static int8_t SectorIndex(uint8_t code) { for (uint8_t i = 0U; i < 6U; i++) if (sector_codes[i] == code) return (int8_t)i; return -1; } static void ClearBuffer(void) { hall1.buffer_index = hall1.buffer_count = hall1.valid = 0U; hall1.period_sum_us = hall1.rpm = 0U; for (uint8_t i = 0U; i < WBuffer_MAX_SIZE; i++) hall1.buffer[i] = 0U; } void HallFeedback_Reset(uint8_t code, uint32_t now_us) { hall1 = (HALL_Struct){0}; hall1.state = code; hall1.last_edge_us = now_us; hall1.startup = 1U; } uint8_t HallFeedback_OnEdge(uint8_t code, uint32_t now_us, uint32_t period_us) { int8_t old_index, new_index, direction; new_index = SectorIndex(code); if (new_index < 0) return 0U; if (code == hall1.state) return 0U; if (hall1.startup || (uint32_t)(now_us - hall1.last_edge_us) > MOTOR_HALL_TIMEOUT_US) { HallFeedback_Reset(code, now_us); hall1.startup = 0U; return 1U; } if (period_us < MOTOR_HALL_MIN_EDGE_US || period_us > MOTOR_HALL_TIMEOUT_US) return 0U; old_index = SectorIndex(hall1.state); if (new_index == (old_index + 1) % 6) direction = 1; else if (old_index == (new_index + 1) % 6) direction = -1; else { hall1.sequence_error = 1U; return 0U; } if (hall1.direction != 0 && direction != hall1.direction) ClearBuffer(); hall1.direction = direction; hall1.state = code; hall1.last_edge_us = now_us; hall1.sequence_error = 0U; hall1.period_sum_us -= hall1.buffer[hall1.buffer_index]; hall1.buffer[hall1.buffer_index] = period_us; hall1.period_sum_us += period_us; hall1.buffer_index = (uint8_t)((hall1.buffer_index + 1U) % WBuffer_MAX_SIZE); if (hall1.buffer_count < WBuffer_MAX_SIZE) hall1.buffer_count++; hall1.valid = hall1.buffer_count == WBuffer_MAX_SIZE; { uint64_t rpm = (60000000ULL * hall1.buffer_count) / ((uint64_t)hall1.period_sum_us * 6U * MOTOR_POLE_PAIRS); hall1.rpm = (uint16_t)((rpm > 65535U) ? 65535U : rpm); } return 1U; } void HallFeedback_Read(uint32_t now_us, HallFeedback *feedback) { uint32_t irq_state = __get_PRIMASK(); uint32_t age; __disable_irq(); age = (uint32_t)(now_us - hall1.last_edge_us); if (age > 0x7FFFFFFFU) age = 0U; if (age > MOTOR_HALL_TIMEOUT_US) { ClearBuffer(); hall1.startup = 1U; hall1.direction = 0; } feedback->code = hall1.state; feedback->sequence_error = hall1.sequence_error; feedback->valid = hall1.valid && !hall1.sequence_error; feedback->age_us = age; feedback->rpm = feedback->valid ? hall1.rpm : 0U; __set_PRIMASK(irq_state); } #endif uint8_t Hall_Read(void) { uint32_t pins = HAL_GPIO_ReadInputPort(GPIOA); /* 三路用同一时刻的快照,避免拼接到过渡状态。 */ uint8_t h1 = (pins & GPIO_PIN_0) != 0U; uint8_t h2 = (pins & GPIO_PIN_1) != 0U; uint8_t h3 = (pins & GPIO_PIN_2) != 0U; return (uint8_t)((h1 << 2) | (h2 << 1) | h3); }

上述代码中,HallFeedback_OnEdge在每次霍尔信号跳变时被调用,负责更新扇区索引、方向判断和转速计算;HallFeedback_Read供主循环读取当前状态,并在超时后自动清空缓冲;Hall_Read通过一次快照读取三路引脚,避免拼接到过渡状态。

2.7 Hall 序列学习

在电机首次上电或更换电机时,霍尔传感器的安装顺序可能与默认配置不一致。下面的代码用于自动学习 6 个扇区的霍尔编码顺序,并将结果发布到换向表:

#include "hall_sequence.h" #include "../motor_config.h" #include <string.h> void HallSequence_Reset(HallSequence *sequence, uint8_t raw_code, uint32_t now_us) { memset(sequence, 0, sizeof(*sequence)); sequence->last_us = now_us; sequence->last_code = raw_code; if (raw_code < 8U) { sequence->codes[0] = raw_code; sequence->count = 1U; sequence->seen = (uint8_t)(1U << raw_code); } } uint8_t HallSequence_Update(HallSequence *sequence, uint8_t raw_code, uint32_t now_us) { uint32_t elapsed; uint8_t changed; if (sequence->complete || raw_code == sequence->last_code) return 0U; elapsed = now_us - sequence->last_us; if (elapsed < MOTOR_HALL_MIN_EDGE_US) return 0U; changed = raw_code ^ sequence->last_code; if (raw_code >= 8U || sequence->count == 0U || elapsed > MOTOR_HALL_TIMEOUT_US || changed == 0U || (changed & (changed - 1U)) != 0U) { HallSequence_Reset(sequence, raw_code, now_us); return 1U; } if (sequence->count == 6U && raw_code == sequence->codes[0]) { /* 观察到第七次编码回到起点,才发布完整电角周期。 */ sequence->complete = 1U; } else if (sequence->count >= 6U || (sequence->seen & (1U << raw_code))) { HallSequence_Reset(sequence, raw_code, now_us); /* 往返抖动或顺序异常 */ return 1U; } else { sequence->codes[sequence->count++] = raw_code; sequence->seen |= (uint8_t)(1U << raw_code); } sequence->last_code = raw_code; sequence->last_us = now_us; return 1U; } void HallSequence_Publish(const HallSequence *sequence, volatile uint8_t codes[6], volatile uint8_t *ready) { *ready = 0U; for (uint8_t i = 0U; i < 6U; i++) codes[i] = sequence->codes[i]; *ready = sequence->complete; }

该模块通过校验相邻编码只变化一位(changed & (changed - 1U) == 0)来过滤抖动和非法跳变,并在观察到第七次编码回到起点时判定学习完成,随后将学习到的 6 个扇区编码发布到换向表。


总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询