创建FOC电流闭环工程遇到的问题

这一次创建完整的电流闭环工程我耗费了比之前都要长的时间,算是对心态和技术的双重考验了。

1.电流环相对于之前的速度环,角度环FOC,需要添加ADC的相关配置,这里我不做说明,只提几个对于FOC比较重要的问题。

首先,我要强调的是ADC读取的一个时效性。

因为电流环频率是很高的,所以这就要求采集ADC值到算出电流值这一过程要足够迅速。

我用的是STM32F407ZGT6,可以将ADC最高配置到30多MHZ,但是我认为没有必要,21MHZ完全足够了。因为转换时间是固定的,为12.5 cycles,而采样周期是用户自己决定的,如果ADC时钟频率过高,转换时间就太低了,可能会使数据传输错误的。然后就是需要对整个ADC采样周期和转换周期进行计算,以21MHZ的时钟频率为例。

首先需要明确,电流环的频率至少是要10KHZ以上的,所以ADC采集电流的时间要<100us,然后就是要根据你们的电路安排来选择采样周期。我这个只需要采集两路的ADC,而且,采样周期越长,ADC电路中的电容充电时间越长,获得的电压也会更加精确与稳定,所以我选择了采样周期里的最大值480cycles。

两路ADC采样所需要花的时间大概是47us,也就是差不多21.28KHZ,对于电流环的频率来说绰绰有余,再算上帕克变换,克拉克变换和其他一些运算所需的时间,电流环执行下来的一套时间,肯定是小于100us的,这样就能确保电流环不会滞后,同时也使ADC电容充电的时间更久,采样值更精确。

2.其次要强调的点就是ADC+DMA传输转运ADC值的话,必须用uint16_t类型的变量就接,并且在后面的运算中一定要强制转换为float类型去进行运算。

一般我是建议开启DMA的,因为DMA把从ADC那里得到的值搬运到目标数组上不占用CPU资源。而如果用到DMA的话,就不得不提到这个函数,

volatile uint16_t adc_value[2]={0,0};

HAL_ADC_Start_DMA(&hadc1,(uint32_t*)adc_value,2);

传入的第二个参数必须是uint16_t类型的,不然DMA那里过来的数据无法正确接收。那么既然ADC值是无符号整形的话,在做运算的话就一定要(float)adc_value[0],不然/4095这么大的数,结果会直接是0。

#include "electricity.h"

float adc1_sum=0,adc2_sum=0;
float adc1_init=0,adc2_init=0;
float current_a=0.0f,current_b=0.0f;
#define _1_SQRT3 0.57735026919f
#define _2_SQRT3 1.15470053838f
#define _ADC_CONV 3.3f/4095.0f

void electricity_init(void)
{
	HAL_Delay(1000);
	for(int i=0;i<1000;i++)
	{
		adc1_sum+=(float)adc_value[0]*_ADC_CONV;
		adc2_sum+=(float)adc_value[1]*_ADC_CONV;
		HAL_Delay(1);
	}
	adc1_init=adc1_sum/1000.0f;	
	adc2_init=adc2_sum/1000.0f;
}

float calculate_current(float angle)
{
	current_a=((float)adc_value[0]*_ADC_CONV-adc1_init)/50.0f/0.01f;  //经过ADC转换为电流值公式得到该小数
	current_b=((float)adc_value[1]*_ADC_CONV-adc2_init)/50.0f/0.01f;
	
    float I_alpha=current_a;
    float I_beta = _1_SQRT3 * current_a + _2_SQRT3 * current_b;

    float ct = cos(angle);
    float st = sin(angle);
    //float I_d = I_alpha * ct + I_beta * st;
    float I_q = I_beta * ct - I_alpha * st;
    return I_q;
}

接下来要说的就是这个公式:

这个就是把得到的ADC值转换成电流值的通式了。其中里面的那个2048只是一个理论值,真正这个值是要在电机不转的情况下去多获取几次ADC值取平均值才能得到的。*3.3V表示ADC的供电电压是3.3,4095是因为我的ADC是12位的,这个G和R分别表示的是电流检测的增益大小和分流电阻,这两个东西需要分别去你使用的电流检测芯片手册和PCB原理图中去查看才能得出结果。最后算出来的电流值就一定要记得经过一阶低通数字滤波滤波后再拿去使用,过滤噪声后的电机运动抖动更小,噪声也更小!

3.最后也是个最关键的点,就是,电机型号不同,空载时达不到目标电流值这很正常!有的电机可能0.2A,空载就达不到电流值了,而有的电机又是0.5A才跟不上目标值的。

就单单是这一句话,就困扰了我4到5天,我在这期间一直不断地在检查代码,不断地调整PID参数,结果现象还是,我给输入目标电流值为0.2A,电机空载的情况下永远达不到0.2A,最大只能到0.17,我输入100也是这样的情况。一直一直以为是哪里限幅输出了,甚至开始怀疑起电流被限流了,直到问了一个FOC大佬,我才知道原来我的板子和软件一点问题没有,空载达不到电流(就算这个电流不大)也是非常正常的!因为没给他提供阻力,空载电流是有个最大值的,只不过我这个电机空载电流的最大值比较小而已。

那么怎么判断出现这样的情况到底正不正常呢?你只需要堵转电机,看看这个时候电机输出的电流有没有接近目标值,比如我输入0.5,实际电流最大值还是0.17A,但是我堵转以后,电流直接飙升到0.5A了,这时候明显就能感觉到电机给我的力非常的大了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值