ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

STM32电机控制实战指南:从硬件配置到PID闭环全链路解析

STM32电机控制实战指南:从硬件配置到PID闭环全链路解析

简介:本资源是野火电子2021年5月发布的《电机应用开发实战指南—基于STM32》完整PDF教程,面向嵌入式初学者、自动化工程师及高校机电/电控方向实践者,系统解决电机控制原理理解难、STM32驱动实现无从下手、多类电机(直流/步进/伺服)开发缺乏统一方法论等核心问题。全书共1个PDF文件,大小35.84MB,内容覆盖电机分类详解(含舵机)、四大驱动器选型与接口设计、STM32定时器在PWM调速与脉冲定位中的关键应用,并配套野火全系列开发板实操指引。目录结构清晰,从电机基础、学习路径、硬件准备到驱动器分类层层递进,第6章深入剖析TIM定时器与电机控制的强耦合关系,提供可直接复用的底层驱动逻辑框架。目前已有863人学习下载,适合希望打通“理论—芯片—驱动—电机”全链路能力的工程实践者快速上手并开展创新开发。

1. 为什么这份《电机应用开发实战指南》能让你少走半年弯路?——从“调不动电机”到“闭环稳如磐石”的完整交付链

你是不是也经历过:STM32代码烧进去了,PWM波形用示波器一测——有;驱动板上电,MOS管微热——正常;可电机就是不转,或者一转就抖、一加速就停、一加负载就失步?查手册、翻论坛、问群友,最后发现是定时器通道配置错了一位、编码器滤波时间设得太短、PID的采样周期和控制周期没对齐……这些不是玄学,是电机控制项目里最真实、最高频、最致命的“断点”。

这份由野火电子在2021年5月发布的《电机应用开发实战指南—基于STM32》,不是一本讲完霍尔效应就收尾的理论书,而是一套从硬件选型、驱动电路分析、外设配置、保护逻辑实现,到闭环算法落地、上位机联调、参数整定验证的全链路交付方案。它覆盖直流有刷、舵机、步进、无刷四大类电机,每类都配真实硬件平台(野火STM32全系列开发板)、可编译工程、可复现现象、可测量波形、可验证保护动作——换句话说,它把“电机控制”这件事,拆成了你能一步步焊、一步步测、一步步调、一步步验收的工程模块。

适合谁?正在做毕业设计/课程设计、需要交一份有硬件连接图、有代码片段、有波形截图、有保护触发记录、有PID整定过程的完整方案的学生;刚接手电机类嵌入式项目的工程师,手头只有原理图和芯片手册,却不知道该先测哪一路信号、该在哪加滤波、该用哪个定时器模式、该把PID放在哪个中断里跑;还有那些被“电机失控”问题卡住两周、靠运气调通却不敢改参数的开发者。这不是速成课,而是帮你把电机控制从“能动”推进到“可控、可测、可保、可调、可验”的实操手册。


2. 总体架构设计:四层结构与五大核心模块的职责划分

电机控制系统的复杂性,往往不在算法本身,而在各模块间的耦合与时序依赖。野火这套方案没有堆砌高大上的分层模型,而是用一套经实践反复验证的四层物理-逻辑架构,把STM32资源、驱动硬件、电机本体、用户需求清晰切分:

  • 物理层:电机本体(直流/步进/无刷/舵机)+ 驱动板(H桥/MOS驱动/细分器/FOC模块)+ 传感器(电流采样电阻、NTC热敏电阻、ADC分压网络、编码器A/B/Z相)
  • 驱动层:STM32外设驱动(TIM高级定时器PWM互补输出、TIM编码器接口、ADC多通道同步采样、GPIO方向控制、UART协议栈)
  • 控制层:速度环/位置环PID控制器、限流/过压/欠压/过温保护状态机、步进脉冲生成器、无刷换相逻辑(六步法基础版)
  • 应用层:用户交互(按键/串口指令)、数据上报(实时电流/电压/温度/转速)、上位机通信协议解析与响应

