FOC-VESC

开源DIY3天前更新 半隐
19 00

VESC是个开源电机控制器项目,全称Vedder Electronic Speed Controller。2015年瑞典工程师Benjamin Vedder开发出来,最初是给电动滑板用的。后来被各种改装,电动自行车、平衡车、机器人关节、无人机都在用。

这个项目的特点是算法全面。FOC磁场定向控制、无感启动、参数自辨识、双电机同步控制都实现了。不是那种演示性质的代码,是真正经过大规模应用验证的工程方案。

硬件平台是STM32F405,Cortex-M4内核,主频168MHz,带FPU硬件浮点单元。外围搭配DRV8302三相栅极驱动芯片,支持100A峰值电流。三电阻采样,母线电压用分压电路采样,温度传感器是NTC热敏电阻。

软件跑ChibiOS实时操作系统。ChibiOS是个轻量级RTOS,代码量小,实时性好,调度延迟在微秒级。整个控制架构是硬件中断加后台线程的混合模式。FOC控制循环在ADC中断里完成。后台线程处理通信、参数更新、故障监控这些不需要硬实时的任务。

代码组织挺清晰。电机控制核心其实就三个C文件:

  • mc_interface.c:电机接口层,处理上层指令到底层执行的转换
  • mcpwm_foc.c:FOC算法实现,包括电流环、观测器、HFI注入
  • foc_math.c:数学库,Clarke/Park变换、SVPWM、PLL锁相环

这三个文件加起来不到1万行,但包含了一个完整FOC控制器该有的所有功能。代码注释很详细,数学公式都标出了出处,有些地方还有推导过程。单元测试覆盖率60%以上,tests目录下有一堆测试用例。

配套的VESC Tool上位机软件很强。实时监控波形、调参数、参数辨识、固件升级全都能在图形界面上完成。这对调试帮助很大,不用每次都改代码重新烧录。

代码仓库里有417个硬件配置文件。不同的VESC衍生板,电流采样电阻阻值不一样,运放增益不一样,温度传感器型号不一样,都需要单独的配置。这417个配置文件覆盖了市面上几乎所有的VESC变体。想移植到自己板子上,找个最接近的配置文件改改就能用。

系统架构

硬件资源分配

STM32F405的外设资源我总结成了一个表格:

资源用途配置说明
TIM1电机1三相PWM输出中心对齐模式,频率20-40kHz可配,典型30kHz
TIM8电机2三相PWM输出双电机版本使用,配置同TIM1
TIM2ADC采样触发CC2通道与TIM1同步,触发频率=PWM频率
TIM5系统计时器1MHz基准,用于时间戳和性能统计
ADC1三相电流采样注入模式,3通道同时转换,12位精度
ADC2/3电压温度采样规则模式,DMA扫描
DMA2ADC数据搬运Stream4,循环模式,零CPU占用
CAN1多电机通信1Mbps,扩展帧格式,支持多机同步
USART1-4调试和通信115200-2Mbps可配
USB FS上位机连接CDC虚拟串口
CCM RAM实时变量存储16KB零等待周期,存放中断临时变量

TIM1负责生成三相PWM,中心对齐模式。(中心对齐的好处是PWM波形的中心位置正好是电流采样的最佳时刻,此时上桥臂和下桥臂都导通,开关噪声最小)

频率一般配在20-40kHz之间。(太低了电机噪音大,电流纹波也大。太高了开关损耗增加,MOSFET发热严重)死区时间配成200纳秒。(这个时间要根据MOSFET的开关特性调。太小会导致桥臂直通,上下管同时导通,短路烧管子。太大会让死区效应明显,电流波形畸变,谐波增加)

TIM2专门用来触发ADC采样。CC2通道跟TIM1同步,在每个PWM周期的中心位置产生触发信号。ADC工作在注入模式,硬件触发启动转换。注入模式的优先级比普通模式高,可以打断正在进行的普通转换,保证电流采样不会被延迟。

三相电流通过ADC1的三个注入通道同时采样。转换完成后,DMA自动把数据从ADC的数据寄存器搬到内存缓冲区。DMA配置成循环模式,最后触发中断通知CPU。

整个采样链路的延时控制得很严。从PWM中心点到ADC触发信号,硬件延时小于100纳秒。ADC转换1微秒,DMA搬运几乎没有延时,中断响应大约1微秒。总延时在2-3微秒以内,相对于33微秒的控制周期占比不到10%。 

中断优先级

优先级0(最高) → ADC注入完成中断(电流环控制) 优先级1      → TIM2触发中断(采样同步) 优先级2       → 编码器脉冲中断 优先级3       → CAN总线中断 优先级4      → UART接收中断 优先级5(最低) → USB中断

