一文教你快速搞懂 FOC ramp function 斜坡函數的作用和實現

定義

x(t)={0t<0At,t0 x(t) = \begin{cases} 0,t<0\\ At,t \ge 0\\ \end{cases}

其中A爲增益,相當於給定一個速度,在時間 [0,t][0, t ]期間內,按照A作爲加速度,勻加速或者勻減速到速度給定值 vrefv_{ref}

在這裏插入圖片描述
如上圖所示,這種函數就相當於控制系統中均速變換的位置信號,在三環控制的位置中,相當於這樣一個過程;

  • 設定最終的位置量爲x(t0)x(t_0)
  • 系統按照A的速度進行均勻的位置變換,A=dxdtA = \cfrac{dx}{dt}
  • 最終到達 t0t_0 時刻,系統到達設定的位置x(t0)x(t_{0})

同樣的,也適用於速度環,對於不同的被控對象,增益AA的物理意義也不同,但是斜坡函數的最終目的就是讓輸入信號變得更加平緩,減少系統超調,從而優化系統的時間響應。

進行離散化
將方程進行離散化,按照 T\bigtriangleup_{T}的時間採樣,那麼可以將輸入離散化:
x(i)={0i<0Ai,i0 x(i) = \begin{cases} 0,i<0\\ Ai,i \ge 0\\ \end{cases}
在這裏插入圖片描述

程序的實現

首先這裏簡單講一下斜坡函數實現的思路:

  • 採樣時間,需要根據採樣時間對系統進行離散;
  • 當前值,系統當前狀態被控量的值,即 x(i)x(i)
  • 目標值,系統最終期望到達的值,即x(i0)x(i_0)
  • 延遲時間,系統到達目標值所需要的時間;
  • 步數,系統達到目標值的步數,通常爲 i=tdelayTi = \cfrac{t_{delay}}{\bigtriangleup_{T}}
  • 斜率,斜率爲 XtargetXinitalstep\cfrac{X_{target} - X_{inital}}{step},也就是每一步需要增加的值,最終一步一步增加到目標值;

通常在實際控制系統中,在定時器中斷或者事件函數中,需要根據系統當前值目標值,和延遲時間進行一次計算,得到斜坡函數需要執行的步數和斜坡函數的斜率

下面用matlab先用模擬一下斜坡函數的生成,另外實際測試了一下C語言在實際硬件上的運行情況。

matlab 程序

以下程序模擬了採樣時間爲1,並且在delay時間(delay爲sample_time的整數倍)之後最終到達target,具體程序如下所示;

function ramp_func()
%採樣時間爲1
sample_time = 1;
current = 0;
%到達目標值期望的時間
delay = 10;

%需要步數
step = delay/sample_time;
fprintf('step:%d\n',step);
%目標值
target = 20;

%斜率 增益A
inc_dec = (target - current)/step;
output = 1:1:step;
i=1;

while i <= step
    output(i) = current + inc_dec;
    current = output(i);
    fprintf('output(%d):%d\n',i,output(i));
    i = i+1;
end
plot(output);
end

最終的運行結果如下;

在這裏插入圖片描述
在這裏插入圖片描述

C語言程序

下面是一個速度的斜坡函數,相關參數封裝到speed_ramp_mod中,具體如下所示;

struct speed_ramp_mod{
	int16_t target_val;		//目標參考值
	int16_t present_ref;	//當前參考值
	int16_t step_val;		//當前參考值到目標參考值所需要的步數
	int16_t inc_val;		//步長/斜率
	int16_t freq_hz;		//速度環頻率
};
typedef struct speed_ramp_mod speed_ramp_mod_t;
speed_ramp_mod_t user_ramp = {
	.target_val = 0,			//目標參考值
	.present_ref = 0,			//當前參考值
	.step_val = 0,				//當前參考值到目標參考值所需要的步數
	.inc_val = 0,				//步長
	.freq_hz = RAMP_SPEED_FREQ	//速度採樣頻率
};

int16_t speed_ramp_calc(speed_ramp_mod_t *p){
		
	int32_t ref;
	ref = p->present_ref;
	
	if(p->step_val > 1){
		ref += p->inc_val;
		p->step_val--;
	}else if(p->step_val == 1){
		ref = p->target_val;
		p->step_val = 0;
	}else{
		/**
			Do Nothing
		*/
	}
	p->present_ref = ref;
	return ref;
}

uint8_t speed_ramp_exec(speed_ramp_mod_t *p,int16_t target_val,int16_t durationms){
	
	int32_t inc = 0;
	int16_t ref = 0;
	ref = p->present_ref;
	if(durationms == 0){
		p->step_val = 0;
		p->inc_val = 0;
		p->present_ref = target_val;
	}else{
		p->target_val = target_val;
		//計算步長度
		p->step_val = (int32_t)durationms*p->freq_hz / 1000;
		p->inc_val = (p->target_val - ref)/p->step_val;
	}
}

uint8_t speed_ramp_completed(speed_ramp_mod_t *p){
	uint8_t retval = 0;
	if(p->step_val == 0){
		retval = 1;
	}
	return retval;
}

void speed_ramp_stop(speed_ramp_mod_t *p){
	p->step_val = 0;	
	p->inc_val = 0;
}

下面是測試程序,可以將程序放到定時器中進行週期性執行;

int16_t spd_ref = 0;
int16_t speed_ramp_ref = 0;
int16_t rpm_speed_set = 0;

void test(void){
	if(speed_ramp_completed(&user_ramp)){
		speed_ramp_exec(&user_ramp,rpm_speed_set,USER_RAMP_DELAY);
	}
	speed_ramp_ref = speed_ramp_calc(&user_ramp);
	printf("%d\r\n", speed_ramp_ref);
}

最終給定的速度曲線和實際的速度採樣曲線如下圖所示;

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章