这四层不是教科书里的抽象概念,而是每一章都在落实的具体分工。比如第7章直流有刷电机,硬件设计落在物理层(L298N或TB6612驱动电路),软件设计落在驱动层(TIM3_CH2 PWM配置)和控制层(开环占空比调节+闭环PID速度控制),而第16章PID整定,则直接打通应用层(上位机发Kp/Ki/Kd指令)→控制层(下位机更新参数)→驱动层(TIM重载值刷新)→物理层(电机响应变化)的完整回路。

2.1 定时器资源规划:为什么必须用TIM1/TIM8做电机主控?

在STM32F1/F4系列中,定时器并非等价可用。野火方案明确要求:所有电机PWM输出、编码器计数、捕获输入,必须绑定到高级定时器(TIM1/TIM8),而非通用定时器(TIM2-TIM5)。这不是为了炫技,而是由三个硬性约束决定的:

  1. 死区插入(Dead-time Insertion):H桥驱动必须避免上下桥臂直通。TIM1/TIM8支持硬件死区生成(BDTR寄存器),可在互补PWM通道间自动插入纳秒级延时。若用TIM2输出互补波,需软件模拟死区,极易因中断延迟导致直通炸管。
  2. 刹车功能(Break Function):紧急停机时需强制关断所有输出。TIM1/TIM8提供BKIN引脚硬件刹车,响应时间<1μs;通用定时器无此能力,只能靠软件置零,存在窗口风险。
  3. 编码器接口专用性:TIM2/TIM5虽支持编码器模式,但仅支持1x或2x计数;TIM1/TIM8支持4x正交解码(AB相双边沿计数),分辨率提升4倍——这对步进微步控制、无刷换相角度精度至关重要。

提示:野火开发板原理图中,TIM1_CH1/CH1N接L298N的IN1/IN2,TIM1_CH2/CH2N接IN3/IN4,正是为利用其互补输出+死区能力。若你用的是非野火板,请务必核对MCU型号是否含TIM1/TIM8,否则后续所有电机实验将无法复现。

2.2 ADC采样策略:多通道同步+硬件过采样降噪

电机控制中的电流、电压、温度采样,不是“读个ADC值”那么简单。野火方案在第8章(直流有刷)和第12章(无刷)中,统一采用三通道同步采样 + 硬件过采样(Oversampling)+ 数字滤波组合策略:

  • 同步采样:使用TIM1 TRGO事件触发ADC1/ADC2同步转换,确保电流(I_SENSE)、母线电压(V_BUS)、驱动温度(T_DRV)在同一时刻被捕获,消除相位差导致的功率计算误差。
  • 硬件过采样:ADC_CR2寄存器配置OVSR=3(16次过采样)、OVSS=2(移位2位),使12位ADC有效分辨率提升至14位,信噪比提高约12dB。
  • 数字滤波:在DMA传输完成后,对连续16次采样值做中值滤波+滑动平均,剔除MOS开关噪声尖峰。
// 野火例程中ADC初始化关键配置(以F103为例) ADC_DeInit(ADC1); ADC_StructInit(&ADC_InitStructure); ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 扫描模式 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 单次转换(由TIM触发) ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; // TIM1_CC1触发 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 3; // 3通道:CH0(I), CH1(V), CH2(T) ADC_Init(ADC1, &ADC_InitStructure); // 启用过采样 ADC_OverSamplingCmd(ADC1, ENABLE); ADC_OverSamplingRatioConfig(ADC1, ADC_OverSampling_Ratio_16); // 16x ADC_OverSamplingShiftConfig(ADC1, ADC_OverSampling_Shift_2); // 右移2位

这段配置背后是血泪经验:曾有学生用软件延时依次读取三路ADC,结果电流峰值出现在电压谷底,算出的瞬时功率为负值,保护逻辑误判为能量回馈而锁死输出。同步采样不是“更准”,而是“保证物理关系不失真”。