这个优先级顺序保证了电流环中断不会被任何任务打断。其他任务都可以等,但电流环不能等。STM32F405有个特殊的内存区域叫CCM RAM(Core Coupled Memory),16KB大小,零等待周期。普通SRAM访问需要经过AHB总线仲裁,有时候会被DMA占用,产生等待周期。CCM RAM直接连到CPU内核,不经过总线,访问速度最快。

(VESC把电流环中断里用到的临时变量都放在CCM RAM里。每个周期几十次的内存访问,每次省一个时钟周期,加起来能省不少时间。这种细节优化在实时控制里很重要)

软件架构

软件是两层架构。底层是硬实时中断,上层是软实时线程。

硬实时层(中断)

  • ADC注入完成中断:30kHz频率,处理FOC控制循环
  • TIM2触发中断:同步PWM更新
  • 编码器中断:捕获位置脉冲,更新角度

软实时层(线程)

  • timer_thread(1kHz):温度采样、电压滤波、故障检测、看门狗喂狗
  • hfi_thread(事件触发):HFI高频注入的FFT处理,计算量大,不能放中断
  • pid_thread(1kHz):速度环PI控制、位置环PI控制

这种分层设计的核心思想是:电流环必须硬实时,不能被任何任务打断。其他算法,哪怕很重要,也要放在后台线程,避免影响电流环的时间确定性。

HFI算法就是个典型例子。高频注入需要做FFT变换,计算量不小。如果把FFT放在电流环中断里,中断执行时间会超过33微秒,下一个周期就来不及处理了。VESC的做法是,中断里只做简单的采样和注入,把采样数据扔到缓冲区。后台线程从缓冲区读数据,做FFT,算出角度,再把结果写回去。中断下次读取时,用的是上一次FFT的结果。这样有一个周期的延迟,但不影响控制性能,因为转子位置变化是连续的,延迟可以预测补偿。

启动流程也是围绕这个架构设计的:

上电后先跑HAL初始化和ChibiOS内核启动,配置时钟树、GPIO、中断向量表。然后进入电机模块初始化

定时器配置完,ADC和DMA配置完,就要做电流零点校准。这一步很关键。关闭PWM输出,让电机处于自由停止状态,连续采样1000次,计算三相电流的ADC平均值。这个平均值就是零点偏置。后面每次采样都要减掉这个偏置,否则会有几安培的直流误差。

零点偏置不是固定值。ADC参考电压有波动,运放有失调电压,温度变化也会影响。所以每次上电都要重新校准。有些设计会把零点偏置存到Flash里,但VESC没这么做,每次上电都测一遍,更可靠。

观测器初始化就是把状态量清零,x1=0, x2=0,phase=0, speed=0。如果是第一次启动,这些值确实是零。如果是运行中重启(比如故障恢复),这些值可能不是零,但代码里还是强制清零,让观测器重新收敛。收敛时间大约几十毫秒,对用户体验影响不大。

后台线程启动后,主循环进入死循环,不停地休眠10毫秒。所有控制逻辑都在中断和线程里跑,主循环什么都不干。这是RTOS的典型用法,主循环只是个占位符,真正的任务都是事件驱动的。

FOC控制循环

电流环控制在ADC注入完成中断里执行。函数是

mcpwm_foc_adc_int_handler,这个中断每33微秒触发一次,对应30kHz的PWM频率。

中断里要完成一个完整的FOC循环:

流程很标准。读ADC,Clarke变换,获取角度,Park变换,PI控制,解耦,限幅,逆Park,SVPWM,更新PWM,观测器更新。

但工程实现有很多细节。Clarke变换会强制三相电流和为零,消除采样误差。Park变换用查表法算sin/cos。解耦补偿加了交叉耦合项和反电势项。电压限幅采用d轴优先策略,保证弱磁控制的稳定性。SVPWM的扇区判断用符号位运算,省掉多个if分支。

这些优化累加起来,整个中断实测24微秒左右,留9微秒裕量。CPU占用率70%,还有30%应对参数波动和负载变化。(这些细节到后面我都会一个个拆解,给大家呈现,这篇只做介绍)

【核心算法】

把VESC代码扒了一遍,列出最值得学习的技术点。这些算法后面会逐期详细拆解

1. 参数离线自辨识

VESC实现了全自动参数辨识。电阻测量用直流注入法,给定电流看稳态电压。电感测量用高频方波注入,测电压斜率算di/dt。磁链测量靠开环旋转,测反电势峰值。凸极率测量用多角度扫频,对比不同方向的电流响应。

