尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

基于Arduino的BLDC无刷电调DIY:BEMF检测电路详解

发布时间:2026/9/25 1:45:54

资讯中心
01
ARTICLE

基于Arduino的BLDC无刷电调DIY:BEMF检测电路详解

基于Arduino的BLDC无刷电调DIY:BEMF检测电路详解
说实话电调ESC这东西玩航模和无人机的朋友肯定都见过但真正动手自己做一个的人不算多。我自己从“用Arduino点亮LED”一路折腾到“用Arduino把无刷电机转起来”中间炸过管子、烧过芯片、反复查资料才把整套逻辑理顺。这篇就把我做BLDC电调的完整过程拆开重点把很多教程里含糊带过的BEMF检测电路讲透——从原理推导到参数计算再到和Arduino程序的配合一次性说清楚。文章面向已经会Arduino基础编程、能分清楚PWM占空比是什么、手上万用表和电烙铁齐全的朋友。最终你能得到一个能驱动常见小型无刷电机、带BEMF反馈闭环换相的DIY电调也可以进一步改造成智能车、机器人、小型风机等项目的动力模块。项目规模不大但建议先看完全文再动工尤其是BEMF那部分硬件和软件必须配合着设计否则很容易出现“电机转一下就不转”或者“完全没反应”的尴尬情况。1. 为什么需要BEMF检测从BLDC电机结构说起1.1 无刷电机与有刷电机的根本区别有刷直流电机大家很熟悉两根线一接转子通过换向器和电刷自动切换绕组里的电流方向电机就转起来了。BLDC无刷直流电机去掉了电刷和换向器转子换成永久磁铁定子是三相星形绕组。好处是寿命长、效率高、噪音小但代价是“谁来换相”这件事落到了外部驱动电路头上。要让定子磁场始终领先转子磁钢一点角度持续拖动转子旋转外部就必须根据转子位置依次让三相绕组中的两相通电、一相悬空。这个过程叫电子换相也叫六步换相。1.2 六步换相与转子位置六步换相其实就是在一个电气周期里按固定顺序切换六个通电状态。每个状态持续60°电角度六个状态恰好完成一个完整的360°电周期。状态导通上管导通下管悬空相电流方向Step 0ABCA → BStep 1ACBA → CStep 2BCAB → CStep 3BACB → AStep 4CABC → AStep 5CBAC → B每次换相之前都必须知道转子当前在什么位置。带霍尔传感器的电机内部霍尔元件直接告诉控制器转子扇区无传感器方案则靠检测悬空相的反电动势BEMF用算法推算换相时机。1.3 为什么DIY电调首选无感方案霍尔方案逻辑简单但很多BLDC电机出厂时不带霍尔接口不想换电机就只能做无感。而且霍尔线多、安装位置讲究、信号也容易被大电流干扰在DIY场景里非常不方便。无感方案只靠三个分压电阻网络加一个比较器就能在悬空相上“偷听”转子位置信息成本低、体积小、适应性强。所以自己做电调首选就是无感的BEMF检测方案。到这里你应该明白了无感BLDC电调的核心难点就是怎么准确检测悬空相的反电动势过零也就是接下来要重点拆解的BEMF检测电路。2. BEMF检测电路详解原理与参数计算2.1 反电动势是怎么产生的电机绕组在磁场中旋转会产生反电动势数值上正比于转速和磁场强度简单写就是 e Ke × ω。对于星形连接的BLDC电机当某一相不参与通电时该相端电压并不是0而是包含两部分绕组内部感生的反电动势和三相星形中点电压。具体来说悬空相端电压 V_z e_z V_n其中 e_z 是悬空相反电动势V_n 是星形中性点电压。当转子旋转时悬空相反电动势在正负之间变化必然会穿过0伏。这个过零点恰好落在前后两次换相的正中间也就是距离上一次换相30°电角度的位置。2.2 检测原理端电压法检测过零最常用的方法是端电压法。把悬空相端电压与虚拟中性点电压进行比较悬空相分压后的采样电压V_sample K × (e_z V_n)虚拟中性点参考电压V_ref K × V_n当 e_z 过零时V_sample 等于 V_ref比较器输出发生跳变。只要在每次换相后只关注当前悬空相的比较器输出就能拿到过零信号。这里不能直接把Arduino的ADC引脚接到相线上原因有三个一是母线电压可能超过5V会烧引脚二是PWM开关噪声非常严重三是电机绕组处于悬空状态直接测量会引入很大的共模干扰。所以先分压再低通滤波最后交给比较器判断。2.3 硬件电路与关键参数计算我用的电路如下以12V供电为例A、B、C三相分别接一个R1100kΩ上分压电阻对地接R247kΩ下分压电阻。三个分压中点除了送到各自比较器外还通过一个100kΩ电阻相连形成虚拟中性点。虚拟中性点再接一个10kΩ电位器做微调送到三个比较器的反相端。分压比 K R2 / (R1 R2) 47 / (100 47) ≈ 0.32。假设母线12V星形中点理论上是6V那么虚拟中性点分压后约 6V × 0.32 1.92V。悬空相BEMF的电压摆幅通常不会超过半个母线电压所以分压后的采样电压大致在1V到2.8V之间这个范围对LM393比较器来说非常舒服。比较器用LM393工作电压5V输出为开漏结构需要接上拉电阻到5V。比较器同相端接当前悬空相的分压采样值反相端接虚拟中性点参考电压。当悬空相BEMF从正往负穿越零点时V_sample 从大于 V_ref 变为小于 V_ref比较器输出跳变。Arduino根据当前换相步骤只选择对应悬空相的比较器输出引脚来判断过零事件。为了滤除PWM噪声每个分压中点再加一节RC低通滤波。我选R1kΩ、C15nF截止频率 fc 1 / (2πRC) ≈ 10.6kHz。这个频率低于20kHz的PWM载波能衰减一部分开关噪声对于电机电气频率从几十Hz到几kHz的BEMF信号来说衰减和相位延迟都比较小适合入门调试。如果想更彻底地滤掉PWM噪声可以把C加到33nF甚至47nF但要注意过零信号相位会滞后软件里需要做相应补偿。参数数值作用R1100kΩ分压上臂减小对BEMF信号的负载效应R247kΩ分压下臂输出到比较器和虚拟中性点RC滤波1kΩ 15nF滤除PWM噪声截止频率约10.6kHz比较器LM393开漏输出单电源5V即可比较器上拉10kΩ 到5V让开漏输出转换成数字电平迟滞电阻1MΩ正反馈防止过零信号抖动虚拟中性点微调10kΩ电位器校准电阻误差与中点漂移2.4 PWM噪声对过零检测的影响与分析这里有个新手特别容易踩的坑PWM开和关的瞬间悬空相端电压会有非常明显的尖峰和振荡如果不管它比较器会输出一堆无用的翻转换相直接乱套。解决思路主要有两条。第一条是在比较器前加RC低通滤波让比较器看到的是平滑后的BEMF波形。第二条是让检测发生在PWM的某个稳定时刻比如在PWM OFF期间采样。对Arduino DIY来说RC加迟滞比较器最省事软件只需要处理可能的抖动导致误触发。另外虚拟中性点也要走同样的分压和滤波路径否则比较器两端共模噪声没法抵消后面会频繁误判。我见过有人只给三相采样滤波没给虚拟中性点滤波结果电机转速稍高就开始一顿一顿的就是共模噪声造成的。还有一个细节比较器输出是开漏结构不同相的比较器输出不要直接并在一起。我当初图省事想把三路输出合并成一个引脚结果在悬空相切换时出现电平互拉导致过零事件全部丢失。正确做法是三路分别接Arduino的三个输入引脚然后在中断或查询逻辑里根据当前状态选对应引脚。3. 硬件搭建驱动桥、栅极驱动与电源3.1 器件清单与选型理由完整的BOM参考如下类别型号/规格数量说明主控Arduino Nano / Uno1引脚兼容开发方便栅极驱动IR21043半桥驱动器自带自举和死区MOSFETIRLZ44N 或 AO44046逻辑电平NMOSRDS(on)约0.022Ω比较器LM3931开漏输出也可用LM339采样电阻100kΩ、47kΩ、1kΩ若干分压和滤波滤波电容15nF、100nF、10uF、470uF若干PWM滤波与电源去耦上拉/迟滞电阻10kΩ、1MΩ若干比较器外围电源12V直流电源或3S锂电池1起步或堵转时电流会很大电机小型无刷电机1比如2212、2204航模电机为什么用IR2104而不是三极管搭半桥因为IR2104内部集成了死区时间和自举升压电路一个输入引脚就能控制上下两个MOSFET能极大简化控制逻辑。而且它的逻辑输入兼容5V和3.3V直接接Arduino没问题。MOSFET选型要注意三点首先必须是逻辑电平MOSFET栅极阈值电压最好在3V到5V以内IRLZ44N就是专门为5V驱动设计的其次看RDS(on)导通电阻越小大电流时发热越少最后看封装面包板原型阶段用TO-220封装的IRLZ44N方便插拔定型之后可以换贴片AO4404这类小封装。3.2 三相全桥与IR2104驱动三相全桥由三个半桥组成。每个半桥包含上管和下管IR2104的HO和LO分别驱动它们VB和VS之间接自举电容。因为上管处于浮动地栅极驱动电压需要比母线电压更高内部自举电路配合外部电容就能实现省掉了额外的隔离电源。自举电容我推荐1uF的X7R陶瓷电容工作频率在20kHz附近完全够用。电容太小上管导通后电压下降明显表现为PWM占空比大时电机没劲电容太大自举充电时间过长启动阶段上管导通不充分同样要避免。接线时每相逻辑如下半桥AArduino PWM引脚 → IR2104的INArduino普通IO → IR2104的SDHO → A相上管栅极LO → A相下管栅极半桥B、半桥C同理重复三次。六步换相时状态机每进入一个状态就把对应上管的IN设置为PWM信号对应下管的IN拉低且SD拉高让下管常通悬空相的SD拉低关闭两个输出。这样任意时刻每相最多只有一个MOSFET导通IR2104内部死区时间又能防止直通逻辑非常清晰。3.3 电源与布线避坑电源部分有两个容易忽略的点。第一母线两端必须加大容量电解电容我习惯用470uF/25V以上用来吸收MOSFET开关瞬间产生的电流尖峰。第二Arduino的5V供电和电机大电流的地不能共用一条长地线最好做到一点接地动力地的电流不要流过Arduino的地线否则Arduino会随机重启。如果使用3S锂电池IR2104的VCC可以接到Arduino的5V也可以单独用降压模块供电关键是不要让电机瞬时大电流把控制电压拉垮。面包板搭功率级并不是长久之计。MOSFET开关节点的电压变化率非常高面包板的寄生电感会产生振铃严重时甚至炸管。逻辑调通之后建议第一时间转到洞洞板或画个小PCB。4. Arduino软件实现六步换相与闭环控制4.1 引脚分配与PWM频率配置先给一张引脚分配表功能Arduino引脚半桥A INPWMD9半桥A SDD8半桥B INPWMD10半桥B SDD7半桥C INPWMD11半桥C SDD6油门输入电位器A0比较器A输出D2外部中断0比较器B输出D3外部中断1比较器C输出A1查询A、B两相的比较器接硬件中断引脚C相用查询方式读取。如果比较器C也想要中断Arduino Nano只有两个外部中断引脚可以换用Pro Mini或其它支持更多中断的板子。查询方式只要主循环跑得够快中低速电机完全没问题。PWM频率必须改。Arduino默认analogWrite频率是490Hz或980Hz驱动电机时会发出刺耳噪音电流纹波也大。需要重新配置定时器把PWM频率提到20kHz左右。Timer1控制D9和D10配置成Fast PWM模式void setupTimer1PWM20k() { TCCR1A _BV(WGM11) | _BV(COM1A1) | _BV(COM1B1); TCCR1B _BV(WGM13) | _BV(WGM12) | _BV(CS11); // 预分频8 ICR1 99; // 16MHz / (8 * 100) 20kHz OCR1A 50; // D9 占空比约50% OCR1B 50; // D10 占空比约50% }D11由Timer2控制类似地可以将Timer2配置成快速PWM模式预分频8OCR2A99同样能得到20kHz左右的PWM。由于占空比最终要跟随油门实时变化实际代码里在换相函数中根据油门值动态设置OCR寄存器即可。4.2 六步换相状态机与过零处理状态机的核心是一张6元素的换向表每个状态定义三相各自的工作模式上管PWM、下管导通或悬空。// 三相状态: 0悬空, 1上管PWM, 2下管导通 const uint8_t commTable[6][3] { {1, 2, 0}, // step 0: A上PWM, B下通, C悬空 {1, 0, 2}, // step 1: A上PWM, C下通, B悬空 {2, 1, 0}, // step 2: B上PWM, A下通, C悬空 {0, 1, 2}, // step 3: B上PWM, C下通, A悬空 {2, 0, 1}, // step 4: C上PWM, A下通, B悬空 {0, 2, 1} // step 5: C上PWM, B下通, A悬空 };每次换相根据 commutationStep 查表设置三个半桥的IN和SD引脚。比如step 0时A半桥IN给出油门PWM且SD拉高B半桥IN拉低且SD拉高让下管常通C半桥SD拉低全部关闭。这样A相上管做PWM调制B相下管持续导通C相悬空正好对应一个标准通电状态。过零事件处理的核心逻辑是比较器输出翻转意味着悬空相BEMF已经过零。按照六步换相规则下一次换相应在30°电角度之后。软件只需要记录过零发生的时刻再用当前转速换算延时到时间后执行下一次换相。volatile unsigned long lastZeroCrossTime 0; volatile bool zeroCrossDetected false; void isrBemfA() { // 只有当 A 相是当前悬空相时才记录过零 if (commutationStep 0 || commutationStep 3) { lastZeroCrossTime micros(); zeroCrossDetected true; } }这里必须加状态判断只处理当前悬空相的比较器中断避免其它相噪声引起误触发。B、C两相的中断函数做同样处理只是判定的step号不同。4.3 开环启动流程与闭环切换无感BLDC电机静止时没有BEMF无法直接进入闭环检测所以要先“拽”它转起来。最常用的方法是开环强制换相按固定油门占空比以固定时间间隔依次送六个状态让定子磁场强制拉着转子转。随后逐渐减小换相间隔相当于加速当转速达到一定值BEMF信号足够大再切成闭环模式。我的启动流程如下设置启动占空比比如40%。初始换相周期20ms大约是每秒换五次相让电机缓慢定位和拖动。每个换相周期结束就把周期缩短0.5ms直到最小3ms。当换相周期小于等于3ms并且连续检测到3次有效的过零中断就判定转速足够切到闭环。闭环模式下过零中断负责更新换相时间PWM占空比由油门输入决定。简化代码框架void runStartup() { if (commutationPeriod MIN_STARTUP_PERIOD) { scheduleNextCommut(commutationPeriod); commutationPeriod - 0.5; } else { motorState MOTOR_CLOSED_LOOP; } }实际调试时启动占空比和换相周期必须按电机调整。占空比太低电机拖不动太高可能跳过换相点甚至反转。刚开始不确定时优先选择更保守的启动周期让电机慢慢找感觉再用串口打印换相周期观察变化。4.4 关键代码实现把完整工程贴出来太长但核心循环逻辑可以浓缩成三块初始化、换相、过零处理。主循环的结构大致如下unsigned long nextCommutationMicros 0; int commutationPeriodMicros 20000; // 启动时20ms uint8_t commutationStep 0; uint8_t motorState MOTOR_STOP; void loop() { throttle map(analogRead(THROTTLE_PIN), 0, 1023, 0, 100); switch (motorState) { case MOTOR_STOP: // 等待油门大于5% break; case MOTOR_STARTUP: runStartup(); break; case MOTOR_CLOSED_LOOP: runClosedLoop(); break; } } void runClosedLoop() { if (zeroCrossDetected) { unsigned long now micros(); int halfStepDelay (now - lastCommutationMicros) / 2; nextCommutationMicros now halfStepDelay; zeroCrossDetected false; } if (micros() nextCommutationMicros) { doCommutation(); } }这段代码里lastCommutationMicros 在每次 doCommutation 时更新。过零之后延迟当前半周期时间也就是30°电角度再执行下一次换相。动态估算的思路在转速变化不剧烈时非常稳足够覆盖大多数DIY应用。中断函数里只做轻量操作不要放delay或analogWrite否则会破坏实时性。我的ISR里只记录时间戳和置标志真正的换相安排全部放到主循环里完成。5. 调试心得与常见问题排查5.1 症状、原因与排查速查表症状可能原因检查思路电机完全不动供电不足、SD引脚未使能、油门信号没读到先单独测Arduino引脚电平确认各半桥SD为高电机抖动但不转启动换相周期太快或占空比太小启动周期调长到20ms占空比调到30%~50%电机启动时反转换向表顺序反了交换任意两相的物理接线或者把换向表倒序转起来后一加负载就停BEMF信号被噪声淹没或过零判断滞后检查RC滤波参数和迟滞电阻尝试加大滤波电容高速时噪音大、掉转速PWM频率太低或死区不足把PWM频率提高到20kHz以上检查IR2104供电烧MOSFET或芯片母线电压过高、接线错误、地线过长检查电源电压确认上下管无直通加母线去耦电容5.2 我的几次翻车记录第一次上电我只给驱动部分送了电忘了给Arduino供电结果IR2104的SD引脚悬空上下管全部导通母线直接短路当场烧掉两个MOSFET。之后我养成了一个习惯程序初始化时先把所有使能引脚全部拉低确认无输出后再开主电源。还有一次电机空转非常顺但一加载就停串口打印看到过零中断异常频繁。查到最后发现虚拟中性点被我接错了接在了某一相的分压中点上导致参考电压跟着PWM波动。把三个分压电阻的中点都连到公共节点后问题立刻消失。这类问题往往不是大故障而是某个细节接错。排查时不要急着改程序先用万用表按照原理图把每个分压节点的电压量一遍尤其是虚拟中性点电压要稳定在理论计算值附近。5.3 调试工具建议做电调调试示波器是最好用的工具不用多高端几十块钱的逻辑分析仪配合虚拟示波器也能看波形。重点观察三个位置MOSFET栅极波形确认上下管没有直通风险悬空相分压后的波形看BEMF是否清晰、过零点是否稳定比较器输出波形看是否产生连续干净的翻转信号。如果没有示波器也可以用万用表量比较器输出在电机低速时的静态电平再用LED接在比较器输出上观察转速变化时LED闪烁频率是否跟随。这个方法虽然粗糙但能快速判断过零信号到底有没有产生。调电调强烈建议准备一个具备电流限制功能的直流稳压电源把限流设置到1A左右。这样即使接线错误短路电源也不会输出大电流能少炸几次管子。这是DIY电力电子项目里最值得的一笔投入。最后再分享一个实在的经验这类项目不要追求一次成功。我第一次完整搭出来到稳定运行前后花了三个晚上。第一晚全搭好灯亮但电机纹丝不动第二晚排除了逻辑接线问题电机开始抖动但还是不转第三晚把启动时序和BEMF滤波参数调好电机才真正稳定转起来。如果一次没成功大概率不是能力问题而是某个细节没对上。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。