2.3 保护逻辑分层:从硬件熔断到软件状态机的四级防线

电机失控的后果轻则烧MOS,重则飞车伤人。野火方案将保护设计为四级递进式防线,每级响应时间与作用域严格区分:

防线层级实现方式响应时间作用范围野火对应章节
L1硬件熔断驱动芯片自保护(如L298N过热关断)<100ns单颗芯片第5章驱动器介绍
L2硬件比较外置比较器(LM339)+ 硬件关断信号<1μs整个驱动板第8章电流采样电路图
L3固件中断ADC溢出中断(EOC+AWD)+ TIM刹车<10μsSTM32外设+驱动板第8.5节限流保护
L4应用层状态机主循环检测+PID输出钳位+故障上报~1ms全系统+人机交互第16章上位机协议

这种分层不是炫技,而是工程必需。例如第8.5节“限电流-过压-欠压保护”,其软件设计核心不是“if (current > 5.0) stop_motor()”,而是:

  • 在ADC转换完成中断中,仅做原始值采集与缓存(快);
  • 在1ms SysTick中断中,执行中值滤波+标定换算+阈值比较(准);
  • 在主循环中,根据比较结果更新保护状态机(NORMAL/ALERT/LOCKED)并触发相应动作(稳)。

这样既保证了快速响应(L3中断),又避免了毛刺误触发(L4状态机防抖),还留出了故障日志记录空间(UART上报当前电流/电压/时间戳)。


3. 关键模块实现:从PWM生成到PID闭环的代码级落地方案

电机控制的“灵魂”不在原理图,而在那一段段跑在裸机或RTOS上的C代码。野火方案的可贵之处,在于它把每个关键函数都拆解到寄存器级,并给出可验证的行为描述。下面以直流有刷电机速度闭环控制为例,展示从定时器配置、ADC采样、PID计算到PWM更新的完整链条。

3.1 高级定时器PWM互补输出:TIM1的寄存器级配置

第6.3.4节“PWM互补输出实验”给出了TIM1_CH1/CH1N驱动H桥的经典配置。其核心在于三个寄存器的协同:

  • TIM1_CCMR1:设置CH1为PWM模式1(OC1M=110),使能预装载(OC1PE=1)
  • TIM1_CCER:使能CH1输出(CC1E=1)、使能互补输出(CC1NE=1)、设置极性(CC1P=0, CC1NP=1)
  • TIM1_BDTR:开启死区(MOE=1, AOE=1),设置死区时间(DTG=0x7F → 约1.2μs)
// 野火例程TIM1初始化片段(精简) TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_BDTRInitTypeDef TIM_BDTRInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); TIM_TimeBaseStructure.TIM_Period = 999; // 自动重装载值ARR=1000 TIM_TimeBaseStructure.TIM_Prescaler = 71; // PSC=72 → 72MHz/72=1MHz计数频率 TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM模式1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // 互补使能 TIM_OCInitStructure.TIM_Pulse = 500; // 初始占空比50% TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Set; TIM_OC1Init(TIM1, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); // 死区配置:DTG[7:0] = 0x7F → 死区时间 = (64+127)*Tck = 191*Tck ≈ 191ns (72MHz) TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; TIM_BDTRInitStructure.TIM_DeadTime = 0x7F; // 关键!死区时间 TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable; TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High; TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure); TIM_Cmd(TIM1, ENABLE); TIM_CtrlPWMOutputs(TIM1, ENABLE); // 必须显式使能主输出

这段代码后必须跟一句说明:TIM_CtrlPWMOutputs(TIM1, ENABLE)是常被忽略的“后悔药”。若忘记此句,TIM1所有通道输出将保持高阻态,示波器测不到任何波形,且无任何错误标志——这是野火论坛高频提问“为什么没PWM?”的头号原因。

