之前發的一篇文章有討論到如何做資料平滑化處理,用的就是最小二乘擬合法,不過每次擬合處理的資料是9筆

 

最小二乘擬合法有個問題,就是每次擬合計算的資料筆數越少,擬合出來的資料和原資料偏差越大。而每次擬合計算的資料筆數越多則偏差越小,但計算效率越差。如何拿捏設定每次擬合計算的資料筆數,是個重要的問題

 

相關的計算在LabVIEW內找不到可使用的VI(若有人知道是哪一個請告知),為此要把找到的計算公式寫成SubVI,方便應用在其他程式。而SubVI程式的基本要求是可選擇每次要擬合計算的資料筆數

 

 

首先是擬合計算要用到的Savitgky-Golay係數,雖然有公式可以計算,但不是這篇文章要探討的部份,所以直接取用已計算好的資料(如下圖)

20090131-11  

 

 

整個擬合公式改寫如下:


(Y(i)*R(0)+(Y(i+1)+Y(i-1))*R(1)+...+(Y(i+n)+Y(i-n))*R(n))/(R(0)+(R(1)*2)+...+(R(n)*2))


Y是來源資料,R是Savitgky-Golay係數,n是擬合的點數除2去尾取整數


公式要這樣改寫是方便LabVIEW程式書寫

 

 

SubVI程式的面板配置如下:

20090131-05  

 

2個輸入端:1個是要擬合的資料輸入陣列,另1個是Menu Ring元件作成的擬合點數選單


1個輸出端:使用Waveform Graph元件顯示擬合處理後的資料圖形

 

 

再來是程式書寫部份:


首先是要把Savitgky-Golay係數的資料作成2D陣列(如下圖):

20090131-06  

 

接著是把擬合點數(5,9,11,...,23,25)數值做成1D陣列(如下圖):

20090131-07  

 

 

寫好的程式如下:

20090131-08  

 

 

程式分為兩個部份:左半邊是把要擬合計算所用到的數值先計算好,右半邊則是實際擬合計算的部份

 

 

左半邊程式部份:

20090131-09  

 

1.先用Menu Ring元件輸出的數值從擬合點數列表的1D陣列中取出擬合點數的數值,同樣以Menu Ring元件輸出的數值從Savitgky-Golay係數的2D陣列中取出對應的1D數值陣列

 

2.把數值來源的資料輸入陣列用Array Size元件求得所有資料數量,再減去擬合點數的數值,若小於0則右半邊程式切換到錯誤訊息程式,並顯示資料不足無法處理的對話方塊。若大於0則右半邊程式執行資料擬合計算

 

3.再來是計算公式的分母數值(R(0)+(R(1)*2)+...+(R(n)*2))部份,先將擬合點數的數值除2去尾取整數求得公式中的n值,作為For Loop迴圈的執行次數數值。For Loop迴圈內把Savitgky-Golay係數中1~n的數值分別乘2,再全部相加在加上Savitgky-Golay係數0的數值,求得分母的數值

 

 

右半邊程式部份:

20090131-10  

 

1.最外圍用Case Structure元件來判定資料輸入數量是否正確,錯誤則切換到錯誤訊息程式,並顯示資料不足無法處理的對話方塊。正確則執行資料擬合計算

 

2.資料擬合計算使用窗口移位法,每次只從資料輸入陣列中取出擬合點數的數值同樣多的資料進行計算

 

3.使用2個For Loop迴圈,外迴圈執行次數設定為資料輸入陣列減去擬合點數的數值,也就是全部資料的有效計算範圍。內迴圈執行次數設定為n值,也就是擬合計算有重複的部份

 

4.內外迴圈分別把來源資料乘上對應的Savitgky-Golay係數,再把乘好的數值全部相加除以左半邊程式算出的分母數值。擬合計算後的資料會減少擬合點數數值減1的數量

 

 

以下為寫好的SubVI程式執行結果:


來源資料

20090131-01  

 

5點擬合計算

20090131-02  

 

9點擬合計算

20090131-03  

 

25點擬合計算

20090131-04  

 

可以看出擬合的點數越多,數值平滑效果越好,減少的資料越多。要兼顧程式執行的平滑結果和效率,擬合的點數建議設定在9~13之間

arrow
arrow

    未出師的小工程師 發表在 痞客邦 留言(0) 人氣()