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

【电机控制】FOC单电阻电流采样配置

文章目录

  • 前言
  • 1 基本原理
  • 2 核心功能函数
    • 2.1 基本设置
    • 2.2 获取CCR排序
    • 2.2 判断PWM是否需要偏移以及需要偏移多少,并确定ADC采样点,判断采样电流的相以及方向
    • 2.3 结合具体MCU型号的TIM以及DMA配置
  • 总结


前言

本文记录笔者在学习单电阻采样代码实现过程中的总结和思考。


1 基本原理

笔者默认本文读者对单电阻采样的原理层面已经有了基本的理解,因此仅提供如下采样时序图以及编程中一些需要重点考虑的事项。
在这里插入图片描述
这里省略采样前的各相占空比需求和CCR计算。

2 核心功能函数

2.1 基本设置

最小采样间隔时间以及其中包含的死区、开通时间、稳定时间等需要实验测定。

2.2 获取CCR排序

前面已经获取duty或ccr值,两两比较后分别赋值给max_duty_index, mid_duty_index, min_duty_index。比较简单,如下是代码段参考

#define u 0
#define v 1
#define w 2void FOC_InvClark_Tr(FOC_t *foc)
{int16_t com;foc->pCtl->Vph.s_volt[u] = foc->pCtl->Vab.va;foc->pCtl->Vph.s_volt[v] = -foc->pCtl->Vab.va / 2 + Q_Mpy(foc->pCtl->Vab.vb, SQRT3DIV2_Q);foc->pCtl->Vph.s_volt[w] = -foc->pCtl->Vab.va / 2 - Q_Mpy(foc->pCtl->Vab.vb, SQRT3DIV2_Q);if (foc->pCtl->Vph.s_volt[u] >= foc->pCtl->Vph.s_volt[v]){if (foc->pCtl->Vph.s_volt[v] >= foc->pCtl->Vph.s_volt[w]){foc->pCtl->Svpwm.max_duty_phase = u;foc->pCtl->Svpwm.mid_duty_phase = v;foc->pCtl->Svpwm.min_duty_phase = w;}else{if (foc->pCtl->Vph.s_volt[u] >= foc->pCtl->Vph.s_volt[w]){foc->pCtl->Svpwm.max_duty_phase = u;foc->pCtl->Svpwm.mid_duty_phase = w;foc->pCtl->Svpwm.min_duty_phase = v;}else{foc->pCtl->Svpwm.max_duty_phase = w;foc->pCtl->Svpwm.mid_duty_phase = u;foc->pCtl->Svpwm.min_duty_phase = v;}}}else{if (foc->pCtl->Vph.s_volt[u] >= foc->pCtl->Vph.s_volt[w]){foc->pCtl->Svpwm.max_duty_phase = v;foc->pCtl->Svpwm.mid_duty_phase = u;foc->pCtl->Svpwm.min_duty_phase = w;}else{if (foc->pCtl->Vph.s_volt[v] >= foc->pCtl->Vph.s_volt[w]){foc->pCtl->Svpwm.max_duty_phase = v;foc->pCtl->Svpwm.mid_duty_phase = w;foc->pCtl->Svpwm.min_duty_phase = u;}else{foc->pCtl->Svpwm.max_duty_phase = w;foc->pCtl->Svpwm.mid_duty_phase = v;foc->pCtl->Svpwm.min_duty_phase = u;}}}/* Insert 3rd harmonic component to generate saddle wave. */com = (foc->pCtl->Vph.s_volt[foc->pCtl->Svpwm.max_duty_phase] >> 1) + ((foc->pCtl->Vph.s_volt[foc->pCtl->Svpwm.min_duty_phase] + 1) >> 1);/* Circle limit assure duty cycle is not over 100% or less than 0%. */foc->pCtl->Vph.u_volt[u] = (uint16_t)((int32_t)foc->pCtl->Vph.s_volt[u] + (foc->pCtl->vdcPu >> 1) - com);foc->pCtl->Vph.u_volt[v] = (uint16_t)((int32_t)foc->pCtl->Vph.s_volt[v] + (foc->pCtl->vdcPu >> 1) - com);foc->pCtl->Vph.u_volt[w] = (uint16_t)((int32_t)foc->pCtl->Vph.s_volt[w] + (foc->pCtl->vdcPu >> 1) - com);
}

2.2 判断PWM是否需要偏移以及需要偏移多少,并确定ADC采样点,判断采样电流的相以及方向

代码如下(示例):

