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


定義

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

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

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

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

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

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

程序的實現

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

  • 采樣時間,需要根據采樣時間對系統進行離散;
  • 當前值,系統當前狀態被控量的值,即 x ( i ) x(i)
  • 目標值,系統最終期望到達的值,即 x ( i 0 ) x(i_0)
  • 延遲時間,系統到達目標值所需要的時間;
  • 步數,系統達到目標值的步數,通常為 i = t d e l a y T i = \cfrac{t_{delay}}{\bigtriangleup_{T}}
  • 斜率,斜率為 X t a r g e t X i n i t a l s t e p \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);
}

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

在這里插入圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM