本帖最后由 radio2radio 于 2018-11-26 15:51 编辑
: b ~" ]5 Q! ^- h1 ^# I9 J% d
# e+ H" _/ q6 c+ w) X# X7 t虽然这个话题是程序员的基本功,但是,每一次实际使用时都要“重新编程+除错”折腾一番。
+ f% V" q+ x7 s6 p# a7 W于是,萌发了搞一个“通用的”,目的是,下次用到时,拿过来就用。, H' u$ {! I* a. e
大家看看我的方法是不是最佳的,欢迎提出改进方案。; i3 M5 c' c: v- U, w5 T' R& m
7 h* p. ^: J; K由MCU的ADC读到的“真实世界”的数据,0~1023对应10bit的ADC,0~4095对应12bit,0~65535对应16bit。通常,这些数据都要通过简单的数据处理,变换成电压/电流/温度/压力/等等意义明确的数值,用于传输或者显示。. ?9 ?4 m. x+ h6 }) _
9 b' d: r" W$ C9 I3 W% }$ ?) J6 l
线性插值,就是最最常用的数据处理方法。 直线函数公式:
; w8 A( x5 h/ v' k+ Z
% Y! V! ?- t1 ^% e8 N/ ~7 {' C" W* G' G! z, w
& m; v3 q5 y4 @" o% d7 h! a
应用实例,某电池的“电压—容量”测量估算结果,大致如下图所示:" L8 y. H6 ~' e, L" J
; q# _% h& r$ h# m* B6 }) M# b
9 q% V; G6 [& T! b
由曲线上面可以看出,虽然已经有了10组实测数据,但是只要取其中黄色的4组数据,也就是用3段直线进行线性插值,就可以得到很好的“近似结果”。
! o. b' U7 H. U/ ]1 N, q下图,就是用我的“通用线性插值程序”得到的计算结果,看图形,基本上一样的。& f& v. G$ t; h+ ]/ d. I& h
(注意,ADC数据所对应的电池电压值,只是测量ADC数据时用可调电源代替电池的外加电压,它们并不参与运算。 直接由ADC数据插值出电池的剩余电量。)
/ z0 C! F5 D1 K0 v# z' T; K
' Y8 l f! h9 s+ ]" {( K- a$ y
! _. Z# ` X2 V
6 K- f, L/ ~1 ^/ a2 D' U C2 }
( I, a* N) N# H. y正弦曲线测试实例,使用37个X轴等间隔的数据(每10度一个),线性插值出0-360度的范围一段正弦曲线的结果:8 o5 J- \+ `; ?( A5 D' d! j6 }+ N0 O
(为了提高转换精度,合理的做法是在曲线变化剧烈的部分,密集取点;线性好的部分,少量取点。而不是采用等间隔的方式取点。)
/ _# F" y& ` I; K+ j4 Q
/ n! ^3 Z) g: u6 m9 x
0 o6 c6 f* p% H" h( n
5 w0 y; G% R. T% G) z
0 w( z" R* _ p. b A最后,给出子程序:$ X+ {- X! |# q( Y2 f0 d; x
需要说明的是,笔者对有符号的整数(int)和浮点数(float)有“原始的抵触”,喜欢使用无符号整数类型(uint)。所以只做出了整数类型的。
( m/ N/ G! Y1 s# Z5 l: ^
% W, t' H" B: [ H# C- # r) w: N& J: o5 C0 D
- //General integer Linear Interpolation
1 z j. Q! ]. T& L - //
2 g, m N7 ^7 W - //setup: uint16_t Y[size] = {Y0, Y1, Y2, , , Ysize-1};4 t1 d& [0 i& n& @4 X3 g# G
- //setup: uint16_t X[size] = {X0, X1, X2, , , Xsize-1};
! e7 j1 d0 w9 G& `5 z- O - // - Two Arrays in integer format, Unsigned, no negative values.! k x; r/ ], d1 T$ y* P
- // - X[0]<X[1]<X[2]......<Xn, must increasing.
6 p; q3 ^; Y7 a: \* D - ' t* y, ^3 ?/ J
- //Test data-1, battery capacity:( c. G# ]0 W1 S9 a' ?4 {* O
- const uint16_t X[] = {31778, 33442, 39398, 40421};
' ]7 |! }& z- L$ {& K( D) W1 E( L - const uint16_t Y[] = {0, 29, 94, 100 };- ~$ o8 X) Q5 [
* C. I( [# H2 F5 S* _8 S( F0 B- //Test data-2, sine wave:% ?, [7 F# L5 v2 z
- //const uint16_t X[] = {0,10,20,30,40,50,60,70,80,90,! ?# n* d( e( I: a
- // 100,110,120,130,140,150,160,170,180,190,4 X( `; r! j: n$ F6 G* q
- // 200,210,220,230,240,250,260,270,280,290,. u: P8 a4 c2 L8 G* ?" j
- // 300,310,320,330,340,350,360};! Z/ O; b' T9 G1 B4 r) z8 l. h' n
- //const uint16_t Y[] = {2000,2174,2342,2500,2643,2766,2866,2940,2985,3000,
& T' b! l& r! N% q/ S q4 y - // 2985,2940,2866,2766,2643,2500,2342,2174,2000,1826,$ o# `% |" a5 x3 B0 O5 f" A
- // 1658,1500,1357,1234,1134,1060,1015,1000,1015,1060,# Z \- _" l. S- I% g% N. t
- // 1134,1234,1357,1500,1658,1826,2000};$ }# t& V, P! f0 [1 ?
- * a) R$ Z$ W; y/ ~) Z+ p
- [& B6 ~' m: ~3 @6 T; J+ o- uint16_t u16LinearInterpolation(uint16_t xdata)
8 f- A8 Z( b e |& n% L - {( f* Y# h: {4 `& _
- uint32_t u32Temp;1 c1 [" k2 U5 W" q7 C* G: }
- int i,size;8 a- V) f5 y# S9 I0 ~2 k
- " B6 @! ]6 |: y: D/ d0 w; X7 B( L
- size = sizeof(X)/2; //get the array numbers, uint16_t occupied 2 bytes.' p# ^, w2 o$ J: g: I
- % k* M% X3 G0 f2 N' c& e% Y
- if (xdata <= X[0]) return Y[0];' Y7 n; A' P1 X
- if (xdata >= X[size-1]) return Y[size-1];
& k% ~( |! S2 W* u* s5 v/ ^ -
! o! T& ]8 }, U! s. f - for (i=0; i<(size-1); i++)! p, y; ]+ }4 D6 R G
- {
( v0 h. F# u- m2 l1 P9 q/ F1 P - if ((xdata >= X[i]) && (xdata < X[i+1])) break;
# l& M( i- J' C! E" \ - }' W: s, n4 C$ i" C* b2 ?* u6 E
-
; Z) w# x2 ^/ T- e) [ - if ((xdata == X[i]) || (Y[i] == Y[i+1])) return Y[i];6 v1 }0 @8 x8 U4 s4 c
-
5 ]6 Y! H7 Z' S: O - //Y(x)=[Yi*(Xi+1-x)+Yi+1*(x-Xi)]/(Xi+1-Xi) R/ b- a6 }3 x0 \# `/ L7 d! f! m
- u32Temp = Y[i]*(X[i+1]-xdata);
$ T% ]7 d% [ v2 W) c2 F - u32Temp += Y[i+1]*(xdata-X[i]);
/ U8 T; P1 M! l2 k: o - u32Temp /= X[i+1]-X[i];
: D. d3 M: _* b- [+ C, i - 5 K" ^' D. K" H5 o2 R T2 {5 T/ a( Q8 _
- return (uint16_t) u32Temp;: C6 ^% N+ P/ v
- }( @# U; c( \& F2 _# z
复制代码 9 ~- ]3 f4 R$ {0 g7 ?9 \4 H2 v3 G
$ U7 k" t. h) Z4 K; ~* _+ s- G
* S1 h5 Y. L4 z T9 _
" d+ X; k& Q0 V' u) Y. M
9 I. z& p8 e, z9 w5 M |