void FOC_Generate_Svpwm(FOC_t *foc)
{foc->pCtl->Svpwm.duty[u] = (uint32_t)foc->pCtl->Vph.u_volt[u] << 16 / foc->pCtl->vdcPu;foc->pCtl->Svpwm.duty[v] = (uint32_t)foc->pCtl->Vph.u_volt[v] << 16 / foc->pCtl->vdcPu;foc->pCtl->Svpwm.duty[w] = (uint32_t)foc->pCtl->Vph.u_volt[w] << 16 / foc->pCtl->vdcPu;foc->pCtl->Svpwm.ccr[u] = PWM_TIME_PERIOD - (uint32_t)foc->pCtl->Vph.u_volt[u] * PWM_TIME_PERIOD / foc->pCtl->vdcPu;foc->pCtl->Svpwm.ccr[v] = PWM_TIME_PERIOD - (uint32_t)foc->pCtl->Vph.u_volt[v] * PWM_TIME_PERIOD / foc->pCtl->vdcPu;foc->pCtl->Svpwm.ccr[w] = PWM_TIME_PERIOD - (uint32_t)foc->pCtl->Vph.u_volt[w] * PWM_TIME_PERIOD / foc->pCtl->vdcPu;// foc->pCtl->Svpwm.ccr[u] = (uint16_t)Math_Sat(ccu, T_MAX, T_MIN);// foc->pCtl->Svpwm.ccr[v] = (uint16_t)Math_Sat(ccv, T_MAX, T_MIN);// foc->pCtl->Svpwm.ccr[w] = (uint16_t)Math_Sat(ccw, T_MAX, T_MIN);#ifdef SINGLE_SHUNT_SAMPLEint8_t max_ccr_index, mid_ccr_index, min_ccr_index;max_ccr_index = foc->pCtl->Svpwm.min_duty_phase;mid_ccr_index = foc->pCtl->Svpwm.mid_duty_phase;min_ccr_index = foc->pCtl->Svpwm.max_duty_phase;/*  * __为低电平* ##为高电平* !为采样点* 情况1: 三相占空比间隔时间足够采样;* max ___#!##########___* mid _____#!######_____       ===>>>          NO SHIFT* min _______####_______* 情况2: 低调制比情况下,两两之间采样时间均不足* max ______######______                       max ____#!####________* mid ______######______       ===>>>          mid ______#!####______       以最中值为基准,max向左边平移,min向右边平移* min ______######______                       min ________######____       * 情况3: 换相时,两相间隔时间不足采样;细分为高高低,高低低两种情况,高高低的* max __##############__                       max _#!############___       * mid __##############__       ===>>>          mid ___#!############_       以中值为基准,max向左边平移* min _______####_______                       min _______####_______* max _################_                       max _#!##############_* mid _______####_______       ===>>>          mid _______#!##_______       以中值为基准,min向右边平移* min _______####_______                       min _________####_____       *! 为确保采样时间足够,并通过单次平移实现足够采样时间,CCR_MAX < PERIOD - T_GAP_MIN, CCR_MIN > T_GAP_MIN*/int16_t d_max_mid, d_mid_min;int16_t ccr_max_shift, ccr_min_shift;d_max_mid = foc->pCtl->Svpwm.ccr[max_ccr_index] - foc->pCtl->Svpwm.ccr[mid_ccr_index];d_mid_min = foc->pCtl->Svpwm.ccr[mid_ccr_index] - foc->pCtl->Svpwm.ccr[min_ccr_index];if (foc->pCtl->Svpwm.ccr[mid_ccr_index] - foc->pCtl->Svpwm.ccr[min_ccr_index] >= T_GAP_MIN){//ccr min index phase sample time OK. Current direction is positive.}else{ccr_min_shift = T_GAP_MIN - d_mid_min;if (foc->pCtl->Svpwm.ccr[min_ccr_index] > ccr_min_shift){// Shift action must confirm that right ccr value is greater than 0foc->pCtl->Svpwm.ccr_dma_buffer_latch[min_ccr_index] = foc->pCtl->Svpwm.ccr[min_ccr_index] - ccr_min_shift;foc->pCtl->Svpwm.ccr_dma_buffer_latch[min_ccr_index + 3] = foc->pCtl->Svpwm.ccr[min_ccr_index] + ccr_min_shift;foc->pCtl->Svpwm.adc_signal[0] = 1;}else{/* Shift space is not enough. Est current inherit from last cycle. Skip flag required. */foc->pCtl->Svpwm.ccr_dma_buffer_latch[min_ccr_index] = foc->pCtl->Svpwm.ccr[min_ccr_index];foc->pCtl->Svpwm.ccr_dma_buffer_latch[min_ccr_index + 3] = foc->pCtl->Svpwm.ccr[min_ccr_index];foc->pCtl->Svpwm.adc_signal[0] = 0;}}if (foc->pCtl->Svpwm.ccr[max_ccr_index] - foc->pCtl->Svpwm.ccr[mid_ccr_index] >= T_GAP_MIN){//ccr max index phase sample time OK. Current direction is negative.}else{ccr_max_shift = T_GAP_MIN - d_max_mid;// Shift action must confirm that left ccr value is less than ARif (foc->pCtl->Svpwm.ccr[max_ccr_index] + ccr_max_shift < PWM_TIME_PERIOD){foc->pCtl->Svpwm.ccr_dma_buffer_latch[max_ccr_index] = foc->pCtl->Svpwm.ccr[max_ccr_index] + ccr_max_shift;foc->pCtl->Svpwm.ccr_dma_buffer_latch[max_ccr_index + 3] = foc->pCtl->Svpwm.ccr[max_ccr_index] - ccr_max_shift;foc->pCtl->Svpwm.adc_signal[1] = -1;}else{/* Shift space is not enough. Est current inherit from last cycle. Skip flag required. */foc->pCtl->Svpwm.ccr_dma_buffer_latch[max_ccr_index] = foc->pCtl->Svpwm.ccr[max_ccr_index];foc->pCtl->Svpwm.ccr_dma_buffer_latch[max_ccr_index + 3] = foc->pCtl->Svpwm.ccr[max_ccr_index];foc->pCtl->Svpwm.adc_signal[1] = 0;}}foc->pCtl->Svpwm.ccr_dma_buffer_latch[mid_ccr_index] = foc->pCtl->Svpwm.ccr[mid_ccr_index];foc->pCtl->Svpwm.ccr_dma_buffer_latch[mid_ccr_index + 3] = foc->pCtl->Svpwm.ccr[mid_ccr_index];/* Set CCR4 to the very first sampling pointwhen CNT matches CCR4 value (first sampling point), it raises CH4 signal:- it triggers the first ADC injected conversion- it triggers a DMA transfer to load CCR4 with the second sampling valuewhich lowers CH4 signal.when CNT matches CCR4 value (second sampling point value) it raises CH4 signal- it triggers the second ADC injected conversion- it triggers a DMA to transfer to load 0 into CCR4 register which makes CH4stay high until next PWM cyclewhen CNT matches CCR4 value (0 i.e start of a new PWM cycle) it lowers CH4 signal- it triggers a DMA to transfer to load CCR4 with the first sampling point value */foc->pCtl->Svpwm.ccr_adc[0] = foc->pCtl->Svpwm.ccr_dma_buffer_latch[min_ccr_index] + T_RISE;foc->pCtl->Svpwm.ccr_adc[1] = foc->pCtl->Svpwm.ccr_dma_buffer_latch[mid_ccr_index] + T_RISE;foc->pCtl->Svpwm.ccr_adc[2] = 0;foc->pCtl->Svpwm.adc_index[0] = min_ccr_index;foc->pCtl->Svpwm.adc_index[1] = max_ccr_index;foc->pCtl->Svpwm.adc_signal[0] = 1;foc->pCtl->Svpwm.adc_signal[1] = -1;#endif
}

