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

【嵌入式电机控制#26】BLDC:三相模拟采集

        之前有些网友试着用有刷的平均电流法采集三相,还搞了个闭环控制。求!结果直接把驱动板给干没了......

        做过仿真的朋友们都知道,无刷电机的相电流波形是介于方波和正弦波的。如果拿平均电流去测量,很不靠谱。

        这节内容为大家分享采集三相模拟量的通用配置思路。

        一、CubeMX的ADC初始化

        使能三个ADC通道,分别传输UVW线电流(Y型下等于相电流)

                

        四分频表示APB2总线/4,也就是说ADC频率为72Mhz/4 = 18Mhz 这是我们F1下ADC的基础频率。若用F407系列请自行计算。

        12倍原始采样率、右对齐、扫描转换模式开、EOC选择顺序转换、连续转换模式开、DMA连续请求开、常规采样开、

        cycle转换通道量为2.5/3(因型号不同),我这里设置的是2.5cycles,表示2.5个ADC基础周期采集一次rank1,由此我们可推算出各个通道的采样频率

        接着设置所有rank对应的通道(1,2,3)、采样周期为3个循环     

        (ARM架构上绝大部分三相采集都如此配置,可以记住,原因比较难解释)

           接着配置DMA, 虽然最终数据寄存器float是32位,但是我们用的是12位采样,DMA寄存器是uint16_t的,一次读两个字节刚合适,不要把概念搞混淆了。

           

          二、ADC的DMA中断处理逻辑

