当前位置: 首页 > news >正文

全开源代码:BLDC PMSM FOC控制程序,有感无感驱动及滑膜霍尔编码器实现

全开源代码 BLDC PMSM FOC 有感 无感 滑膜 霍尔 编码器 基于STM32F1的有传感器和无传感驱动 直流无刷电机有传感器和无传感驱动程序, 无传感的实现是基于反电动势过零点实现的,有传感的霍尔实现。 永磁同步电机有感无感程序,有感为霍尔FOC和编码器方式, 无感为换滑模观测器方式。 有原理图和文档

最近在捣鼓一个全开源的电机驱动项目,用STM32F1实现了有感和无感的BLDC/PMSM驱动。这玩意儿挺有意思,尤其是无感方案在资源紧张的F1上跑起来还有点挑战性,今天就跟大伙儿唠唠实现细节。

全开源代码 BLDC PMSM FOC 有感 无感 滑膜 霍尔 编码器 基于STM32F1的有传感器和无传感驱动 直流无刷电机有传感器和无传感驱动程序, 无传感的实现是基于反电动势过零点实现的,有传感的霍尔实现。 永磁同步电机有感无感程序,有感为霍尔FOC和编码器方式, 无感为换滑模观测器方式。 有原理图和文档

先看硬件架构,核心是用三路PWM配合六步换相。原理图上MOS管驱动用的经典IR2101方案,电流采样直接用ADC怼相电压。这里有个坑:F1的ADC采样率得控制在1MHz以内,不然数据会飘。我们的ADC配置代码长这样:

void ADC_Config(void) { ADC_InitTypeDef adc; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); ADC_DeInit(ADC1); adc.ADC_Mode = ADC_Mode_Independent; adc.ADC_ScanConvMode = DISABLE; adc.ADC_ContinuousConvMode = ENABLE; adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; adc.ADC_DataAlign = ADC_DataAlign_Right; adc.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &adc); ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_71Cycles5); ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); ADC_SoftwareStartConvCmd(ADC1, ENABLE); }

有传感器方案相对简单,霍尔信号处理用外部中断触发换相。这里注意要消抖处理,我们的骚操作是在中断里启动10μs的定时器延时:

void EXTI9_5_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line8) != RESET) { TIM_OC1PreloadConfig(TIM2, DISABLE); //关闭预装载 Hall_Update(); //换相逻辑 __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, duty); //更新占空比 EXTI_ClearITPendingBit(EXTI_Line8); } }

无感方案才是重头戏,反电动势过零点检测用硬件比较器+Vbus分压。关键点在滤波处理——我们用了移动平均滤波配合滞后比较,实测在20000转时还能稳如老狗:

#define FILTER_LEN 8 uint16_t bemf_buffer[FILTER_LEN] = {0}; uint8_t Detect_ZeroCross(void) { static uint8_t index = 0; uint32_t sum = 0; bemf_buffer[index] = ADC_GetValue(); index = (index + 1) % FILTER_LEN; for(int i=0; i<FILTER_LEN; i++) sum += bemf_buffer[i]; uint16_t avg = sum / FILTER_LEN; return (avg > threshold_high) || (avg < threshold_low); }

PMSM的滑模观测器实现更刺激,核心算法在定时器中断里跑。注意F1没有FPU,得用Q格式定点数运算。关键代码段:

int32_t SMO_Estimate(int32_t ia, int32_t ib) { static int32_t z_alpha=0, z_beta=0; int32_t e_alpha = ia - (Lq*ia + z_alpha); int32_t e_beta = ib - (Lq*ib + z_beta); //滑模切换函数 z_alpha += (e_alpha > 0) ? K_SMO : -K_SMO; z_beta += (e_beta > 0) ? K_SMO : -K_SMO; //反正切求角度 return _atan2(z_beta, z_alpha); }

实测发现无感启动需要两步走:先对齐转子位置,再用三段式启动。这里有个骚操作是用PWM占空比渐变代替传统开环加速:

void Sensorless_Startup(void) { //强制对齐 PWM_Output(ALIGN_PHASE, 30); Delay_ms(300); //斜坡加速 for(int i=30; i<80; i+=2){ PWM_Output(next_phase, i); Delay_us(200); //换相间隔随转速增加 } //切入闭环 Enable_SMO_Observer(); }

项目里还藏了个彩蛋:通过宏定义切换霍尔FOC和编码器FOC。编码器方案用定时器的编码器接口模式,配合SVPWM实现真闭环。不过要注意F1的定时器只有16位,高转速时记得处理计数器溢出:

void Encoder_Config(void) { TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); TIM_SetCounter(TIM3, 32768); //初始值设为中间值防溢出 }

最后给想复现的兄弟提个醒:无感方案对PCB布局敏感,采样电阻到MCU的走线要尽量短。代码仓库里有个motor_debug.c文件,里面集成了在线观测功能,可以通过串口实时调整PID参数,这玩意儿调参时能救命。

http://www.jsqmd.com/news/454318/

相关文章:

  • COMSOL光学模型下的手性小球特性分析与模拟研究
  • 1975-2030年全球1km分辨率人口空间分布栅格数据
  • 北京留学机构TOP10优选!解锁名校申请捷径 - 博客湾
  • 【声呐技术】FS2-DETR:基于Transformer的增强特征感知小样本声呐目标检测
  • 2026年首个基于OpenClaw pi内核的商用桌面AI私域助理
  • 北京留学机构:靠谱平台助力打造高质量申请 - 博客湾
  • 互联网最常用的加密通信技术
  • 【信道估计】大规模MIMO-OFDM系统的5G通信信道估计算法研究【含Matlab源码 15125期】含文献
  • 从零实现一个进程池(基于管道通信)
  • 【快速EI检索 | SPIE出版】2026 年智能信号与图像处理国际学术会议(ISIP 2026)
  • 全球电动滚筒市场发展趋势分析
  • FOMO All In One
  • 第三部分 — 服务工作者(后台)chrome.runtime 是什么(在 MV3 的说法中)
  • matlab画图工具
  • 2005-2025年我国乡镇级的逐日最低气温数据(Shp/Excel格式)
  • 只禁止「显卡」驱动自动更新 不影响声卡、网卡、蓝牙、任何其他硬件
  • 【先到先得】夸克网盘免费领取1TB空间保姆级教程!新老用户均可!最新可用!
  • 林俊旸离职,AI 人才路在何方?
  • Python绘制相交平面
  • 2026生物医药行业纯水设备优质品牌推荐榜 - 优质品牌商家
  • 养护策略优化模型:从单设备到路网级的多维决策系统
  • openclaw 调用openai codex , python 调用
  • 如何利用熊猫智汇赋能数字员工突破业务壁垒?
  • ORA-29660错误找不到EXTERNAL NAME定义的类,远程处理故障修复思路分享
  • 吐血整理,性能测试总结汇总,多个视角分析性能压测,一篇通透...
  • 快手 C++ 面试题:如何突破封装访问私有成员?
  • 基于电解槽与甲烷反应器构建低碳综合能源系统优化策略:购能成本、碳排放与弃风成本最小化实践指导文献研究
  • 代码随想录算法营完结!
  • 全网最细,web端测试常见与最有意义的bug(总结)
  • Abaqus与Matlab联合应用:直齿轮、斜齿轮模型调试及裂纹磨损故障刚度分析,稳态瞬态温度场研究