2.3 结合具体MCU型号的TIM以及DMA配置

本文以国民N32G435的配置为例:


总结

本文借鉴了ST MCSDK单电阻采样的写法,但也有诸多配置和策略上的不同,代码是笔者手敲的,仅供参考,欢迎指正。
注:笔者并没有采用常规的六分区写法,而是采用了三次谐波插入法做变换计算生成马鞍波。

http://www.lryc.cn/news/617819.html

相关文章:

  • DHCP 服务详解与部署
  • React 19 通用 ECharts 组件
  • Redis应⽤-缓存与分布式锁
  • Linux驱动学习day27天(USB驱动理论部分)
  • 修改学生信息管理系统以及查询
  • Ansys Mechanical中的声学分析
  • Nestjs框架: RBAC基于角色的权限控制模型初探
  • java内部类-匿名内部类
  • 适用于高质量核磁共振(NMR)的溶剂推荐
  • Apache ECharts 6 核心技术解密 – Vue3企业级可视化实战指南
  • 每日五个pyecharts可视化图表-line:从入门到精通 (3)
  • 编程技术杂谈4.0
  • SQL复杂查询
  • 论文学习22:UNETR: Transformers for 3D Medical Image Segmentation
  • TCGA数据集下载工具gdc-client下载慢解决方案
  • 掘金数据富矿,永洪科技为山东黄金定制“数智掘金”实战营
  • JavaScript let的使用
  • macos彻底删除vscode
  • 2025年农业工程与环境预防国际会议(ICAEEP 2025)
  • k8s 部署mysql主从集群
  • 用AListLite让安卓手机成为NAS实现文件共享
  • 基于开源模型构建医疗疾病大模型:从理论到实践
  • 2025牛客多校第八场 根号-2进制 个人题解
  • USB 基本描述符
  • TRL - Transformer Reinforcement Learning SFTTrainer 和 SFTConfig
  • AI(2)-神经网络(激活函数)
  • 当生产环境卡成 PPT:Spring Boot 线程 Dump 捉妖指南 - 第544篇
  • 【09-神经网络介绍2】
  • 数据结构-排序(2)
  • 【排序算法】⑦归并排序