加上编码器矫正,整个流程3分钟跑完,精度±5%。测完后参数自动写入配置,直接能用。不需要拆电机,不需要示波器,上位机点个按钮就行。

这个功能对快速调试帮助很大。换个电机,跑一遍辨识,PI参数自动整定好。比手动测参数效率高太多。

(预告第5期详细讲辨识流程、误差来源、补偿策略)

2. 七种观测器算法

无感控制的核心是位置观测器。VESC支持7种算法,运行时可切换。

经典的Ortega算法,基于反电势磁链积分。MxLemming算法是MESC项目贡献的优化版,低速稳定性更好。MxV系列有3个变种,分别针对不同的电机参数。还有带λ补偿的版本,处理磁路饱和。

不同算法适用场景不一样。低速用MxLemming,高速用Ortega精度高。永磁同步电机和内置式电机选择也不同。代码里都实现了,配置文件切换就行。

观测器的数学原理其实不复杂,就是状态方程加误差校正。但工程实现有很多坑。磁链幅值要限幅,否则积分器会发散。电阻温度漂移要补偿,不然角度误差累积。采样噪声要滤波,但滤波器又引入相位滞后。

(预告第3期对比各观测器原理、收敛性、误差特性)

3. HFI高频注入

低速时用HFI高频注入。物理原理是永磁同步电机存在凸极效应,d轴电感Ld和q轴电感Lq不相等。注入高频电压(1-2kHz),测电流响应,响应大的方向就是d轴。

VESC支持4种注入模式。6向量旋转注入,鲁棒性好但计算量大。±45度脉冲注入,简单但噪声敏感。单轴脉冲加FFT,精度高需要后台线程处理。优化单轴V5算法,当前的主流方案。

在极性判断中。d轴有两个方向,N极和S极。单纯的高频注入只能确定轴线,分不清极性。VESC在启动前累积128个样本,旋转注入方向,统计哪个方向电流响应更大。这个方向就是N极。整个过程4-5毫秒。

HFI只在低速用。加速到1500 ERPM后,反电势够大了,自动切换到观测器模式。切换过程做了平滑处理,角度不会跳变。

(预告第3期讲HFI注入波形、FFT解调、极性消歧、切换策略)

4. 温度自适应

铜线电阻温度系数0.39%/°C。电机从25°C跑到80°C,电阻涨21%。

电阻变了,PI参数不跟着调就会出问题。积分时间常数Ti = L/R,R变大Ti变小,电流环动态特性偏移。解耦补偿的前馈项也用R,R不准解耦效果就差。观测器的电压方程里有R·i项,R偏了磁链估算就错,角度误差累积。

VESC每1ms读一次电机温度,NTC热敏电阻采样。温度通过B值方程换算成开尔文,然后用线性模型修正电阻:R(T) = R0 × (1 + α(T – T0))。修正后的R用在解耦补偿和观测器里。

还有个细节,Ki也要跟着调。电阻变了,极点位置变了,保持相同的闭环特性需要动态调整Ki。代码里实现了这个补偿,冷启动和热态的控制性能基本一致。

除了温度,磁路饱和也要补偿。大电流时磁路饱和,磁链λ会下降。VESC根据电流幅值动态调整λ的估计值,保证观测器在全电流范围内都准确。

温度补偿推导、磁路饱和模型、负载自适应)

解耦推导、PI整定公式、抗饱和设计、弱磁控制)

6. 快速三角函数

Park变换每个周期要算4次sin/cos(正反变换各2次)。标准库函数sinf()和cosf()太慢,一次调用100+时钟周期。

VESC的方案是查表加线性插值。预先把0到2π的sin和cos值存在数组里,步长0.01弧度,一共629个点。运行时根据角度找最近的两个点,线性插值得到结果。

插值公式很简单:

index = angle / 0.01; frac = angle - index * 0.01; sin_val = sin_table[index] + frac * (sin_table[index+1] - sin_table[index]);

精度0.001,角度误差小于0.06度。耗时只有10个时钟周期,比标准函数快10倍。

查表数组结构、插值算法、精度分析)

7. 智能电流采样

三相PWM有死区。占空比太低(<10%)或太高(>90%)时,开关管导通时间太短,ADC采样会碰到死区,采不到准确值。

VESC实现了三种采样模式,根据占空比自动切换:

最长零矢量模式:选择PWM占空比最低的相进行采样,避开死区。但只能采两相,第三相要算出来。

完整Clarke变换模式:三相都采样,完整Clarke变换。精度最高但要求占空比在合理范围(10%-90%)。

