esp_sensorless_bldc_control 比较器反电势过零检测与六步换相源码解读【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution这篇文章以 esp-iot-solution 仓库中的esp_sensorless_bldc_control组件为对象,讲清基于硬件比较器检测反电动势(BEMF)过零点的无感方波电机控制方案:先给出过零信号的物理来源与虚拟中性点技巧,再走读三路比较器硬件电路,然后按"采样、滤波、测速、状态映射"四个机制逐段读源码,最后覆盖接线、bldc_user_cfg.h配置与闭环启动的完整流程,并附上典型故障现象的排查对照。跟着走读完成后,你可以基于仓库自带测试用例独立完成比较器三路接线、参数调整与无感闭环启动。一、快速总览条目内容核心概念比较器输出过零电平判断转子位置硬件门槛三路比较器、等阻网络、三个输入 GPIO适用场景低成本无感方波驱动、无霍尔电机关键文件comparer.c 与 six_step.c该方案是组件内与ALIGNMENT_ADC(ADC 采样)并列的另一种无感模式,通过配置项ALIGNMENT_COMPARER启用。两者共用同一套六步换相框架,区别只在过零信号的产生与确认方式。二、原理走读过零信号从哪来:反电势幅值与转速成正比方波驱动的 BLDC 电机任意时刻只有两相导通(一相接正、一相接负),第三相浮空。浮空相绕组没有电流,其端电压主要就是反电动势,因此浮空相是检测转子位置的最佳窗口。反电势的物理来源是绕组切割转子磁场,按楞次定律其极性总是阻碍电流变化:BEMF = NlrBω符号含义N绕组匝数l转子导条有效长度r转子内半径B转子磁场强度ω转子角速度电机下线后 N、l、r、B 都是定值,所以反电势幅值只与角速度 ω 成正比。这直接决定了两个工程事实:转速越快过零检测越可靠;转速过低时反电势弱到淹没在噪声里,必须先靠对齐(ALIGNMENT)和强拖(DRAG)把转速拉起来,过零信号才稳定可用。图中每个 60° 电角度发生一次换相,换相后新浮空相的反电势在半周期内穿越中点,这个穿越点就是比较器要捕捉的过零点。关键技巧:等阻电阻重构虚拟中性点判断过零需要比较"端电压与中性点电压谁大",但星形接法的电机通常不引出中性点,无法直接测量。比较器方案的做法是用相同阻值的电阻把三相拉到公共点,该公共点电压近似等于真实中性点,称为虚拟中性点。每相端电压与虚拟中性点各接一路比较器的输入,比较器输出高低电平即代表该相端电压在不在中性点上方,电平翻转时刻就是过零点。过零间隔与转速的数学关系浮空相反电势每半个电气周期(180° 电角度)穿越一次中点。设计时基准频率为 ft、电机极对数为 n、两次过零之间累计的计数值为 c,则:speed_rpm = ft / (2 × n × c) × 60ft 是周期中断频率,2×n 对应一个机械转内含有的半电气周期数。按组件默认配置MCPWM_CLK_SRC=20MHz、MCPWM_PERIOD=2000,计时周期ALARM_COUNT_US=100µs,POLE_PAIR=5,代入后系数为 60000,即speed_rpm = 60000 / speed_count。三、硬件/接口走读下左图是组件文档给出的功率侧参考:三相全桥(UH/VH/WH 上管、UL/VL/WL 下管)驱动星形绕组,母线 Udc 加在桥臂之间。下右图是信号侧:每相端电压经 1K 分压电阻(R25/R28、R29/R31、R32/R34)接入比较器反相端,等阻 20K 电阻(R25 上方标注 20K 的网络)合成虚拟中性点接比较器同相端,输出经 100R + 100nF 滤波后分别得到 BEMF_1/2/3 三路过零信号,另有一路比较器(U8:2)用于输出端分压参考。硬件要点:三路比较器支路:每相一路,负责把该相端电压与虚拟中性点的比较结果变成数字电平,是过零信号的直接来源;排查时先用示波器确认三路输出在电机转动时确有规律翻转。等阻虚拟中性点网络:R28/R29/R32 等电阻必须同阻值,任一路偏差都会把中性点基准拉偏,导致某一相过零点系统性偏移。输出 RC 滤波:100R 串联加 100nF 对地,抑制 PWM 开关噪声;电容过大则电平翻转滞后,与软件滤波叠加会加大换相延迟。GPIO 接口:三路信号接普通 GPIO,组件按输入模式初始化,active_level字段用于适配比较器输出极性。硬件排查顺序建议:先测三路比较器输出是否随转速稳定翻转,再核对等阻电阻的实测偏差(建议 1% 以内),最后检查输出端滤波电容取值与比较器供电、地线是否干净。四、源码机制走读同步采样:MCPWM on_full 时刻的 64 位移入队列做什么:MCPWM 定时器每次计数到峰值(on_full 事件)时,把三路比较器 GPIO 电平各取一次,逐位移入每相 64 位环形队列。为什么:换相刚发生的窗口内,端电压受续流二极管和开关噪声影响严重,连续读 GPIO 会采到大量脏数据。绑定 PWM 峰值时刻采样,保证每个 PWM 周期只取一个干净的样本点,同时把采样节拍与 PWM 严格同步。在哪做:bldc_control.c 中注册回调,bldc_zero_cross_comparer.c 中实现采样:// bldc_control.c: ALIGNMENT_COMPARER 分支 control->zero_cross = &bldc_zero_cross_comparer_operation; control->cbs->on_full = &read_comparer_on_full; /* 关键:PWM 峰值时刻触发采样 */ config->six_step_config.upper_switch_config.bldc_mcpwm.timer_cb_user_data = (void *)control->zero_cross_handle;// bldc_zero_cross_comparer.c: 每相 64 位队列左移 1 位并入当前电平 static void IRAM_ATTR alignment_comparer_get_value(bldc_zero_cross_comparer_t *zero_cross) { for (int i = 0; i < PHASE_MAX; i++) { zero_cross->alignment_queue_value[i] = zero_cross->alignment_queue_value[i] << 1; zero_cross->alignment_queue_value[i] |= gpio_ll_get_level(&GPIO, zero_cross->alignment_pin[i]); } }怎么调:采样时刻固定在 on_full,无独立参数可调;采样密度由MCPWM_CLK_SRC与MCPWM_PERIOD决定(默认 10kHz PWM),改 PWM 频率时注意队列窗口覆盖的时间随之变化。连续滤波与过零确认:0xFFFF 相同样本判有效做什么:把队列低 16 位与ZERO_CROSS_DETECTION_ACCURACY做按位与,全 1 判该相为高、全 0 判为低、否则判滤波失败并跳过本周期处理。为什么:硬件滤波后仍可能有窄脉冲噪声,"连续多次同电平"的判决能拒绝孤立毛刺,避免把噪声当过零事件触发误换相。滤波失败时filter_failed_count累加,超过 15000 次会被主状态机判为堵转(BLOCKED),这一计数同时是信号质量的在线监测指标。在哪做:bldc_zero_cross_comparer.c:for (int i = 0; i < PHASE_MAX; i++) { if ((zero_cross->alignment_queue_value[i] & ZERO_CROSS_DETECTION_ACCURACY) == ZERO_CROSS_DETECTION_ACCURACY) { zero_cross->queue_filter_state[i] = 1; /* 连续 16 次高电平 */ } else if ((zero_cross->alignment_queue_value[i] & ZERO_CROSS_DETECTION_ACCURACY) == 0) { zero_cross->queue_filter_state[i] = 0; /* 连续 16 次低电平 */ } else { zero_cross->control_param->filter_failed_count++; return 0; /* 滤波失败:本周期不处理 */ } }怎么调:ZERO_CROSS_DETECTION_ACCURACY默认0xFFFF(连续 16 次相同),最大0xFFFFFFFF(32 次)。改大会提高抗噪能力,但电平确认延迟增大、换相整体后移,需与ZERO_CROSS_ADVANCE联动补偿。测速与提前角补偿:speed_count 折算 RPM做什么:以 U 相滤波状态为基准做边沿检测,检测到 1→0 下降沿时,把本半周期累计的speed_count折算成转速,经一阶低通后写回speed_rpm,同时算出提前换向延迟filter_delay。为什么:无传感器方案需要转速反馈给 PID;而比较器检测到的过零点理论上是换向前 30° 电角度到来,加上软件滤波滞后,若立即换相角度会偏晚,需要按当前转速折算出延迟量做补偿。在哪做:bldc_zero_cross_comparer.c,系数定义在 bldc_config.h:#define COMPARER_RPM_CALCULATION_COEFFICIENT (((1000000 / ALARM_COUNT_US) / (2.0 * POLE_PAIR)) * 60) // bldc_zero_cross_comparer.c: U 相状态 1->0 下降沿处 if (filterEdge == 0) { if (zero_cross->zero_stable_flag >= ZERO_STABLE_FLAG_CNT) { speed_rpm = (uint32_t)(COMPARER_RPM_CALCULATION_COEFFICIENT / zero_cross->control_param->speed_count); BLDC_LPF(zero_cross->control_param->speed_rpm, speed_rpm, 0.2); /* 系数 0.2 低通平滑 */ } zero_cross->control_param->filter_delay = zero_cross->control_param->speed_count / ZERO_CROSS_ADVANCE; }怎么调:POLE_PAIR默认 5,必须按电机实际极对数设置,否则转速读数整体成倍偏差。ZERO_CROSS_ADVANCE默认 8,提前角 = 180°/该值(默认 22.5°,略小于理论 30° 以抵消滤波滞后),注释要求不小于 6;改小则换相更提前,过快会过冲,建议用示波器对比实际与理论换相角。六种过零状态到换相动作的映射做什么:滤波后的三相状态(各 0/1)共六种有效组合,zero_cross_comparer_get_phase()输入三相状态与方向dir,返回 1~6 的相位号;相位号变化时bldc_six_step_turn()按方向选择对应的六步数组执行换相。为什么:三相比较器电平的组合恰好唯一编码了当前转子所在的 60° 扇区,查表即可把"电平组合"翻译成"下一步该导通哪两相",无需任何位置积分。在哪做:相位判定在 bldc_zero_cross_comparer.c,换相序列与执行在 bldc_six_step.c:// bldc_zero_cross_comparer.c: 连续稳定后取相位 uint8_t phase = zero_cross_comparer_get_phase(zero_cross->queue_filter_state, zero_cross->control_param->dir); if (phase <= 0 || phase > 6) { zero_cross->control_param->error_hall_count++; /* 非法组合:信号质量异常 */ return 0; }// bldc_six_step.c: 正转六步序列(函数指针数组) static void (*six_step_comparer_cw_array[6])(...) = { &bldc_six_step_UphaseH_VphaseL, /* U 上管 PWM,V 下管导通 */ &bldc_six_step_WphaseH_VphaseL, &bldc_six_step_WphaseH_UphaseL, &bldc_six_step_VphaseH_UphaseL, &bldc_six_step_VphaseH_WphaseL, &bldc_six_step_UphaseH_WphaseL, };方向数组的选择在 bldc_six_step.c:alignment_mode == ALIGNMENT_COMPARER时绑定比较器专用数组,否则绑定 ADC 数组。官方文档中的映射表("1/0" 表示该相比较器输出高于/低于虚拟中性点;"上开下关 / 上关下开 / 上关下关" 表示该相桥臂状态):正转(CW):序号ZERO UZERO VZERO WU 相状态V 相状态W 相状态1001上开下关上关下开上关下关2011上开下关上关下关上关下开3010上关下关上开下关上关下开4110上关下开上开下关上关下关5100上关下开上关下关上开下关6101上关下关上关下开上开下关反转(CCW):序号ZERO UZERO VZERO WU 相状态V 相状态W 相状态1010上关下开上开下关上关下关2110上关下开上关下关上开下关3100上关下关上关下开上开下关4101上开下关上关下开上关下关5001上开下关上关下关上关下开6011上关下关上开下关上关下开说明:仓库文档 bldc_snls_comparer.rst 中两张映射表的表头三列均写作 "ZERO U",结合源码queue_filter_state[PHASE_MAX]为 U/V/W 三相状态数组的事实判断,三列实际依次为 ZERO U、ZERO V、ZERO W,上表按此呈现。怎么调:方向由bldc_control_set_dir(handle, CW/CCW)设置,方向设置必须与电机实际绕线一致,否则会反向或无法启动;调试时观察error_hall_count,持续递增说明三相状态长期落在六种合法组合之外,优先查硬件。五、实践三步第 1 步:添加组件依赖与用户配置文件在项目根目录执行:idf.py add-dependency "espressif/esp_sensorless_bldc_control=*"把 user_cfg/bldc_user_cfg.h 复制到项目的main/目录(保持文件名bldc_user_cfg.h),并在main/CMakeLists.txt中追加(与 test_apps/bldc_comparer/main/CMakeLists.txt 相同):idf_component_get_property(bldc_lib espressif__esp_sensorless_bldc_control COMPONENT_LIB) cmake_policy(SET CMP0079 NEW) target_link_libraries(${bldc_lib} PUBLIC ${COMPONENT_LIB})验证点:idf.py build通过,且不再报bldc_user_cfg.h not found, must provide by user(该报错由 bldc_config.h 的__has_include检查触发)。第 2 步:填写硬件配置结构体参考 test_comparer.c,LEDC 驱动上管、GPIO 驱动下管的最小配置:bldc_zero_cross_comparer_config_t zero_cross_comparer_config = { .comparer_gpio[0] = { .gpio_num = 3, .gpio_mode = GPIO_MODE_INPUT, .active_level = 0 }, /* U 相过零 */ .comparer_gpio[1] = { .gpio_num = 46, .gpio_mode = GPIO_MODE_INPUT, .active_level = 0 }, /* V 相过零 */ .comparer_gpio[2] = { .gpio_num = 9, .gpio_mode = GPIO_MODE_INPUT, .active_level = 0 }, /* W 相过零 */ }; bldc_control_config_t config = { .speed_mode = SPEED_CLOSED_LOOP, .control_mode = BLDC_SIX_STEP, .alignment_mode = ALIGNMENT_COMPARER, /* 关键:选择比较器过零检测 */ .six_step_config = { .lower_switch_active_level = 0, /* 关键:下管有效电平,须与驱动板一致 */ .upper_switch_config = upper_switch_config, .lower_switch_config = lower_switch_config, .mos_en_config.has_enable = false, }, .zero_cross_comparer_config = zero_cross_comparer_config, };验证点:comparer_gpio[i].gpio_num与硬件上 BEMF_1/2/3 的接线一一对应;active_level与比较器输出极性匹配(反接时软件滤波会一直判失败)。第 3 步:初始化、设方向并启动bldc_control_handle_t bldc_control_handle = NULL; bldc_control_init(&bldc_control_handle, &config); /* 初始化硬件驱动 */ bldc_control_set_dir(bldc_control_handle, CCW); /* 设置旋转方向 */ bldc_control_start(bldc_control_handle, 300); /* 以 300 RPM 启动 */验证点:串口日志依次出现BLDC_CONTROL_ALIGNMENT、BLDC_CONTROL_DRAG,稳定运行后打印CLOSED_LOOP事件(事件名表见 bldc_control.c);只停在 DRAG 不进入闭环即说明过零信号未达标。六、排障速查现象可能原因对策比较器 GPIO 长期无规律翻转,进不了 DRAG 后的闭环采样支路断线、等阻电阻偏差大、比较器未供电示波器逐一确认 BEMF_1/2/3 输出;核对 20K 等阻网络阻值一致性(建议 1% 精度)强拖正常但始终进不了 CLOSED_LOOP滤波判决长期失败,filter_failed_count高先把ZERO_CROSS_DETECTION_ACCURACY调大验证;仍无效则查硬件滤波电容与active_level配置闭环后运行抖动、偶尔丢步滤波深度不足,窄脉冲噪声触发误换相ZERO_CROSS_DETECTION_ACCURACY从0xFFFF提到0xFFFFFFFF,并同步减小ZERO_CROSS_ADVANCE补偿延迟电机反转或启动时抖一下再反着转dir与绕线方向不符,或某两相线序接反对调 U/V 两相接线,或bldc_control_set_dir改方向,二者改其一闭环后进入 BLOCKED(日志打印 BLOCKED)filter_failed_count超 15000 被判堵转,信号持续无效观察error_hall_count是否同步递增;递增则为信号质量差,按前两项排查硬件转速读数明显偏离实际值POLE_PAIR设置错误,测速系数成倍偏差按电机铭牌极对数重设POLE_PAIR,读数偏差与设置比应成反比七、关键参数速查以下宏定义在 user_cfg/bldc_user_cfg.h:宏默认值作用调整方向ZERO_STABLE_FLAG_CNT4连续稳定检测到多少个过零后进入无感闭环偏大→进闭环更晚但更可靠;偏小→启动段误判风险高ZERO_CROSS_DETECTION_ACCURACY0xFFFF连续多少次相同采样判为有效电平(16 次)偏大→抗噪强但换相延迟大,需配合减小ZERO_CROSS_ADVANCE;偏小→噪点易通过,filter_failed_count上升ZERO_CROSS_ADVANCE8提前换向分母,提前角 = 180°/该值,要求 ≥ 6偏大→提前角变小、换相偏晚;偏小→换相过提前,角度过冲POLE_PAIR5电机极对数,决定测速系数偏大→转速读数偏低;偏小→读数偏高,须按实际极对设置RAMP_DUTY_STA/RAMP_DUTY_END20% / 40%强拖起始/结束占空比(DUTY_MAX为 1000)偏大→启动扭矩强但易过流;偏小→带载时拉不起来RAMP_TIM_STA/RAMP_TIM_END600 / 90强拖换相间隔的起/止值(单位:gptimer 节拍)偏大→启动平滑但时间长;偏小→快但带载易丢步MCPWM_CLK_SRC/MCPWM_PERIOD20MHz / 2000PWM 时钟与周期(10kHz),决定ALARM_COUNT_US=100µs改变会同步改变测速系数与滤波窗口,需整体复核SPEED_KP/SPEED_KI0.004 / 0.00015速度闭环 PID 增益偏大→跟踪快但易振荡;偏小→响应迟钝、带载掉速八、延伸阅读bldc_overview.rst:BLDC 结构、逆变桥与有感/无感控制方式的总览对比。bldc_snls_comparer.rst:官方对比较器方案的完整说明,含本文两张映射表的原始出处。esp_sensorless_bldc_control.rst:INJECT/ALIGNMENT/DRAG/CLOSED_LOOP 各启动阶段的参数详解与调参提示。bldc_control.c:状态机主体、事件分发与回调注册位置。bldc_zero_cross_comparer.c 与 bldc_six_step.c:过零确认与六步换相的两段核心实现。test_comparer.c:LEDC + GPIO 与 MCPWM 两种配置的完整运行示例,可直接烧录验证。比较器方案的核心链条很短:等阻网络重构虚拟中性点,比较器把端电压比较结果变成三路电平,64 位队列滤波确认过零,再查表映射成六步换相。实际调参时最关键的一条经验是:加深ZERO_CROSS_DETECTION_ACCURACY滤波后务必同步减小ZERO_CROSS_ADVANCE,并用示波器核对实际换相角与理论换相角,换相角度并不是越提前越好。【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
esp_sensorless_bldc_control 比较器反电势过零检测与六步换相源码解读【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution这篇文章以 esp-iot-solution 仓库中的esp_sensorless_bldc_control组件为对象,讲清基于硬件比较器检测反电动势(BEMF)过零点的无感方波电机控制方案:先给出过零信号的物理来源与虚拟中性点技巧,再走读三路比较器硬件电路,然后按"采样、滤波、测速、状态映射"四个机制逐段读源码,最后覆盖接线、bldc_user_cfg.h配置与闭环启动的完整流程,并附上典型故障现象的排查对照。跟着走读完成后,你可以基于仓库自带测试用例独立完成比较器三路接线、参数调整与无感闭环启动。一、快速总览条目内容核心概念比较器输出过零电平判断转子位置硬件门槛三路比较器、等阻网络、三个输入 GPIO适用场景低成本无感方波驱动、无霍尔电机关键文件comparer.c 与 six_step.c该方案是组件内与ALIGNMENT_ADC(ADC 采样)并列的另一种无感模式,通过配置项ALIGNMENT_COMPARER启用。两者共用同一套六步换相框架,区别只在过零信号的产生与确认方式。二、原理走读过零信号从哪来:反电势幅值与转速成正比方波驱动的 BLDC 电机任意时刻只有两相导通(一相接正、一相接负),第三相浮空。浮空相绕组没有电流,其端电压主要就是反电动势,因此浮空相是检测转子位置的最佳窗口。反电势的物理来源是绕组切割转子磁场,按楞次定律其极性总是阻碍电流变化:BEMF = NlrBω符号含义N绕组匝数l转子导条有效长度r转子内半径B转子磁场强度ω转子角速度电机下线后 N、l、r、B 都是定值,所以反电势幅值只与角速度 ω 成正比。这直接决定了两个工程事实:转速越快过零检测越可靠;转速过低时反电势弱到淹没在噪声里,必须先靠对齐(ALIGNMENT)和强拖(DRAG)把转速拉起来,过零信号才稳定可用。图中每个 60° 电角度发生一次换相,换相后新浮空相的反电势在半周期内穿越中点,这个穿越点就是比较器要捕捉的过零点。关键技巧:等阻电阻重构虚拟中性点判断过零需要比较"端电压与中性点电压谁大",但星形接法的电机通常不引出中性点,无法直接测量。比较器方案的做法是用相同阻值的电阻把三相拉到公共点,该公共点电压近似等于真实中性点,称为虚拟中性点。每相端电压与虚拟中性点各接一路比较器的输入,比较器输出高低电平即代表该相端电压在不在中性点上方,电平翻转时刻就是过零点。过零间隔与转速的数学关系浮空相反电势每半个电气周期(180° 电角度)穿越一次中点。设计时基准频率为 ft、电机极对数为 n、两次过零之间累计的计数值为 c,则:speed_rpm = ft / (2 × n × c) × 60ft 是周期中断频率,2×n 对应一个机械转内含有的半电气周期数。按组件默认配置MCPWM_CLK_SRC=20MHz、MCPWM_PERIOD=2000,计时周期ALARM_COUNT_US=100µs,POLE_PAIR=5,代入后系数为 60000,即speed_rpm = 60000 / speed_count。三、硬件/接口走读下左图是组件文档给出的功率侧参考:三相全桥(UH/VH/WH 上管、UL/VL/WL 下管)驱动星形绕组,母线 Udc 加在桥臂之间。下右图是信号侧:每相端电压经 1K 分压电阻(R25/R28、R29/R31、R32/R34)接入比较器反相端,等阻 20K 电阻(R25 上方标注 20K 的网络)合成虚拟中性点接比较器同相端,输出经 100R + 100nF 滤波后分别得到 BEMF_1/2/3 三路过零信号,另有一路比较器(U8:2)用于输出端分压参考。硬件要点:三路比较器支路:每相一路,负责把该相端电压与虚拟中性点的比较结果变成数字电平,是过零信号的直接来源;排查时先用示波器确认三路输出在电机转动时确有规律翻转。等阻虚拟中性点网络:R28/R29/R32 等电阻必须同阻值,任一路偏差都会把中性点基准拉偏,导致某一相过零点系统性偏移。输出 RC 滤波:100R 串联加 100nF 对地,抑制 PWM 开关噪声;电容过大则电平翻转滞后,与软件滤波叠加会加大换相延迟。GPIO 接口:三路信号接普通 GPIO,组件按输入模式初始化,active_level字段用于适配比较器输出极性。硬件排查顺序建议:先测三路比较器输出是否随转速稳定翻转,再核对等阻电阻的实测偏差(建议 1% 以内),最后检查输出端滤波电容取值与比较器供电、地线是否干净。四、源码机制走读同步采样:MCPWM on_full 时刻的 64 位移入队列做什么:MCPWM 定时器每次计数到峰值(on_full 事件)时,把三路比较器 GPIO 电平各取一次,逐位移入每相 64 位环形队列。为什么:换相刚发生的窗口内,端电压受续流二极管和开关噪声影响严重,连续读 GPIO 会采到大量脏数据。绑定 PWM 峰值时刻采样,保证每个 PWM 周期只取一个干净的样本点,同时把采样节拍与 PWM 严格同步。在哪做:bldc_control.c 中注册回调,bldc_zero_cross_comparer.c 中实现采样:// bldc_control.c: ALIGNMENT_COMPARER 分支 control->zero_cross = &bldc_zero_cross_comparer_operation; control->cbs->on_full = &read_comparer_on_full; /* 关键:PWM 峰值时刻触发采样 */ config->six_step_config.upper_switch_config.bldc_mcpwm.timer_cb_user_data = (void *)control->zero_cross_handle;// bldc_zero_cross_comparer.c: 每相 64 位队列左移 1 位并入当前电平 static void IRAM_ATTR alignment_comparer_get_value(bldc_zero_cross_comparer_t *zero_cross) { for (int i = 0; i < PHASE_MAX; i++) { zero_cross->alignment_queue_value[i] = zero_cross->alignment_queue_value[i] << 1; zero_cross->alignment_queue_value[i] |= gpio_ll_get_level(&GPIO, zero_cross->alignment_pin[i]); } }怎么调:采样时刻固定在 on_full,无独立参数可调;采样密度由MCPWM_CLK_SRC与MCPWM_PERIOD决定(默认 10kHz PWM),改 PWM 频率时注意队列窗口覆盖的时间随之变化。连续滤波与过零确认:0xFFFF 相同样本判有效做什么:把队列低 16 位与ZERO_CROSS_DETECTION_ACCURACY做按位与,全 1 判该相为高、全 0 判为低、否则判滤波失败并跳过本周期处理。为什么:硬件滤波后仍可能有窄脉冲噪声,"连续多次同电平"的判决能拒绝孤立毛刺,避免把噪声当过零事件触发误换相。滤波失败时filter_failed_count累加,超过 15000 次会被主状态机判为堵转(BLOCKED),这一计数同时是信号质量的在线监测指标。在哪做:bldc_zero_cross_comparer.c:for (int i = 0; i < PHASE_MAX; i++) { if ((zero_cross->alignment_queue_value[i] & ZERO_CROSS_DETECTION_ACCURACY) == ZERO_CROSS_DETECTION_ACCURACY) { zero_cross->queue_filter_state[i] = 1; /* 连续 16 次高电平 */ } else if ((zero_cross->alignment_queue_value[i] & ZERO_CROSS_DETECTION_ACCURACY) == 0) { zero_cross->queue_filter_state[i] = 0; /* 连续 16 次低电平 */ } else { zero_cross->control_param->filter_failed_count++; return 0; /* 滤波失败:本周期不处理 */ } }怎么调:ZERO_CROSS_DETECTION_ACCURACY默认0xFFFF(连续 16 次相同),最大0xFFFFFFFF(32 次)。改大会提高抗噪能力,但电平确认延迟增大、换相整体后移,需与ZERO_CROSS_ADVANCE联动补偿。测速与提前角补偿:speed_count 折算 RPM做什么:以 U 相滤波状态为基准做边沿检测,检测到 1→0 下降沿时,把本半周期累计的speed_count折算成转速,经一阶低通后写回speed_rpm,同时算出提前换向延迟filter_delay。为什么:无传感器方案需要转速反馈给 PID;而比较器检测到的过零点理论上是换向前 30° 电角度到来,加上软件滤波滞后,若立即换相角度会偏晚,需要按当前转速折算出延迟量做补偿。在哪做:bldc_zero_cross_comparer.c,系数定义在 bldc_config.h:#define COMPARER_RPM_CALCULATION_COEFFICIENT (((1000000 / ALARM_COUNT_US) / (2.0 * POLE_PAIR)) * 60) // bldc_zero_cross_comparer.c: U 相状态 1->0 下降沿处 if (filterEdge == 0) { if (zero_cross->zero_stable_flag >= ZERO_STABLE_FLAG_CNT) { speed_rpm = (uint32_t)(COMPARER_RPM_CALCULATION_COEFFICIENT / zero_cross->control_param->speed_count); BLDC_LPF(zero_cross->control_param->speed_rpm, speed_rpm, 0.2); /* 系数 0.2 低通平滑 */ } zero_cross->control_param->filter_delay = zero_cross->control_param->speed_count / ZERO_CROSS_ADVANCE; }怎么调:POLE_PAIR默认 5,必须按电机实际极对数设置,否则转速读数整体成倍偏差。ZERO_CROSS_ADVANCE默认 8,提前角 = 180°/该值(默认 22.5°,略小于理论 30° 以抵消滤波滞后),注释要求不小于 6;改小则换相更提前,过快会过冲,建议用示波器对比实际与理论换相角。六种过零状态到换相动作的映射做什么:滤波后的三相状态(各 0/1)共六种有效组合,zero_cross_comparer_get_phase()输入三相状态与方向dir,返回 1~6 的相位号;相位号变化时bldc_six_step_turn()按方向选择对应的六步数组执行换相。为什么:三相比较器电平的组合恰好唯一编码了当前转子所在的 60° 扇区,查表即可把"电平组合"翻译成"下一步该导通哪两相",无需任何位置积分。在哪做:相位判定在 bldc_zero_cross_comparer.c,换相序列与执行在 bldc_six_step.c:// bldc_zero_cross_comparer.c: 连续稳定后取相位 uint8_t phase = zero_cross_comparer_get_phase(zero_cross->queue_filter_state, zero_cross->control_param->dir); if (phase <= 0 || phase > 6) { zero_cross->control_param->error_hall_count++; /* 非法组合:信号质量异常 */ return 0; }// bldc_six_step.c: 正转六步序列(函数指针数组) static void (*six_step_comparer_cw_array[6])(...) = { &bldc_six_step_UphaseH_VphaseL, /* U 上管 PWM,V 下管导通 */ &bldc_six_step_WphaseH_VphaseL, &bldc_six_step_WphaseH_UphaseL, &bldc_six_step_VphaseH_UphaseL, &bldc_six_step_VphaseH_WphaseL, &bldc_six_step_UphaseH_WphaseL, };方向数组的选择在 bldc_six_step.c:alignment_mode == ALIGNMENT_COMPARER时绑定比较器专用数组,否则绑定 ADC 数组。官方文档中的映射表("1/0" 表示该相比较器输出高于/低于虚拟中性点;"上开下关 / 上关下开 / 上关下关" 表示该相桥臂状态):正转(CW):序号ZERO UZERO VZERO WU 相状态V 相状态W 相状态1001上开下关上关下开上关下关2011上开下关上关下关上关下开3010上关下关上开下关上关下开4110上关下开上开下关上关下关5100上关下开上关下关上开下关6101上关下关上关下开上开下关反转(CCW):序号ZERO UZERO VZERO WU 相状态V 相状态W 相状态1010上关下开上开下关上关下关2110上关下开上关下关上开下关3100上关下关上关下开上开下关4101上开下关上关下开上关下关5001上开下关上关下关上关下开6011上关下关上开下关上关下开说明:仓库文档 bldc_snls_comparer.rst 中两张映射表的表头三列均写作 "ZERO U",结合源码queue_filter_state[PHASE_MAX]为 U/V/W 三相状态数组的事实判断,三列实际依次为 ZERO U、ZERO V、ZERO W,上表按此呈现。怎么调:方向由bldc_control_set_dir(handle, CW/CCW)设置,方向设置必须与电机实际绕线一致,否则会反向或无法启动;调试时观察error_hall_count,持续递增说明三相状态长期落在六种合法组合之外,优先查硬件。五、实践三步第 1 步:添加组件依赖与用户配置文件在项目根目录执行:idf.py add-dependency "espressif/esp_sensorless_bldc_control=*"把 user_cfg/bldc_user_cfg.h 复制到项目的main/目录(保持文件名bldc_user_cfg.h),并在main/CMakeLists.txt中追加(与 test_apps/bldc_comparer/main/CMakeLists.txt 相同):idf_component_get_property(bldc_lib espressif__esp_sensorless_bldc_control COMPONENT_LIB) cmake_policy(SET CMP0079 NEW) target_link_libraries(${bldc_lib} PUBLIC ${COMPONENT_LIB})验证点:idf.py build通过,且不再报bldc_user_cfg.h not found, must provide by user(该报错由 bldc_config.h 的__has_include检查触发)。第 2 步:填写硬件配置结构体参考 test_comparer.c,LEDC 驱动上管、GPIO 驱动下管的最小配置:bldc_zero_cross_comparer_config_t zero_cross_comparer_config = { .comparer_gpio[0] = { .gpio_num = 3, .gpio_mode = GPIO_MODE_INPUT, .active_level = 0 }, /* U 相过零 */ .comparer_gpio[1] = { .gpio_num = 46, .gpio_mode = GPIO_MODE_INPUT, .active_level = 0 }, /* V 相过零 */ .comparer_gpio[2] = { .gpio_num = 9, .gpio_mode = GPIO_MODE_INPUT, .active_level = 0 }, /* W 相过零 */ }; bldc_control_config_t config = { .speed_mode = SPEED_CLOSED_LOOP, .control_mode = BLDC_SIX_STEP, .alignment_mode = ALIGNMENT_COMPARER, /* 关键:选择比较器过零检测 */ .six_step_config = { .lower_switch_active_level = 0, /* 关键:下管有效电平,须与驱动板一致 */ .upper_switch_config = upper_switch_config, .lower_switch_config = lower_switch_config, .mos_en_config.has_enable = false, }, .zero_cross_comparer_config = zero_cross_comparer_config, };验证点:comparer_gpio[i].gpio_num与硬件上 BEMF_1/2/3 的接线一一对应;active_level与比较器输出极性匹配(反接时软件滤波会一直判失败)。第 3 步:初始化、设方向并启动bldc_control_handle_t bldc_control_handle = NULL; bldc_control_init(&bldc_control_handle, &config); /* 初始化硬件驱动 */ bldc_control_set_dir(bldc_control_handle, CCW); /* 设置旋转方向 */ bldc_control_start(bldc_control_handle, 300); /* 以 300 RPM 启动 */验证点:串口日志依次出现BLDC_CONTROL_ALIGNMENT、BLDC_CONTROL_DRAG,稳定运行后打印CLOSED_LOOP事件(事件名表见 bldc_control.c);只停在 DRAG 不进入闭环即说明过零信号未达标。六、排障速查现象可能原因对策比较器 GPIO 长期无规律翻转,进不了 DRAG 后的闭环采样支路断线、等阻电阻偏差大、比较器未供电示波器逐一确认 BEMF_1/2/3 输出;核对 20K 等阻网络阻值一致性(建议 1% 精度)强拖正常但始终进不了 CLOSED_LOOP滤波判决长期失败,filter_failed_count高先把ZERO_CROSS_DETECTION_ACCURACY调大验证;仍无效则查硬件滤波电容与active_level配置闭环后运行抖动、偶尔丢步滤波深度不足,窄脉冲噪声触发误换相ZERO_CROSS_DETECTION_ACCURACY从0xFFFF提到0xFFFFFFFF,并同步减小ZERO_CROSS_ADVANCE补偿延迟电机反转或启动时抖一下再反着转dir与绕线方向不符,或某两相线序接反对调 U/V 两相接线,或bldc_control_set_dir改方向,二者改其一闭环后进入 BLOCKED(日志打印 BLOCKED)filter_failed_count超 15000 被判堵转,信号持续无效观察error_hall_count是否同步递增;递增则为信号质量差,按前两项排查硬件转速读数明显偏离实际值POLE_PAIR设置错误,测速系数成倍偏差按电机铭牌极对数重设POLE_PAIR,读数偏差与设置比应成反比七、关键参数速查以下宏定义在 user_cfg/bldc_user_cfg.h:宏默认值作用调整方向ZERO_STABLE_FLAG_CNT4连续稳定检测到多少个过零后进入无感闭环偏大→进闭环更晚但更可靠;偏小→启动段误判风险高ZERO_CROSS_DETECTION_ACCURACY0xFFFF连续多少次相同采样判为有效电平(16 次)偏大→抗噪强但换相延迟大,需配合减小ZERO_CROSS_ADVANCE;偏小→噪点易通过,filter_failed_count上升ZERO_CROSS_ADVANCE8提前换向分母,提前角 = 180°/该值,要求 ≥ 6偏大→提前角变小、换相偏晚;偏小→换相过提前,角度过冲POLE_PAIR5电机极对数,决定测速系数偏大→转速读数偏低;偏小→读数偏高,须按实际极对设置RAMP_DUTY_STA/RAMP_DUTY_END20% / 40%强拖起始/结束占空比(DUTY_MAX为 1000)偏大→启动扭矩强但易过流;偏小→带载时拉不起来RAMP_TIM_STA/RAMP_TIM_END600 / 90强拖换相间隔的起/止值(单位:gptimer 节拍)偏大→启动平滑但时间长;偏小→快但带载易丢步MCPWM_CLK_SRC/MCPWM_PERIOD20MHz / 2000PWM 时钟与周期(10kHz),决定ALARM_COUNT_US=100µs改变会同步改变测速系数与滤波窗口,需整体复核SPEED_KP/SPEED_KI0.004 / 0.00015速度闭环 PID 增益偏大→跟踪快但易振荡;偏小→响应迟钝、带载掉速八、延伸阅读bldc_overview.rst:BLDC 结构、逆变桥与有感/无感控制方式的总览对比。bldc_snls_comparer.rst:官方对比较器方案的完整说明,含本文两张映射表的原始出处。esp_sensorless_bldc_control.rst:INJECT/ALIGNMENT/DRAG/CLOSED_LOOP 各启动阶段的参数详解与调参提示。bldc_control.c:状态机主体、事件分发与回调注册位置。bldc_zero_cross_comparer.c 与 bldc_six_step.c:过零确认与六步换相的两段核心实现。test_comparer.c:LEDC + GPIO 与 MCPWM 两种配置的完整运行示例,可直接烧录验证。比较器方案的核心链条很短:等阻网络重构虚拟中性点,比较器把端电压比较结果变成三路电平,64 位队列滤波确认过零,再查表映射成六步换相。实际调参时最关键的一条经验是:加深ZERO_CROSS_DETECTION_ACCURACY滤波后务必同步减小ZERO_CROSS_ADVANCE,并用示波器核对实际换相角与理论换相角,换相角度并不是越提前越好。【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考