多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

步进电机控制方案:DRV8818与PIC18F46K20的精确位置驱动实践

步进电机控制方案:DRV8818与PIC18F46K20的精确位置驱动实践 在工业自动化这类场景里步进电机控制如果用分立MOS管搭H桥调试成本远比想象中高。DRV8818PWPR加PIC18F46K20这套组合是我近两年在几台小型机器人关节、桌面型三轴平台上反复用过的一套方案很适合那些不想在电机驱动部分重复造轮子、同时又需要把位置控制做得比较稳定的项目。DRV8818负责把电流环和功率桥全部吃掉单片机只做脉冲、方向和使能信号逻辑非常干净排查问题也容易。这篇文章就把这套方案的选型逻辑、硬件电路、固件实现和常见坑一次讲清楚。我最早接触DRV8818PWPR时对这颗芯片的态度是半信半疑的。毕竟之前做步进驱动习惯用A4988那种模块或者干脆自己搭分立MOSFET桥。但随着项目从原型往小批量走分立方案的痛点越来越明显器件离散性大、栅极驱动电路要额外设计、过流保护全靠自己写逻辑每块板子的一致性问题尤其折磨人。后来换用DRV8818之后整块驱动电路面积缩小了将近一半故障率也明显下降。这不是说DRV8818有多神而是它把真正难的部分——电流斩波、H桥互锁、短路保护——在芯片内部做好了留给我的只是把STEP和DIR两路信号做干净。PIC18F46K20在整个系统里扮演的是运动控制大脑的角色。这颗单片机主频最高64MHz在这种只发脉冲的任务里好处是实时性比较好中断响应稳定不会因为算术运算或串口任务导致脉冲抖动。另一个让我选它的理由是5V兼容性虽然实际工作电压是3.3V但很多工业传感器接口仍然是5V电平PIC18F46K20的引脚耐压特性让电气接入时不用加一大堆电平转换。1. 整体方案设计与选型思路1.1 为什么选择DRV8818PWPR而不是模块或分立德做设计之前先把需求列清楚。我的目标场景是工业和机器人应用中的小功率轴控制电机额定电流大多在0.3A到2.0A之间供电电压12V到36V。这类负载有一个共性力矩不大但对位置重复性和低速平稳性有要求而且空间往往紧张控制板最好和驱动器挨在一起。如果是用现成模块比如A4988板子好处是便宜、采购快缺点也很明显板子质量参差不齐散热能力差遇到24V以上的应用时的余量不足而且模块的布局为了兼容各种单片机引线往往很长脉冲信号到了高频时容易受干扰。自己用分立MOSFET做H桥呢光是栅极驱动芯片就要选型还要考虑死区时间、米勒平台、体二极管应力这些细节对于一个“以运动控制为主”的项目来说这些投入太不划算。DRV8818PWPR的特性刚好卡在两者之间。这是一个集成双路H桥的双极步进驱动器峰值电流做到2.5A供电范围8.2V到35VHTSSOP-16封装面积比模块小两三个量级。它内部自带电流检测和斩波控制只需要设置一个参考电压或者取样电阻就能让驱动器在一个固定电流下工作不需要单片机参与电流环计算。对大多数工业应用来说这种“功率部分黑盒化”的做法非常合理因为电机电流环的PID响应时间在微秒级而8位MCU的中断周期很难稳定做到10微秒以下硬要去写电流环结果大概率是发热和噪声。1.2 为什么用PIC18F46K20而不是更高端的MCU选择PIC18F46K20这部分很多人不理解觉得既然做机器人为什么不直接上STM32或者更高性能的芯片。我的理由比较朴素这类步进轴的实时性要求不是那种“必须在1微秒内响应外设事件”的级别它需要的是长期稳定的PWM脉冲输出和可靠的中断调度。PIC18F46K20在定时器中断下的抖动实测能做到几十纳秒级别这已经足够产生精确的步进脉冲了。更重要的是PIC18F46K20的外围接口非常直接没有复杂的复用关系。它的PORTD可编程方向用一个LAT寄存器控制输出配置极简。对于步进驱动这种接口最怕的就是MCU管脚被内部外设偷偷改掉方向PIC18系列的设计风格是“寄存器做加法”每个功能模块开关明确调试时少了很多猜谜时间。另外一个考虑是工作温度范围。PIC18F46K20有几个型号支持-40℃到125℃在工业现场控制柜内部温度经常冲到70℃以上这个余量很重要。加上有内置PLL外部只需要一个8MHz或者16MHz晶振就能跑到64MHz减少了高频晶振对低速电机信号线的辐射干扰。1.3 整体系统架构整套系统的信号流是这样的PIC18F46K20根据上位机指令通过运动规划模块计算出当前想要的速度和位置。定时器中断按照计算好的步距时间产生STEP脉冲同时控制DIR方向引脚。STEP和DIR直接进入DRV8818PWPR芯片内部根据这两个信号和衰减模式设置的搭配驱动A、B两相输出。电机母线电压通过电源模块给DRV8818供电电流参考由取样电阻决定整块驱动板不需要额外的运算放大器。这种架构最大的优势是层级清晰。单片机不管电机线圈里的斩波细节只管“走多少步、多快走”驱动器不管运动学算法只管把脉冲变成电流。两者之间的接口协议实际上就是工业领域通用的STEP/DIR协议这意味着以后把MCU换成其他型号或者把驱动器换成其他品牌改动成本很低。2. 核心硬件电路设计细节2.1 引脚分配与电源方案DRV8818PWPR的关键引脚可以分成几组逻辑电源VCC通常3.3V或5V、电机电源VM、地线GND、功率输出AOUT1/AOUT2/BOUT1/BOUT2以及控制输入STEP、DIR、ENBL、SLEEP和衰减模式配置引脚。PIC18F46K20在电路板上的连接通常是这样PIC18F46K20引脚信号名连接到DRV8818RD0STEPSTEP经1kΩ串联电阻RD1DIRDIR经1kΩ串联电阻RD2ENABLEENBL经反相逻辑或直接配置RD3DECAY0衰减模式配置引脚ARD4DECAY1衰减模式配置引脚BRD0到RD4这五个引脚全部设置为数字输出不需要模拟功能所以PIC18F46K20上对应的ANCON寄存器要把模拟通道关闭。这个细节往往被忽略——PIC18系列单片机上电后模拟引脚默认可能开启如果忘了关ANSEL寄存器明明配置了输出引脚却因为内部的模拟输入缓冲而无法正常释放电平导致STEP信号一直拉不高这是新手上手时最典型的翻车现场之一。电源方面逻辑部分用3.3V给PIC供电DRV8818的VCC也接3.3VVM接电机电源。需要注意DRV8818的逻辑电源和功率地之间要有单点连接或者磁珠隔离防止电机负载变化时逻辑地被大面积拉偏。在布线时VM和GND之间至少要放一个47uF电解电容和一个100nF陶瓷电容两个电容尽量靠近VM引脚。陶瓷电容负责吸收高频毛刺电解电容承担低频能量。电机线的走线尽量远离STEP和DIR信号线否则细长电机线充当天线时放电噪声会耦合进去高速脉冲直接丢失。2.2 衰减模式配置与电流限值设置双极步进电机的绕组是一个感性负载电流不能突变H桥关断时线圈里的电流需要一个泄放路径。DRV8818提供了不同的衰减模式简单理解就是电流续流阶段是让它快速跌到零还是慢慢衰减到目标斩波点。选择哪种模式会影响电机的噪声、发热和高速性能。快速衰减模式下电流纹波大但高速跟进性好慢衰减模式下电流纹波小、噪声低但在某些速度点容易发生电流失控。混合衰减模式介于两者之间。DRV8818的衰减模式引脚通常有两个配置位通过接高电平或低电平组合来选择。实际测试中大多数中小负载电机用慢衰减模式比较安静低速走起来顺滑到了需要跑高速的场合再把衰减模式切到快速衰减。为了方便现场调试我在驱动板上预留了两个跳线帽排针通过跳线帽改变衰减模式的状态。比起在程序里折腾一个GPIO去控制跳线帽的做法从物理上排除程序逻辑错误调试阶段能节省不少时间。电流限值的设置直接决定电机的力矩和热量。DRV8818使用一个取样电阻R-SENSE来检测H桥下管电流电阻的阻值决定了斩波阈值。具体计算公式各厂家的规格书都有我这里重点说工程上的选择流程先查电机规格书找到额定电流。根据额定电流计算所需参考电压再用参考电压除以取样电阻得到电流目标。取样电阻的功率余量至少取峰值的2倍以上防止电阻过热漂移。实机上电后用电流探头测一下实际绕组峰值电流再用热成像仪看驱动芯片和电阻的温度根据温度和噪音微调阻值。这套流程看着繁琐但凡是直接按照电机铭牌电流设定限值就完事的十有八九会遇到“低速走得好好的连续跑半小时后芯片热保护”的情况。原因很简单电机和驱动器都在发热如果余量不足任何一点热漂移都会让系统进入不稳定区间。2.3 PIC18F46K20最小系统与复位PIC18F46K20本身自带内部振荡器但我在这个项目中仍然选择外接16MHz晶振然后开启PLL倍频到64MHz。原因有两个内部振荡器的频率精度虽然够用于普通单片机逻辑但步进脉冲的周期抖动会对电机的匀速性产生直接影响内部RC振荡器受温度影响在±2%左右而晶振做到50ppm以下很容易。运动轴在轻微变速和匀速之间转换时耳朵可能听不出区别但示波器上能看到脉冲间隔的离散性这会转化成低速段的微振动。复位电路我接了一个经典的10kΩ上拉电阻加100nF电容到MCLR引脚没有加外部复位IC。工业环境中如果电源跌落太多这个简易复位电路偶尔会不可靠实际大批量生产时建议加上带电压检测的复位芯片。对于样机阶段RC复位足够。需要补充的一点PIC18F46K20有一个看门狗定时器WDT默认可能是关闭的但工业应用中我通常会把WDT打开超时时间设置得保守一点。这样即使程序跑飞或者进入死循环单片机也能自动复位。看门狗复位之后程序要快速初始化并恢复电机使能状态防止机器人关节在复位瞬间失去保持力矩。3. 固件与运动控制实现3.1 初始化代码与关键寄存器配置用XC8编译器写PIC18F46K20的初始化头几个关键寄存器要设置清楚。下面这个初始化函数是我实际项目里抽出来的简化版可以直接参考。#include xc.h // 配置位外部晶振4倍PLL关闭低电压编程打开看门狗等 #pragma config FOSC HSPLL #pragma config WDTEN ON #pragma config PWRTEN OFF #pragma config MCLRE ON #pragma config LVP OFF #define STEP_PIN LATDbits.LATD0 #define DIR_PIN LATDbits.LATD1 #define ENABLE_PIN LATDbits.LATD2 void System_Init(void) { // 关闭模拟输入确认RD0-RD4是数字IO ANCON0 0x00; ANCON1 0x00; // 设置PORTD低5位为输出 TRISDbits.TRISD0 0; TRISDbits.TRISD1 0; TRISDbits.TRISD2 0; TRISDbits.TRISD3 0; TRISDbits.TRISD4 0; // 初始状态禁止电机方向为正STEP为低 ENABLE_PIN 1; // 根据DRV8818的ENBL极性决定通常是低有效 DIR_PIN 0; STEP_PIN 0; // 配置Timer016位模式用于产生步进脉冲节拍 T0CON 0x01; // 定时器0使能8位预分频16位模式 INTCONbits.TMR0IE 1; INTCONbits.GIE 1; }这段初始化做了几件重要的事情关模拟通道、方向配置、初始电平、定时器中断开启。很多人写步进程序时容易忽略模拟通道的禁用结果折腾半天发现IO不听话其实就是ANCON的问题。ENABLE引脚的极性必须对照DRV8818规格书看清楚不同批次或型号可能有差异如果逻辑反了电机一上电就锁死不动还会听到持续的高频啸叫。3.2 步进脉冲产生的几种方式对比产生一个精确的STEP脉冲在程序实现上有几种选择。最传统的方式是放在定时器中断里翻转电平void __interrupt() T0_ISR(void) { if (INTCONbits.TMR0IF) { INTCONbits.TMR0IF 0; // 重装定时器初值 TMR0H timing_high; TMR0L timing_low; // 输出步进脉冲脉宽由定时器触发的瞬间产生 STEP_PIN 1; __delay_us(10); // 简易方式实际项目建议用另一个定时器或延时 STEP_PIN 0; } }这种写法理解起来很直观但有一个隐含问题在中断里用__delay_us(10)是忙等待如果步进频率很高这个延时占用的时间会导致整个中断循环周期不可预测。处理办法是把脉冲宽度做进一个简单的状态机里或者用PWM硬件模块生成脉宽MCU软件只负责触发。对PIC18F46K20来说用硬件PWM模块产生固定宽度的STEP是一个更稳的方案。比如设置一个周期和脉宽都固定的PWM主循环负责切换它的使能状态。这样脉冲宽度完全由硬件保证不占CPU时间适用于高速步进场景。不过这种方案的缺点是调整频率不方便适合那种速度档位固定的应用。我实际用的是一种折中方案定时器中断负责产生一个“半步周期”标志然后在主循环或者更高级的中断里翻转STEP。这种方式的脉冲宽度取决于循环调度的间隔写代码时要保证翻转动作足够快同时避免在中断里调用耗时的函数。对于大多数低速和高频应用这个方案的表现都很稳定。3.3 梯形加减速与运动规划如果单片机只是把上位机传来的脉冲个数原封不动地转发给驱动器那时间长了就会发现一个严重的问题电机会在启动和停止瞬间产生“咚”的冲击轻则噪声大重则丢步。这是加速度突变的直接后果。步进电机没有速度反馈一旦负载超过动态力矩转子就跟不上脉冲序列进入失步状态。工业项目中常用的解决方法是梯形加减速电机速度从0逐渐增加到目标速度然后匀速运行接近目标位置时再减速到0。实现上不需要复杂的数学库一张预设延时表就可以。比如加速段从5kHz到20kHz分成32级每一级对应一个Timer0初值驱动脉冲的间隔按照这张表逐级缩短。const unsigned int speed_table[32] { 4000, 3600, 3200, 2900, 2650, 2450, 2250, 2100, 1950, 1830, 1720, 1620, 1530, 1450, 1380, 1310, 1250, 1200, 1150, 1110, 1070, 1040, 1010, 980, 960, 940, 920, 900, 885, 870, 855, 840 }; unsigned char table_index 0; unsigned char accel_state 1; // 1加速0匀速-1减速每次Timer0中断里根据accel_state更新table_index再把speed_table[table_index]写入定时器寄存器。匀速时table_index保持不变减速时递减即可。这套逻辑虽然简单但在实际项目中的表现非常稳定电机运行声音从“咔咔咔”变成均匀的“嗡嗡”机械振动也小不少。做加减速表的时候有一个要点级数过少会导致速度跳变仍然明显级数过多会占用太多Flash通常一个轴32级表就够用。要更平滑的话可以用S型曲线但边际收益有限特别是对于小惯性负载。3.4 多轴协同时的引脚扩展一台机器人往往有三四个轴PIC18F46K20的IO数量够不够用取决于你选择“每轴一个独立驱动器”还是“共用一个驱动器加切换逻辑”。比较常规的做法是每个轴一个DRV8818这样每一路都有独立的电流设置和衰减配置。PIC的PORTD可以扩展出多个STEP/DIR信号如果IO不够可以用74HC595或者8255扩展。不过在实际项目中我更建议优先用时间换空间一个定时器中断按时间片轮流为多个轴服务。每个轴各自维护一套速度表和位置计数器中断里扫描到哪个轴就更新哪个轴的STEP输出。这样硬件上少几个芯片代码上多点复杂度对于3轴以下的小型机器人这种方法完全够用。4轴以上时时间片轮流方式会碰到顶部频率限制因为每根轴需要的脉冲间隔最小只有几十微秒假若4根轴都要跑高速单个中断循环的负载会饱和。4. 常见问题与排查技巧实录4.1 电机完全不动但电源正常这是最常被问的问题。先看使能信号DRV8818的ENBL引脚一般在低电平时才让输出桥工作。很多人初始化时直接输出低但如果上电顺序不对比如MCU晚于驱动芯片上电ENBL引脚在悬空期间被内部上拉拉到高电平驱动器就一直处于禁止状态。解决方法是加一个下拉电阻在ENBL引脚默认禁止等MCU初始化完成后再主动拉低。然后是STEP脉冲宽度。DRV8818要求STEP保持高电平时间至少1微秒如果单片机输出的高电平太窄芯片不会识别。用示波器看STEP引脚确认脉冲宽度和频率是否正常。这里有个容易忽略的点单片机IO输出能力有限如果驱动线的寄生电容太大上升沿会被拉长导致脉冲变形试着把STEP串联电阻从0改成100Ω再用示波器观察沿变化。4.2 电机抖动但不连续转动抖动但是不转本质上就是有电流穿过绕组但A/B两相的通电顺序不对或者电流强度不够。先检查DIR和电机相线连接顺序双极步进电机有四根线两两导通如果A相和B相交错了换相顺序就会变成同一相的两半交替导通力矩互相抵消。另一个常见因素是电流限值设置得太低。电机规格书上的额定电流是RMS值而DRV8818的限流参考很多情况下是峰值两者之间差了1.414倍。如果直接用额定电流作为限流目标实际力矩只有标称的一半左右这种情况下电机会表现为空载能转一点带负载就抖动。可以逐步把限流参考往上调同时用点温枪监控芯片温度在不超过85℃的前提下找到平衡。低速抖动还有一个容易被忽略的原因衰减模式不匹配。前面提到慢衰减噪声小、快衰减高速好但实际试下来有些电机在某种衰减模式下会表现出明显的步间振荡。这时不要急着改机械结构先跳线切换一下衰减模式往往立竿见影。4.3 芯片温度异常升高DRV8818发热是正常现象但直接烫得摸不住就要检查。用红外点温枪测芯片表面如果超过100℃先排除电流限值设定偏高。其次看开关频率DRV8818的内部PWM频率和衰减模式的选择会影响开关损耗频率过高时开关损耗占比上升频率过低时电流纹波变大导致导通损耗增加。在规格书推荐范围内选择一个中间值再观察。还有很多人会忽略散热焊盘的连接。HTSSOP-16封装的底部有散热焊盘必须焊接到PCB的地铜皮上并且地铜皮要尽量大面积铺铜再打过孔到背面。如果PCB设计时没把散热焊盘处理好哪怕电流只有1A芯片温度也可能冲到110℃以上。这个问题在手工焊接时尤其严重需要确认锡膏是否充分覆盖了底部焊盘。4.4 丢步与位置偏移丢步是最难排查的故障之一因为有时候电机会恢复同步但位置已经错了。常见原因有三类机械负载过大、加速度过陡、电流不足。我的排查顺序是先减小加速度表和最高速度如果问题不再出现说明加减速曲线需要放缓。如果速度降下来了仍然丢步就需要提高电流限值或者换大一号电机。极少数情况下是脉冲信号受干扰这时把STEP和DIR线各自加一个低通RC滤波器放到电机线和控制线交叉之前。还有一个技巧在固件里做一个位置校验功能。用步数计数到达目标后让电机多走一个极低速的“校准步”或者标定一个零点传感器。这样即使过程中丢了几步系统也能在每次循环回到原点时纠偏。对于机器人关节这种重复定位比较重要的场景这个功能强烈建议做进去。5. 调试与实测经验总结调试这套系统时我最推荐的顺序是先驱动后运动。先用一个可调直流电源给DRV8818供电用信号发生器输入固定的1kHz STEP脉冲确认电机转起来了再接入PIC18F46K20。信号发生器直接模拟脉冲的好处是把MCU从问题树里摘出去硬件驱动是否有问题一眼就能看出来。实际测过一组典型参数电机额定电压2.4V额定电流1.5A电感2.8mH保持力矩0.4N·m工作电压24VDRV8818限流1.6A左右。低速5rpm运行时电流几乎没有噪声表面温度稳定在70℃以下高速到120rpm时力矩有所下降但脉冲跟踪稳定没有出现明显的丢步。这说明系统还有充足的余量。关于PCB布局我想再强调一点DRV8818的GND和PIC18F46K20的GND在物理上要靠近但功率地与逻辑地在汇合点处要足够粗。我在最初一版PCB上偷懒把功率地走了一条细线结果电机一加速控制板上的ADC电压就跳动后来把所有GND引脚用大面积铺铜连起来故障就消失了。这类问题不实测根本发现不了。如果你打算在机器人或者桌面级设备上复用这套方案建议一上来就预留串口调试口。串口打印的速度表、目标位置、当前位置、错误标志能在现场快速定位是运动规划问题还是驱动问题。没有调试接口你只能靠示波器逐个信号猜效率天差地别。我在实际使用中最深的体会是步进电机控制这件事80%的麻烦在电流环和功率部分PIC18F46K20只需要把脉冲发整齐剩下的都交给DRV8818。而一旦选对了驱动器且把限流、衰减模式、散热这三个基础问题处理好系统的稳定性会大幅提升。这套方案的后续扩展方向也清晰加入绝对编码器闭环、增加网络接口远程控制、换用更高速的MCU进一步平滑速度曲线每一条路都走得通没有技术死角。
返回列表