高电流模式:选电流最小的两相采样,推算第三相。扩大了电流测量范围。

代码里每个周期判断当前占空比,选择合适的模式。切换是无缝的,不会产生电流跳变。

讲采样时序、死区影响、模式切换逻辑)

8. SVPWM扇区优化

传统SVPWM算法判断扇区要6个if语句,逐个判断电压矢量落在哪个区域。

VESC用符号位运算一次判断。α和β的符号组合直接对应扇区号,用位操作和查表实现,省掉了多个分支跳转。

具体实现涉及一些位运算技巧,但核心思想是把条件判断转成算术运算。CPU执行算术运算比条件跳转快,分支预测失败的代价也省了。

这个优化在中断里能省几百纳秒。虽然听起来不多,但33微秒的预算里,每一点时间都很宝贵。

SVPWM扇区判断、过调制处理、死区补偿)

9. 双电机同步控制

硬件支持两个电机。TIM1管电机1,TIM8管电机2。两个定时器配置相同,可以独立控制,也可以同步控制。

同步控制通过CAN总线实现。一个控制器做主机,发送时间戳和目标值。其他控制器做从机,接收时间戳同步自己的动作。时间戳误差可以控制在1ms以内。

应用场景很多。四轮驱动的电动车,四个电机要协同输出扭矩。双电机云台,两个电机要同步转动保持平衡。机器人多关节,各个关节要配合完成动作。

CAN总线的带宽是个限制。1Mbps的速率,发送一帧扩展帧大约100微秒。如果同步频率太高,CAN总线会占满。VESC的做法是低频同步(100Hz),高频控制各自独立。

CAN协议、时间戳对齐、力矩分配、故障隔离)

10. 多层故障保护

VESC的故障保护做了多层设计。

硬件层:比较器监测相电流,超过阈值(比如150A)立即触发TIM1的刹车输入,硬件关断PWM输出。响应时间小于500纳秒,MOSFET来不及烧毁。

软件层:ADC中断里检测电流,超过软件限流值(比如120A)立即切换到刹车模式。响应时间是一个控制周期,33微秒。

热保护:定时器线程读取温度,MOSFET温度超过100°C限流50%,超过120°C停机。电机温度超过设定值也限流或停机。

通信超时:500ms没收到上位机指令,自动刹车停机。防止通信断开后电机失控。

配置保护:Flash存储的配置带CRC32校验。读配置时先验证CRC,损坏了就加载上一个备份。写配置时用磨损均衡,选择擦写次数最少的扇区。

这些保护机制让VESC在各种异常情况下都能安全关断,不会烧硬件。实际应用中碰到过几次堵转和过流,硬件保护直接切断输出,板子完好无损。

(电机故障诊断以及故障保护)

代码质量评价

优点:

从工程角度看,VESC的代码已经很成熟。

注释详细,公式都标出了出处。比如观测器部分,代码里直接引用了论文编号,想深入理解去翻论文就行。数学推导虽然没全写,但关键公式都有。

分层也很清晰。硬件抽象层把板子相关的配置抽出来,核心算法不用改。换个板子,改配置文件就能用。这种设计让417个硬件变体能共用一套代码。

单元测试覆盖率60%+。tests目录下有数学库的测试、观测器的测试、SVPWM的测试。虽然不是100%覆盖,但关键算法都测到了。出问题容易定位。

配套的VESC Tool上位机很强大。实时波形监控,参数在线调整,配置导入导出,固件升级,参数辨识,全都在图形界面上完成。调试效率比用串口命令行高太多。

缺点:

mcpwm_foc.c单文件5368行,太长了。找个函数要翻半天。虽然函数划分还算清楚,但维护成本高。理想情况应该拆成几个子模块:电流环控制、观测器、HFI、PWM硬件驱动。

全局变量用得有点多。m_motor_1、m_motor_2这种,虽然用static限制了作用域,但函数之间的数据流不够清晰。有些函数直接操作全局状态,不看实现不知道它干了啥。

宏嵌套深。有些宏定义展开三四层才能看到真正的代码。比如M_MOTOR(is_second_motor)这种,要跳转好几次才知道它访问了哪个结构体。可读性受影响。

观测器部分缺理论推导。代码实现了7种算法,但没有文档解释它们的数学基础、收敛条件、适用范围。想深入理解得自己去翻论文,门槛有点高,后面我会尽量结合自己的知识进行推导。

不过从工程角度看,这些不足不影响使用。代码已经在上万台设备上跑过,稳定性有保障。作为学习FOC控制的工程实现,VESC是很好的参考。

© 版权声明

相关文章

没有相关内容!

暂无评论

none
暂无评论...