[英]Measure variation of data points from a line; To Catch a Dip
(更新:我發布了解決方案和代碼作為答案,而不是再次編輯問題)
理想線(紅色虛線)是從起點開始的圖,每個測量角度均加上平均上升; 我通過平均獲得。 我用黑色測量了測試數據。 如何量化藍色浸入區域? X軸是統一的,因此簡化了斜率和數學運算。
我可以確定像這樣的區域大小的臨界值,然后將其標記為重新測試或失敗。 很少會出現一個更靠近右側的傾斜,但是設置標准偏差的臨界值通常會使這些零件失效。
迭戈的答案幫助我形象地看到了這一點。 現在,我可以看到要執行的操作,接下來將研究實現“自制傾斜檢測器”的算法。 :)
我創建了一個測試台來測試我要銷售的節氣門位置傳感器。 我正在嘗試通過分析收集的數據以編程方式量化繪圖的直線度。 這個特殊的模型讓我很煩惱。
我不想出售的零件的樣圖:
X軸是節氣門開度的均勻間隔角。 步進電機轉動輸入軸,每0.75°停止一次,以測量10位ADC上的輸出,該輸出轉換為Y軸。 該圖是data[idx]
到idx,value
映射到(x,y)
位圖坐標。 然后,我使用Bresenham算法在位圖中的點之間繪制線。
我的其他TPS產品產生令人驚訝的線性輸出 。
該圖的下部(左側)對於任何汽車的正常使用都是至關重要的。 這是當您在城鎮周圍開車,進入停車場等時。該特定部分趨向於在15°的開度附近出現傾角,我希望使用該程序來量化曲線中的“傾角”,而不再依賴於測試人員的直覺。 在上面的示例中,地勢有所下降,但並未恢復到理想的水平。
即使這是一個嵌入式應用程序,打印報告也需要10秒鍾,因此我不認為多次遍歷120個點的數據數組會浪費周期。 另外,由於我使用的是uC32 PIC32微控制器 ,因此有足夠的內存,因此我能夠在控制器內考慮此問題,這是我的榮幸 。
測試點之間的上升陣列:考慮到X軸是統一的,我將X軸完全消除,然后從一個讀數到下一個讀數進行一系列變化。 此數組有助於報表的“點之間的最小上升:0最大:14”。 我稱這個數組為deltas 。
我嘗試對增量使用標准偏差 ,但是,在測試期間,我發現對於這部分,低標准偏差不是可靠的度量。 如果跌落很快返回到早期數據點所暗示的原始線,則Std Dev可以說是低的(觀察到低至2.3),但是該部分仍然是我不想使用的東西。 我嘗試將臨界值設置為2.6,但由於積壓大,它使太多零件失效。 上面鏈接的另一個更線性的部分可以可靠地依靠Std Dev來保證質量。
峰態似乎根本不適合這種情況。 我今天了解了峰度 ,並找到了一個包含峰度和偏度的統計資料庫 。 在繼續測試期間,我發現在這兩個度量中,沒有與通過或失敗相對應的正,負或振幅趨勢。 這位先生共享一個線性回歸庫,但是我相信Lin Reg與我的情況無關,因為我很滿意地認為增量 AVG是我的理想選擇。 線性回歸和R ^ 2更適合從不太理想的數據或更大的數據集中找到一條線。
每個三角洲AVG和標准偏差比較我設置了一個監控器所要檢查的增量的數據的最終平均每個增量。 在這里,我也找不到可靠的指標。 太多合格零件將無法通過將任何差值限制在偏離平均值2倍標准偏差之內的測試。 最終,我可以確定的與AVG唯一的區別是與AVG本身的差異在AVG+Std Dev
之內。 任何更嚴格的限制都會使本來不錯的部分失敗。 大約15°的開度難以捉摸,可以通過此測試。
自制的傾角檢測器當將增量提供給計算機的串行監視器時,我在傾角期間觀察到連續的負增量 ,因此我在傾角檢測器中進行了編程,但對我來說卻非常粗糙。 如果連續存在5個或更多的負增量 ,則將它們相加。 我已經看到,如果我將這個總和與AVG的驟降之差相除,然后除以負增量的數量,則大於2.9或3的值可能表示失敗。 我觀察到跌幅持續6至15個三角洲。 容易觀察到的下探值與AVG的總和之間的差值最多為-35。
AVG累積變化趨勢的趨勢上面的內容使我認為,觀察偏離AVG的增量總和可能是答案。 意思是,我遍歷數組並求和AVG中每個增量的差。 我以為我一直在研究某件事,直到很大一部分使這個理論破滅。 我看到一種趨勢,即運行總和與AVG
小於AVG
的2x AVG
倍,則直線顯示得越直。 許多理想零件只會顯示8個或更少的增量點,而sumOfDiffs
將偏離AVG很遠。
float sumOfDiffs=0.0;
for( int idx=0; idx<stop; idx++ ){
float spread = deltas[idx] - line->AdcAvgRise;
sumOfDiffs = sumOfDiffs + spread;
...
testVal = 2*line->AdcAvgRise;
if( sumOfDiffs > testVal || sumOfDiffs < -testVal ){
flag = 'S';
}
...
}
然后,通過58個數據點sumOfDiffs
了具有奇妙線性圖的零件,其中sumOfDiffs
是AVG的兩倍以上! 我發現這很棒,因為在sumOfDiffs
個數據點的末尾, sumOfDiffs
值為-0.000057。
在測試期間,最終的sumOfDiffs
結果通常會記錄為0.000000,並且只有在異常情況下,該結果才大於.000100。 實際上,我發現這很令人驚訝:“不良零件”如何積累出很高的准確性。
監視sumOfDiffs的樣本輸出此下面的輸出顯示發生了下降。 該測試sumOfDiffs
,在整個測試過程中,運行的sumOfDiffs
距離AVG的距離是AVG的2 sumOfDiffs
以上。 此傾角持續從增量 idx
的23至49; 從17.25°開始,持續19.5°。
Avg rise: 6.75 Std dev: 2.577
idx: delta diff from avg sumOfDiffs Flag
23: 5 -1.75 -14.05 S
24: 6 -0.75 -14.80 S
25: 7 0.25 -14.55 S
26: 5 -1.75 -16.30 S
27: 3 -3.75 -20.06 S
28: 3 -3.75 -23.81 S
29: 7 0.25 -23.56 S
30: 4 -2.75 -26.31 S
31: 2 -4.75 -31.06 S
32: 8 1.25 -29.82 S
33: 6 -0.75 -30.57 S
34: 9 2.25 -28.32 S
35: 8 1.25 -27.07 S
36: 5 -1.75 -28.82 S
37: 15 8.25 -20.58 S
38: 7 0.25 -20.33 S
39: 5 -1.75 -22.08 S
40: 9 2.25 -19.83 S
41: 10 3.25 -16.58 S
42: 9 2.25 -14.34 S
43: 3 -3.75 -18.09 S
44: 6 -0.75 -18.84 S
45: 11 4.25 -14.59 S
47: 3 -3.75 -16.10 S
48: 8 1.25 -14.85 S
49: 8 1.25 -13.60 S
Final Sum of diffs: 0.000030
RunningStats analysis:
NumDataValues= 125
Mean= 6.752
StandardDeviation= 2.577
Skewness= 0.251
Kurtosis= -0.277
關於質量的清晰提示:我踏上這一旅程的第一步是學習主要的汽車OEM供應商如何將4點測試作為這些零件的標准度量。 我的第一個測試台使用的是Arduino,內存為8k,沒有TFT顯示屏,也沒有打印機,機械分辨率僅為3°! 那時,我只是簡單地測試了增量在任意總范圍內,並選擇了單個增量可能有多大的限制。 與之前的30點測試相比,我的120分以上的測試感覺上乘,但是該測試對這些下降並不了解。
Y_dev = Y_data - Y_straight
在數學上相同的Y_dev = Y_data - Y_straight
):
PositiveMax = 0; NegativeMax = 0;
tmp_Area
tmp_Area = Y_dev;
復位累加器tmp_Area = Y_dev;
到以這種方式開始的當前值的新積累 Y_dev
值小於閾值,則不會累加該值。 事實證明,這是我的直覺的結果,而Diego的方法是積分的平均值。 我仍然不喜歡該名稱,因此我已經描述了算法,並在Math.SE上詢問了該名稱的含義,該名稱已遷移到“交叉驗證”(Stats.SE) 。
在對Math.SE問題進行大量編輯之后,我更新了圖表。 事實證明,我正在獲取數據導數的閉合積分的平均值。 :P首先,我們收集數據:
接下來是“導數”:逐步遍歷原始數據數組以形成增量數組,這是ADC值從一個0.75°步進到下一個步進的增量 。 “上升”或“斜率”是派生詞:dy / dx。
在“斜率”或平均水平趨於平穩的情況下,我可以連續找到多個負增量 ,將其相加,然后在下降結束時除以計數。 總和是平均值和增量之間面積的整數,當下降幅度返回正值時,我可以將總和除以下降幅度的計數。
在測試過程中,我得出了該平均值的平均值的截止值2.6。 這是衡量我的“直覺”來衡量部分認為好壞的好方法。
萬一有人發現自己試圖對此進行量化,這是我實現的代碼。 請注意,它只是在尋找負跌幅。 另外,在其他地方將dipCountLimit定義為5。除了傾角檢測器/累加器(即,數值積分器)之外,我還具有一個尖峰檢測器,如果有任何數據點偏離平均值+平均值+標准,則可以任意將測試標記為不良。偏差。 根據觀察到的可能會損壞的零件圖,任意選擇AVG + STD DEV作為峰值限制。
int dipdx=0;
// inDipFlag also counts the length of this dip
int inDipFlag=0;
float dips[140] = { 0.0 };
for( int idx=0; idx<stop; idx++ ){
const float diffFromAvg = deltas[idx] - line->AdcAvgRise;
// state machine to monitor dips
const int _stop = stop-1;
if( diffFromAvg < 0 && idx < _stop ) {
// check NEXT data point for negative diff & set dipFlag to put state in dip
const float nextDiff = deltas[idx+1] - line->AdcAvgRise;
if( nextDiff < 0 && inDipFlag == 0 )
inDipFlag = 1;
// already IN a dip, and next diff is negative
if( nextDiff < 0 && inDipFlag > 0 ) {
inDipFlag++;
}
// accumulate this dip
dips[dipdx]+= diffFromAvg;
// next data point ends this dip and we advance dipdx to next dip
if( inDipFlag > 0 && nextDiff > 0 ) {
if( inDipFlag < dipCountLimit ){
// reset the accumulator, do not advance dipdx to next entry
dips[dipdx]=0.0;
} else {
// change this entry's value from dip sum to its ratio
dips[dipdx] = -dips[dipdx]/inDipFlag;
// advance dipdx to next entry
dipdx++;
}
// Next diff isn't negative, so the dip is done
inDipFlag = 0;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.