3.2 编码器测速:TIM2的4x正交解码与速度计算

第13章和第17章详细讲解了增量式编码器接口。野火方案采用TIM2编码器模式 + DMA搬运 + 定时器捕获中断组合,实现高精度测速:

  • TIM2_EncoderInterfaceConfig()设置TI1/TI2为编码器模式,自动处理A/B相边沿计数;
  • TIM2_TimeBaseInit()的TIM_Period设为0xFFFF,避免溢出;
  • 每10ms进入一次SysTick中断,读取TIM2->CNT值,清零计数器,计算ΔCNT;
  • 速度 = (ΔCNT × 4 × 60) / (编码器线数 × 采样周期_ms) 单位:RPM。
// 编码器初始化(TIM2) void Encoder_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 编码器模式:TI1和TI2都用于计数 TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); // 计数器自动重装载值设为最大,避免溢出 TIM_TimeBaseStructure.TIM_Period = 0xFFFF; TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_Cmd(TIM2, ENABLE); } // 10ms定时器中断中读取速度 uint16_t Read_Speed(void) { static uint16_t last_count = 0; uint16_t current_count = TIM2->CNT; int16_t delta = current_count - last_count; last_count = current_count; // 4x解码,所以实际脉冲数 = delta * 4 // 假设编码器1000线,则一圈4000脉冲 // 速度(RPM) = (delta * 4 * 1000) / (1000 * 10) * 60 = delta * 24 return (uint16_t)(abs(delta) * 24); // 简化公式,实际需按编码器参数调整 }

注意:Read_Speed()中abs(delta)是关键。编码器计数器是双向的,正转时delta>0,反转时delta<0。若不做绝对值,速度值会随转向跳变,PID控制器将无法稳定。

3.3 PID控制器:位置式与增量式的选型依据与C语言实现

第15章给出了两种PID的C语言实现。野火方案明确指出:位置式PID适用于低速、高精度定位(如舵机、步进);增量式PID适用于高速、大惯量调速(如直流有刷、无刷)。原因在于:

  • 位置式输出是绝对控制量(如PWM占空比0~100%),易受积分饱和影响,需手动限幅;
  • 增量式输出是本次与上次的差值(ΔPWM),天然抗积分饱和,且便于实现“软启动”、“平滑切换”。

野火提供的增量式PID代码,其精髓在三点:

  1. 误差限幅:error = constrain(error, -MAX_ERROR, MAX_ERROR)防止初始大偏差导致输出突变;
  2. 输出限幅:output = constrain(output, MIN_OUTPUT, MAX_OUTPUT)保护驱动器;
  3. 微分先行:derivative = Kd * (setpoint - actual)而非Kd * (actual - last_actual),抑制测量噪声对微分项的放大。
// 增量式PID结构体(野火标准定义) typedef struct { float Kp; float Ki; float Kd; float setpoint; float actual; float error; float last_error; float last_actual; float integral; float output; float last_output; } PID_TypeDef; // 增量式PID计算函数 float PID_Incremental(PID_TypeDef* pid) { float error = pid->setpoint - pid->actual; // 误差限幅(防突变) if(error > MAX_ERROR) error = MAX_ERROR; else if(error < -MAX_ERROR) error = -MAX_ERROR; // 积分项:离散积分,带限幅 pid->integral += error * pid->Ki; if(pid->integral > MAX_INTEGRAL) pid->integral = MAX_INTEGRAL; else if(pid->integral < -MAX_INTEGRAL) pid->integral = -MAX_INTEGRAL; // 微分项:微分先行,抑制噪声 float derivative = pid->Kd * (pid->setpoint - pid->actual); // 增量计算 float delta_output = pid->Kp * error + pid->integral + derivative; // 输出限幅 pid->output = pid->last_output + delta_output; if(pid->output > MAX_OUTPUT) pid->output = MAX_OUTPUT; else if(pid->output < MIN_OUTPUT) pid->output = MIN_OUTPUT; pid->last_output = pid->output; pid->last_error = error; pid->last_actual = pid->actual; return pid->output; }

