尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

STM32F103驱动CoreXY步进电机:从PWM到运动控制实现

STM32F103驱动CoreXY步进电机:从PWM到运动控制实现 CoreXY 机构常用在绘图仪、激光雕刻机和小型 3D 打印机上它用两个固定电机配合皮带带动工具头在 X/Y 平面移动。基于 STM32F103 驱动步进电机做运动控制是这类项目最常见的单片机方案。Vibecode 项目的目标就是围绕这套机构完成从底层 PWM 脉冲、步进电机驱动、CoreXY 坐标换算到串口指令控制的一整套最小可运行系统。这篇文章按工程落地顺序来写先说明结构原理和硬件接线再给出脉冲生成和运动学代码最后提供验证方法和排查表。整个过程中会重点解释“为什么这样设计”而不只是堆命令和引脚。1. CoreXY 和步进电机先搞清控制对象和控制目标1.1 CoreXY 结构在解决什么问题常见 XY 平台有两种做法一种是 X 轴滑台叠在 Y 轴滑台上Y 轴电机要背着 X 轴整个移动运动组件重、惯量大另一种就是 CoreXY两个电机都固定在机架底部或侧面通过皮带和惰轮把动力传到工具头。工具头只负责作为皮带上的一个节点所以移动部分很轻在高速往返场景下更稳定。CoreXY 的代价是运动学不直观。单个电机转动工具头会沿斜线走而不是只沿 X 或 Y 走。要让工具头沿 X 轴直线移动两个电机必须按特定比例同时转动。这个比例关系就是下面要讲的运动学换算。控制程序里不能把电机 A 直接对应 X 轴、电机 B 直接对应 Y 轴否则画不出直线。1.2 两相 4 线混合式步进电机的驱动方式两相 4 线混合式步进电机是小型运动机构里最常用的一类内部有两组线圈引出 A、A-、B、B- 四根线。它通过线圈电流的交变来建立旋转磁场转子是永磁体所以断电后有定位力矩运行时比普通直流电机更容易做到开环位置控制。STM32F103 的 GPIO 不能直接驱动电机线圈正常做法是让单片机输出 STEP、DIR、EN 三路信号给步进电机驱动板由驱动板控制电机的相电流。驱动板内部根据 STEP 上的脉冲沿产生一拍一拍的换相DIR 决定旋转方向EN 控制输出级是否使能。常见的驱动板有 A4988、DRV8825、TMC2209它们的 STEP/DIR 接口逻辑基本一致但电流设置、细分设置和 EN 电平可能不同接线前要看具体说明书。1.3 STM32F103 在控制系统中的职责STM32F103 在这个系统里不是放大器也不是电机控制器它的职责是“产生正确的控制时序”。具体包括用定时器产生可调频率的脉冲决定电机转速用 GPIO 输出方向信号决定电机旋转方向用 GPIO 控制驱动板使能脚决定电机是否保持通电通过串口接收运动指令解析目标坐标读取限位开关完成回原点和边界保护。其中最关键也最容易出错的是脉冲生成。步进电机每收到一个脉冲走一步因此脉冲频率决定速度脉冲总数决定位移。要让 CoreXY 画出一条平滑直线两个电机的脉冲总数和脉冲频率必须在一个时间基准下协调。这也是为什么要用 STM32 定时器而不是用普通延时翻转 GPIO 的原因。2. 硬件方案与引脚分配先对最小系统和驱动接线2.1 STM32F103 最小系统时钟、电源、调试口最小系统至少要包含电源、复位电路、时钟、SWD 调试口和启动模式选择。开发阶段可以直接买市面上的最小系统板但自己画板时要注意以下几点。时钟建议优先使用 8MHz 外部晶振通过 PLL 倍频到 72MHz。外部晶振精度高于内部 HSIPWM 输出频率更准。项目标题里的热度词提到“stm32f103 在传统的库函数中如何让 stm32f103 工作在内部晶振模式下”这是为了省掉晶振和两个负载电容。内部 HSI 默认是 8MHz经过 PLL 可以倍频到 64MHz 或 72MHz但 HSI 精度通常只有 1% 左右而且随温度变化。如果只是跑呼吸灯或普通 GPIO 控制内部晶振完全够用如果用来输出步进电机脉冲尤其是长时间连续运动外部晶振会更可靠。上电顺序也要注意逻辑电源 3.3V 和电机电源 12V/24V 要分层设计。调试时先给单片机供电确认串口输出正常再给电机电源供电避免驱动板未配置好就上电导致电流失控。2.2 驱动板选型和 STEP/DIR/EN 接线驱动板选型主要看电机电流、驱动电压、细分能力和散热条件。驱动板典型电压最大电流细分方式适用场景A49888-35V约 2A全步到 1/16小型 CoreXY、学习项目DRV88258.2-45V约 2.5A全步到 1/32中等负载、需要更高细分TMC22094.75-29V约 2A最高 1/256静音模式对噪声敏感、需要静音运行驱动板上的 STEP 脚接单片机定时器 PWM 引脚DIR 脚接普通 GPIOEN 脚接普通 GPIO。A4988 的 EN 通常低电平有效也就是 EN 引脚拉低时使能输出。如果接反电机上电后不会锁定或者一直被锁定不能自由转动。驱动板下侧的电位器用来设置电流上限。初学者容易忽略这一步结果电机电流过小不转或者电流过大烫手。设置电流时要拿万用表测参考电压或按驱动板说明书的公式计算不要凭感觉。2.3 推荐引脚分配与 PWM/DMA 使用位置CoreXY 需要两个电机独立调速因此两个 STEP 信号最好来自两个不同的定时器。下面是一个推荐引脚分配功能引脚外设说明电机 A STEPPA0TIM2_CH1脉冲输出电机 A DIRPB0GPIO 输出方向控制电机 B STEPPA6TIM3_CH1两个电机使用不同定时器频率可独立变化电机 B DIRPB1GPIO 输出方向控制两路 EN 合并控制PC2GPIO 输出同时使能或释放两个电机串口 TX / RXPA9 / PA10USART1接收上位机指令X/Y 限位PC0 / PC1GPIO 输入回原点和边界保护这里要解释一个常见误区PA1 和 PA3 都能输出定时器 PWM它们来自 TIM2 的 CH2 和 CH4。如果只是测试 PWM 波形用 PA1/PA3 很方便但同一个定时器的不同通道只能共用一组预分频和计数周期ARR 一改所有通道频率都变不能用来分别控制两个电机的速度。所以实际运动控制要选两个独立定时器。DMA 的位置要看具体外设映射。例如 TIM2 的更新事件可以触发 DMA 请求定时器的 ARR 或 CCR 寄存器可以通过 DMA 持续更新。不同型号的 DMA 通道映射不同落地前一定要查 STM32F103 参考手册的 DMA 请求映射表不要照抄网上的通道号。2.4 电源地与电流估算驱动板的地和单片机的地必须共地否则 STEP 脉冲没有参考电平驱动板可能不触发。电机电源和逻辑电源可以分别供电但二者要共地。不要把电机电源直接接到单片机 3.3V 上也不能把 12V 接到驱动板逻辑侧。电流估算可以按步进电机参数近似计算。常见 42 步进电机额定电流约 1.5A 到 2A两相同时导通电源侧平均电流会低于电机相电流但峰值和启动瞬间会更高。用 A4988 时 12V 供电通常够用用 DRV8825 且电机电流超过 2A 时电源余量建议留到 50% 以上。3. 底层脉冲生成定时器 PWM 和 DMA 配合3.1 速度本质单位时间内的脉冲数步进电机驱动板收到一个上升沿或下降沿电机就走一个微步。脉冲频率越高速度越快。例如电机是 200 步/转也就是每转需要 200 个整步步进如果驱动板设置 1/10 细分那么每转需要 2000 个脉冲。假设带轮每转带动皮带 40mm那么每毫米脉冲数是2000 / 40 50 脉冲/mm如果输出 10kHz 脉冲工具头理论速度就是10000 / 50 200 mm/s这个换算关系是所有运动控制的基础。速度控制本质上是脉冲频率控制位置控制本质上是脉冲计数控制。3.2 用定时器 PWM 输出固定频率脉冲STM32F103 的通用定时器可以工作在 PWM 模式由 ARR 决定周期由 CCR 决定高电平时间。系统时钟 72MHz 时PWM 频率公式为F 72MHz / PSC 1 × ARR 1下面这段标准外设库代码把 TIM2_CH1 配置成初始 1kHz、50% 占空比的 PWM 输出void PWM_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_0; // TIM2_CH1 GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Prescaler 72 - 1; // 72MHz / 72 1MHz TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period 1000 - 1; // 初始 1kHz TIM_TimeBaseStructure.TIM_ClockDivision 0; TIM_TimeBaseInit(TIM2, TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse 500 - 1; // 50% 占空比 TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_High; TIM_OC1Init(TIM2, TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM2, ENABLE); TIM_Cmd(TIM2, ENABLE); }这段代码把定时器计数频率固定为 1MHz初始 ARR 为 999所以 PWM 频率是 1MHz / 1000 1kHz。修改 ARR 可以改变频率比如 ARR 99 时频率是 10kHz。占空比通过 CCR 控制对步进电机来说 50% 是比较稳妥的选择能保证高电平宽度足够被驱动板识别。3.3 用 DMA 批量发送脉冲串避免 CPU 频繁改频率固定频率 PWM 只能让电机匀速转。实际运动控制中电机启动瞬间如果直接给目标频率可能超出电机的自启动频率范围出现丢步。因此需要从低频慢慢加速到高频再慢慢降频停下来。如果每一步都靠中断修改 ARRCPU 会被频繁打断而且中断延迟会导致脉冲间隔不均匀。更合适的方法是使用“定时器更新事件 DMA”的方式。具体思路是把减速表展开成一段时间序列每个时间点对应一个 ARR 值定时器每产生一次更新事件DMA 就自动把下一个 ARR 值写入定时器。这样 CPU 只需要启动一次 DMA 传输后续频率变化由硬件完成。下面是一个简化的伪代码流程1. 生成速度表 speed_table[]每个元素对应一个 ARR 值 2. 配置定时器更新事件触发 DMA 3. DMA 从内存中的 speed_table 搬运数据到定时器 ARR 寄存器 4. 启动定时器和 DMA 5. DMA 传输完成中断里关闭输出。要注意几点速度表放在内存数组里数据宽度要和 ARR 寄存器一致DMA 工作模式要看是单次传输还是循环传输加减速过程中如果收到停止命令要能主动关闭 DMA 和定时器而不是等自然传输完成。实际进入生产环境前建议用逻辑分析仪抓取 STEP 引脚的波形确认脉冲间隔没有明显突变。3.4 方向与使能的控制顺序STEP、DIR、EN 三路信号之间有时序要求。驱动板通常只在 STEP 上升沿采样 DIR 电平如果在脉冲正在输出的同时切换 DIR驱动板可能采样到不稳定的方向导致最后一步方向错误。建议切换方向时先改 DIR再延时几微秒最后输出脉冲。void Motor_SetDirection(uint8_t direction) { GPIO_WriteBit(GPIOB, GPIO_Pin_0, direction ? Bit_SET : Bit_RESET); delay_us(5); }EN 脚用来控制驱动板输出级。A4988 的 EN 低电平有效所以释放电机时要拉高 EN。运动结束后不要继续让驱动板大电流锁住电机时间久了电机和驱动板都会发热。空闲超过设定时间后可以关掉使能让电机进入自由状态。3.5 常见坑PWM 通道、频率范围和脉冲宽度问题现象常见原因检查方式处理建议两个电机速度互相影响两路 PWM 放在同一个定时器看引脚是否属于同一个 TIM改到不同定时器低频运动时电机一顿一顿ARR 溢出或分频设置不当计算 1MHz 计数下最大周期按频率范围切换 PSC电机不转但 PWM 有输出占空比太小或脉宽不足示波器看高电平时间使用 50% 占空比方向切换时丢步DIR 和 STEP 同时跳变逻辑分析仪看三路信号时序先改 DIR延时后输出脉冲注意PWM 输出频率不等于最终工具头速度。一定要先算清“电机转一圈需要多少脉冲”和“每毫米对应多少脉冲”再设置 ARR。4. CoreXY 运动学换算从目标坐标到两个电机步数4.1 运动学映射关系以常见 1:1 带轮配置为例两个电机运动量分别记作 A 和 B工具头的 X/Y 坐标可以近似表示为X (A B) / 2 Y (A - B) / 2这里的 A、B 代表电机带动的位移单位是 mm。反解得到A X Y B X - Y如果把目标位移记作 dx、dy那么两个电机需要移动的位移分别是dA dx dy dB dx - dy再乘以每毫米脉冲数 K才能得到两个电机的脉冲数stepsA (dx dy) * K stepsB (dx - dy) * K这个公式是理想模型。实际皮带绕法、电机安装方向不同可能会出现 X 正向移动时 stepsA 符号反了、Y 正向移动时 stepsB 符号反了之类的情况。所以控制代码里要预留方向补偿参数在点动测试阶段修正。4.2 步进当量计算细分数、带轮周长、减速比每毫米脉冲数 K 的计算公式为K 电机每转脉冲数 / 带轮每转移动距离电机每转脉冲数由步距角和细分数决定电机每转脉冲数 200 × 细分数带轮每转移动距离由带轮周长决定。2GT 同步带齿距是 2mm20 齿带轮周长约 40mm30 齿带轮约 60mm。如果使用减速机构还要再除以减速比。细分数电机每转脉冲数20 齿带轮 K 值12005 脉冲/mm8160040 脉冲/mm16320080 脉冲/mm326400160 脉冲/mm细分主要影响振动和精度上限但不改变电机物理步距角。细分数提高后每个微步的定位更平滑但微步位置精度受驱动板电流控制能力限制并不是细分越高精度就一定越高。4.3 C 语言实现坐标到步数的换算下面用两个函数分别计算 CoreXY 两个电机的脉冲数。入参是工具头的位移量单位是毫米返回值是脉冲数正数代表一个方向负数代表另一个方向。typedef struct { int32_t x; int32_t y; uint16_t stepsPerMM; } CoreXYState; int32_t CoreXY_StepsA(int32_t dx, int32_t dy, uint16_t stepsPerMM) { return ((dx dy) * (int32_t)stepsPerMM) / 2; } int32_t CoreXY_StepsB(int32_t dx, int32_t dy, uint16_t stepsPerMM) { return ((dx - dy) * (int32_t)stepsPerMM) / 2; }注意这里和前面的反解公式看起来不完全一致。实际上如果 4.1 节的公式已经带上了 /2 系数反解结果就是 dxdy如果直接按 dA dx dy那么就不需要再除 2。更稳妥的做法是先用机械量推导再在样机上用直尺或画线实测根据实际运动方向修正系数和符号。拿到 stepsA、stepsB 后正负号决定 DIR绝对值决定脉冲总数。发送脉冲时会用到下面的运动逻辑void CoreXY_MoveTo(CoreXYState *state, int32_t targetX, int32_t targetY) { int32_t dx targetX - state-x; int32_t dy targetY - state-y; int32_t stepsA CoreXY_StepsA(dx, dy, state-stepsPerMM); int32_t stepsB CoreXY_StepsB(dx, dy, state-stepsPerMM); SetDirection(A_MOTOR, stepsA 0); SetDirection(B_MOTOR, stepsB 0); uint32_t absA stepsA 0 ? stepsA : -stepsA; uint32_t absB stepsB 0 ? stepsB : -stepsB; Motor_StartRamp(absA, absB); state-x targetX; state-y targetY; }这里把启动加减速封装成 Motor_StartRamp它根据两个轴的总脉冲数和目标速度决定每个时刻的脉冲频率。简单实现可以先跑“先 A 后 B”的贪心跳线但会形成折线CoreXY 要做到直线插补需要把速度按比例分配给两个电机。4.4 匀速与梯形加减速的简单实现如果只测试 CoreXY 机构是否能动可以先让两个电机以相同频率匀速转完各自的脉冲数。但这样会造成先完成的电机提前停下来工具头轨迹不是直线。更合理的简单插补思路是以相对较慢的轴为基准按比例分配较快轴的频率。例如 stepsA 是 1000stepsB 是 500A 轴速度是 B 轴的两倍。两个电机同时启动、同时停止工具头就能走出目标直线。加加速和减速后整体轨迹会更平滑。梯形加减速的伪代码如下输入总脉冲数 totalSteps启动频率 fStart最大频率 fMax加速步数 accelSteps 运行过程 1. 当前脉冲数 0 2. 如果当前脉冲数 accelSteps频率 fStart (fMax - fStart) * 当前脉冲数 / accelSteps 3. 如果当前脉冲数 totalSteps - accelSteps频率 fMax - (fMax - fStart) * (totalSteps - 当前脉冲数) / accelSteps 4. 否则频率 fMax 5. 每输出一个脉冲更新当前脉冲数启动频率不能超过电机的自启动频率否则电机会发出尖锐的嗡嗡声并原地抖动根本不会转。一般取 200Hz 到 500Hz 比较安全最大频率根据实际负载和驱动电压调整。5. 控制命令与状态管理从手动点到自动跑平面5.1 自定义串口命令协议CoreXY 控制器需要接收外部指令。最简单的方式是使用文本命令每行以\r\n结尾。比如G0 X10 Y5 F600\r\n G28\r\n M18\r\n其中 G0 表示快速移动到一个坐标点后面的 X、Y 是目标坐标F 是最大进给速度G28 是回原点M18 是释放电机。指令解析可以用 sscanfchar line[64]; if (sscanf(line, G0 X%ld Y%ld F%ld, x, y, f) 3) { SetTargetVelocity(f); CoreXY_MoveTo(state, x, y); } else if (strncmp(line, G28, 3) 0) { HomeAndSetZero(state); } else if (strncmp(line, M18, 3) 0) { Motor_Disable(); }使用 G 代码子集的好处是以后可以接上位机软件、绘图指令或现有的切片软件。串口波特率一般用 115200如果指令长度较长可以在接收中断里用环形缓冲区避免丢字节。5.2 状态机设计运动控制不能每个命令都直接改电机。比如当前正在移动时收到第二个 G0应该排队、覆盖还是拒绝必须明确。推荐设计一个简单的状态机状态进入条件主要动作退出条件IDLE上电复位或运动完成等待指令可关闭电机使能收到 G0/G28RUNNING收到 G0运动开始输出脉冲执行加减速脉冲发送完成HOMING收到 G28低速向限位方向移动到达限位并确认回零ALARM限位被异常触发或命令错误停止脉冲关闭电机收到复位指令代码如下typedef enum { STATE_IDLE, STATE_RUNNING, STATE_HOMING, STATE_ALARM } MotionState; MotionState state STATE_IDLE; void Motion_Task(void) { switch (state) { case STATE_IDLE: if (cmdQueue.Count 0) { StartNextCommand(cmdQueue); } break; case STATE_RUNNING: if (Motion_IsFinished()) { state STATE_IDLE; Motor_Disable(); } break; case STATE_HOMING: if (Limit_IsTriggered()) { Motor_Stop(); state STATE_IDLE; } break; case STATE_ALARM: // 只响应复位命令 break; } }状态机让代码更容易排查。出了问题看状态值就能知道控制器处于什么阶段而不是靠猜测。5.3 限位开关与回原点回原点时有三个要点速度要低、方向要明确、碰到限位后要脱离。如果机构撞到机械限位后电机还继续用力会丢步甚至损坏皮带。建议回零时先低速向负方向移动遇到限位立即停止然后反向移动一小段距离脱离限位把这个位置记录为软件零点。限位开关接成常开还是常闭要根据硬件决定软件里要加滤波避免开关抖动导致误触发。5.4 空闲处理停机模式、低功耗与 FreeRTOS 任务划分如果设备由电池供电或者需要长时间待机空闲时不建议让单片机一直满频运行。STM32F103 支持 Stop 模式进入后大部分外设时钟停止可以用外部中断或 RTC 唤醒。进入 Stop 模式前要先把 PWM 输出关闭、电机使能关掉避免唤醒后产生意外运动。如果系统功能增加比如同时要处理串口、限位、温度监控和运动控制可以使用 FreeRTOS。任务可以这样划分任务优先级职责交互方式运动控制任务高执行脉冲发送、加减速接收坐标队列串口解析任务中接收指令、写入命令队列队列发送给运动任务监控任务低检测温度、限位、心跳状态变量或事件FreeRTOS 只负责任务调度真正的脉冲发送还是应该交给定时器和 DMA否则任务切换抖动会让电机声音发毛、定位精度下降。6. 运行验证与排查按最小链路逐步确认6.1 第一轮验证只输出脉冲不接电机接电机前先用逻辑分析仪或示波器看 STEP 引脚的波形。检查三个方面PWM 频率是否和设置值一致高电平宽度是否足够DIR 信号切换瞬间是否在脉冲间隔内。如果示波器显示频率正确再接驱动板和电机。不要跳过这一步否则 PWM 配置错误被直接当成电机故障排查成本高。6.2 第二轮验证单个电机点动先不写 CoreXY 运动学只发一个固定脉冲数让单个电机低速点动。验证目标电机是否转动方向是否和 DIR 信号一致转一圈所需脉冲数和理论值是否接近电机是否发热、丢步。如果电机只是响和抖动不转优先怀疑电流设置太小或启动频率太高。如果电机反转交换电机相线或调整 DIR 逻辑都能解决但要明确系统里采用哪种方式不要两边同时改。6.3 第三轮验证CoreXY 平面运动在工具头上装一支记号笔让控制器执行 G0 X10 Y0 和 G0 X0 Y10 这类单轴移动。如果 CoreXY 运动学正确X 单轴移动时两个电机都会转但工具头只沿 X 方向走。画完单轴再执行 G0 X10 Y10这支线段应该与 X 轴成 45 度左右。如果实际线条偏斜检查 stepsPerMM 是否一致检查 dx、dy 的符号是否需要在坐标换算里取反。6.4 常见问题排查表问题现象可能原因检查方式处理建议电机完全不动驱动板无供电、EN 未使能、STEP 引脚错万用表量电压示波器看 STEP按“电源 - EN - STEP - DIR”顺序查电机抖动不转电流太小、启动频率太高、掉相量电流设置降低速度重新设置电流改用低启动频率电机发热严重电流设置过大、长时间锁住摸驱动板和电机温度调低电流空闲时关闭使能工具头移动方向偏运动学符号或 stepsPerMM 不对执行单轴运动观察逐个轴标定方向再测每毫米距离直线运动变成折线两个轴不同步看两个 STEP 波形时间差检查插补逻辑确保同时启停串口指令不稳定波特率不一致、未做环形缓冲回显调试使用固定波特率接收后加校验注意不要只验证程序能启动还要验证输入、输出、异常分支和日志是否符合预期。运动控制项目尤其要把“异常停止”作为一种正常功能来测试。7. 工程化建议与最佳实践7.1 固件分层与可维护性Vibecode 这一类项目从 Demo 走向产品固件结构要分层。推荐按驱动层、运动层、应用层三层拆分驱动层封装定时器 PWM、GPIO、串口、DMA 初始化对外提供 Motor_SetFrequency、Motor_SetDirection 这样的函数运动层负责 CoreXY 坐标换算、加减速规划、限位处理应用层负责串口命令解析、状态机切换、用户逻辑。不建议在主循环里直接操作寄存器。把硬件细节隔离后换驱动板型号或改引脚时只需要修改驱动层运动学代码不用动。7.2 运动安全限位、急停、回滚生产环境至少要有三类保护硬件限位防止工具头撞到机架软件限位在代码里维护 X/Y 最大和最小坐标超出范围拒绝执行急停保留一个外部按钮或紧急停止协议触发后立即关闭电机使能和 PWM。停止方式也要区分。正常停止应该走完减速过程避免急停导致丢步紧急停止则要立即封锁脉冲并关闭使能。这两种停止在状态机里应该对应不同处理路径。7.3 电源、散热和抗干扰电机驱动属于强干扰源尤其是斩波电流和启停瞬间。建议将电机电源线、信号线分开走STEP/DIR 信号线使用双绞线不要和电机线扎在一起。驱动板加散热片机箱内部保证空气流动。逻辑地和电机地要共地但布局上要单点连接避免大电流在地线上形成压差干扰单片机的复位和串口通信。如果出现随机丢步、电机跑飞、串口乱码先检查干扰而不是反复改代码。7.4 可复用开发清单开发一个 CoreXY 步进电机控制项目可以按下面的清单推进。环境检查单片机最小系统供电正常晶振起振SWD 可连接定时器 PWM 引脚确认是正确复用功能驱动板电流设置和细分设置完成电机电源电压在驱动板允许范围内。接线检查STEP、DIR、EN 与 GPIO 一一对应驱动板 EN 逻辑确认过高/低有效所有地线共地电机电源正负极无短路限位开关接线和 GPIO 上拉/下拉匹配。软件验证清单示波器观察 PWM 频率和占空比单电机点动方向和速度正确计算并验证每毫米脉冲数CoreXY 单轴运动方向正确斜线运动轨迹为直线限位回零可重复停止命令能在任意时刻中断运动。发布前检查加减速平滑无丢步长时间运行温度和噪声可接受急停功能有效看
返回列表