uint16_t g_adc_firstave_result[3];
//一次均值结果寄存//一次均值函数
int32_t ADC_GetSampleAvgN(int16_t *Data)
{uint32_t temp[ADC_CH_NUM] = {0,0,0};     //初始化结果寄存器int i,j;         //ij计数变量for(i=0;i<ADC_COLL;i++)   //COLL为每个ADC通道的DMA容量{   //在顺序DMA采集中 DMA寄存器的内容结构为 RANK1数据 RANK2数据 RANK3数据......以此类推          for(j=0;j<ADC_CH_NUM;j++)                   {    //NUM为参与顺序DMA的总通道数temp[j] += ADC_ConvValueHex[j+i*ADC_CH_NUM];//temp也按rank排序,把DMA寄存器中,每个独立通道的数据累加}}for(j=0;j<ADC_CH_NUM;j++){//对每个独立通道的累加值求均值temp[j] /= ADC_COLL;//把中间变量值传给最终结果Data[j] = temp[j];       }
}void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)  
{int32_t ADConv = 0 ; //停止DMA,保证数据时序完整性HAL_ADC_Stop_DMA(hadc);//进行一次滤波,并获取数据  ADC_GetSampleAvgN((int16_t*)g_adc_firstave_result);//重新让DMA工作HAL_ADC_Start_DMA(hadc,(uint32_t*)ADC_ConvValueHex, ADC_CH_NUM * ADC_COLL);
}

         三、定时器中断处理逻辑

 if(timeTickCurrent != 0)timeTickCurrent--;else {if(Motor_State==MOTOR_ENABLE){
//当电机运行时,读取实际的电流(相电流+偏置电流)for(uint8_t i=0; i<3; i++){adc_val_m1[i] = g_adc_firstave_result[i];   adc_amp[i] = adc_val_m1[i] - adc_amp_offset[i][ADC_AMP_OFFSET_TIMES];if(adc_amp[i] >= 0)    adc_amp_un[i] = adc_amp[i];							}
//U相电流
current[0] = ((float)(adc_amp_un[0] * VOLT_RESOLUTION)- 1650.0f)/4020.0f/SM_REST;
//V相电流
current[1] = ((float)(adc_amp_un[1] * VOLT_RESOLUTION)- 1650.0f)/4020.0f/SM_REST;
//Z相电流
current[2] = ((float)(adc_amp_un[2] * VOLT_RESOLUTION)- 1650.0f)/4020.0f/SM_REST;/*W*/Vofa_data(current[0],VOFA_CHANNEL1);
Vofa_data(current[1],VOFA_CHANNEL2);
Vofa_data(current[2],VOFA_CHANNEL3);//上传到上位机//一节低通滤波暂时不用//						current[0] = ((float)(1-FILTER_Q_CURRENT) * LS_Speed_hz) + (FILTER_Q_CURRENT * Speed_hz) ;
//						current[1]= ((float)(1-FILTER_Q_CURRENT) * LS_Speed_hz) + (FILTER_Q_CURRENT * Speed_hz) ;
//						current[2]= ((float)(1-FILTER_Q_CURRENT) * LS_Speed_hz) + (FILTER_Q_CURRENT * Speed_hz) ;}
if(Motor_State==MOTOR_DISABLE){//当电机停止的时候uint8_t i;//三个均值变量,用于寄存UVW三相的偏置电压uint32_t avg[3] = {0,0,0};//这里直接用了二维数组存放偏置量//结构为  通道1p1 通道1p2 通道1p3 ... 通道1pn//通道2p1 通道2p2 通道2p3 ... 通道2pn//以此类推adc_amp_offset[0][adc_amp_offset_p] = g_adc_firstave_result[0]; adc_amp_offset[1][adc_amp_offset_p] = g_adc_firstave_result[1];adc_amp_offset[2][adc_amp_offset_p] = g_adc_firstave_result[2];adc_amp_offset_p++;//若数据采集满,进行二次均值滤波if(adc_amp_offset_p >= ADC_AMP_OFFSET_TIMES){adc_amp_offset_p = 0;}//进行均值累加   for(i = 0; i < ADC_AMP_OFFSET_TIMES; i++)              {avg[0] += adc_amp_offset[0][i];avg[1] += adc_amp_offset[1][i];avg[2] += adc_amp_offset[2][i];}//进行平均并把数据重新传回offset最后一列,作为标准偏置for(i = 0; i < 3; i++)                             {avg[i] /= ADC_AMP_OFFSET_TIMES;adc_amp_offset[i][ADC_AMP_OFFSET_TIMES] = avg[i];  }}//我这里的偏置采集量设置的是50次,而采集一次相电流所需时间大概在1.5ms左右,所以在电机启动前需要一个至少大于75ms的delaytimeTickCurrent = TIMECNT_CURRENT;}

        四、相电流开环图像

        此时测量的是平均相电流图像,与仿真时的实时图像有所区别,一般不会有周期性的0出现,如果出现了,就得考虑以下采样频率是不是取的过大。

        在实际工程中,最常用的是平均电流做控制。在高精度场景下,也有用实时电流做控制的,但其相应的控制器响应要求更高,经典控制算法无法达到这种需求。

        其次,查看你的三相电流是不是满足波峰交替的,如果重合成了一条线,那你的DMA配置及处理过程必然有错误。

        

http://www.dtcms.com/a/317048.html

相关文章:

  • springboot项目前后端通用下载方法、问题和解决方案
  • [滑动窗口]904. 水果成篮
  • Maven入门到精通
  • Linux网络编程基础-简易TCP服务器框架
  • Unity笔记(一)——生命周期函数、Inspector面板、MonoBehavior、GameObject
  • Go语言版JSON转TypeScript接口生成器:支持智能递归解析与命名优化
  • 超细整理,接口测试基础+流程,真实环境下怎么测...
  • [GESP202309 四级] 2023年9月GESP C++四级上机题题解,附带讲解视频!
  • 解锁音频创作新可能:AI 人声伴奏分离神器 Replay 深度解析
  • Python 进行点云ICP(lterative Closest Point)配准(精配准)
  • 【Java String】类深度解析:从原理到高效使用技巧
  • 数论手机辅助:打造便捷高效的移动应用交互体验
  • Wisdom SSH:数据库自动化运维的坚固基石
  • WARNING: Illegal reflective access by org.apache.ibatis.reflection.Reflector
  • 八股——IM项目
  • 多端同步新解法:Joplin+cpolar联合通过开源设计实现跨平台无缝协作?
  • 2025年测绘程序设计模拟赛一--地形图图幅编号及图廓点经纬度计算
  • Python日志记录库——logaid
  • 磁悬浮转子振动控制:主动电磁力如何成为高速旋转的“振动克星”
  • 数据集相关类代码回顾理解 | sns.distplot\%matplotlib inline\sns.scatterplot
  • LeetCode 刷题【31. 下一个排列】
  • Golang 基本数据类型
  • 【vibe coding】Kubernetes + Nginx Ingress 实现云端Workspace容器分配与域名访问方案
  • Linux lvm逻辑卷管理
  • MySQL间隙锁在查询时锁定的范围
  • lesson32:Pygame模块详解:从入门到实战的2D游戏开发指南
  • Python 3.13 预览版:颠覆性特性与实战指南
  • 项目设计模式草稿纸
  • 电感矩阵-信号完整性分析
  • ob数据库是什么