这段代码中MAX_INTEGRAL的设定值(通常为MAX_OUTPUT * 0.5)是野火工程师踩坑后总结的黄金比例:积分项过大会导致超调振荡,过小则消除静差慢。这个值不是理论推导,而是用示波器观察阶跃响应后反复调整出来的。


4. 常见问题排查:电机控制项目中最容易翻车的5个致命点

电机控制项目里,80%的问题不是出在算法,而是出在“以为没问题”的细节上。以下是野火方案实践中高频出现、且极易被忽略的5个翻车点,按“现象→原因→解决”结构列出,每一条都来自真实调试现场。

4.1 现象:电机空载能转,一加负载就停,示波器看PWM波形正常

原因:电流采样电路未做RC低通滤波,MOS开关噪声被ADC误采为过流,触发L3保护锁死输出。
解决:在电流采样电阻两端并联100nF陶瓷电容+10Ω电阻构成RC滤波(截止频率≈160kHz),并在ADC软件中增加2次中值滤波。野火第8.1节电路图已包含此设计,若自行搭建驱动板请务必复现。

4.2 现象:编码器计数跳变,正转时偶尔出现负值,速度计算忽高忽低

原因:编码器A/B相布线过长且未双绞,受电机驱动噪声干扰,导致TIM2误判边沿。
解决:重新布线,A/B相必须双绞并远离功率线;在编码器供电端加100μF电解电容+0.1μF陶瓷电容;TIM2的TIM_ICFilter寄存器设为0x0F(8个采样时钟滤波)。野火开发板PCB已做此优化,若用杜邦线飞线必翻车。

4.3 现象:PID调参时,增大Kp后电机振荡加剧,减小Kp又响应太慢,始终找不到平衡点

原因:采样周期(Ts)与控制周期不匹配。野火方案要求PID必须在SysTick中断中执行,且Ts必须严格等于1ms(F103默认配置)。若误将PID放在主循环中,实际Ts随任务负载波动(2~20ms),Kp物理意义失效。
解决:确认SysTick_Config(SystemCoreClock / 1000)已正确调用;在PID函数入口加if (tick_flag) { tick_flag = 0; ... },确保严格1ms执行;用示波器测GPIO翻转验证周期。

4.4 现象:无刷电机换相混乱,转子抖动严重,霍尔信号波形正常但TIM1捕获中断不触发

原因:霍尔传感器输出为开漏(OD)结构,未接上拉电阻。野火开发板原理图中,霍尔VCC经10kΩ电阻上拉至5V,若自行焊接遗漏,霍尔信号在MCU引脚上呈现高阻态,无法被识别。
解决:用万用表测霍尔输出引脚对地电压,空载应为5V(上拉有效),按下霍尔应变为0V。若始终为0V或浮空,检查上拉电阻焊接与阻值。

4.5 现象:上位机发送PID参数后,电机无响应,串口调试助手中看到参数已接收,但pid->Kp值未更新

原因:野火上位机协议中,参数以ASCII字符串发送(如"Kp=12.5\r\n"),但下位机解析函数未清除接收缓冲区末尾的\r\n,导致atof()解析失败返回0.0。
解决:在USART_ReceiveData()后,对接收数组执行strchr(rx_buffer, '\r')定位,并将\r及之后字符置0;或使用sscanf(rx_buffer, "Kp=%f", &kp)更鲁棒。野火第16.3.4节“解析数据包”代码已修正此问题,但初学者常直接复制旧版例程。


5. 验收与答辩:如何用一份报告让导师/客户一眼看懂你的电机控制系统

答辩不是背诵原理,而是证明你真正掌控了整个系统。我带过的十几个电机类毕设/课设项目,最终能拿高分的,都不是讲得最炫的,而是那份验收记录表填得最满、波形截图最扎实、故障日志最详实的报告。以下是我给学生定的硬性验收清单,你照着做,答辩时直接打开文档逐条演示,比讲十分钟理论更有说服力。

5.1 四维验收法:用一张表锁定系统健康度

不要只写“电机已实现闭环控制”,要量化到具体指标。我要求学生必须提交这张表,且所有数据需附原始波形截图+时间戳:

验收维度测试条件期望结果实测结果波形截图编号是否通过
启动响应空载,设定转速1000RPM启动时间≤0.5s,超调≤10%启动时间0.42s,超调8.3%Fig1_Startup✓
负载适应突加50%额定负载转速跌落≤5%,200ms内恢复跌落4.1%,185ms恢复Fig2_LoadStep✓
保护触发人为短接电流采样电阻10ms内停机,UART上报"OVER_CURRENT"9.8ms停机,日志完整Fig3_Protect✓
参数鲁棒性Kp±20%,Ki±30%转速波动≤±2%波动±1.7%Fig4_Robust✓

注意:波形截图必须包含时间轴刻度、通道标识、触发点标记。我见过太多学生贴一张模糊的示波器照片,被导师一句“这个时间标尺是多少?”直接问懵。野火配套的上位机软件(第16章)可直接导出CSV波形数据,用Excel画图更规范。

5.2 答辩演示三板斧:从“能动”到“可信”的递进式呈现

导师最怕听到“理论上应该可以”,最喜欢看到“这就是它现在的样子”。我的学生答辩时,永远按这三步走:

第一板斧:故障注入演示(证明你懂保护)

  • 当场拔掉编码器Z相信号线 → 观察电机是否立即停机并上报“ENCODER_LOST”;
  • 用镊子短接电流采样电阻 → 验证过流保护动作时间(示波器抓TIM1_BKIN引脚下降沿);
  • 这一步证明你不是调通了就结束,而是构建了可信的防护体系。

第二板斧:参数在线整定(证明你懂控制)

  • 打开野火PID上位机,实时拖动Kp滑块 → 屏幕同步显示转速曲线变化;
  • 切换到“阶跃响应”模式,注入100RPM阶跃 → 截图保存超调量、调节时间;
  • 这一步证明你掌握的不是固定参数,而是动态调控能力。

第三板斧:多工况对比(证明你懂工程)

  • 准备三组数据:空载/半载/满载下的电流-转速曲线(X-Y图);
  • 同一PID参数下,不同供电电压(12V/15V/18V)的转速稳定性对比;
  • 这一步把“单点调通”升维到“系统级性能评估”,是工程师和学生的分水岭。

5.3 答辩话术:把“我做了”变成“我解决了”

永远用问题驱动叙述,而不是技术堆砌。比如不要说:“我用了TIM1高级定时器,配置了互补PWM和死区”,而要说:

“最初电机一加速就炸MOS,查了三天才发现是上下桥臂同时导通。后来发现通用定时器不支持硬件死区,换成TIM1后,通过BDTR寄存器配置1.2μs死区,炸管问题彻底消失。这是我在第8.3节‘硬件连接’里特别标注的要点。”

再比如谈PID,不要说:“我实现了增量式PID”,而要说:

“位置式PID在满载启动时会严重超调,因为积分项累积太快。改成增量式后,输出只与本次误差相关,配合微分先行,超调从25%降到8%。这个改进记录在第15.5节‘增量式PID的C语言实现’的注释里。”

从那以后我每次带学生做电机项目,都强制他们在代码注释里写三行:

  1. 这段代码解决什么具体问题?
  2. 如果不写它,系统会出现什么现象?
  3. 这个参数(如DTG=0x7F)是怎么确定的?依据是什么?

不是为了应付检查,而是逼自己把“调通”变成“吃透”。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表