你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

线性插值---通用的ADC数据处理子程序

[复制链接]
radio2radio 发布时间:2018-11-25 23:46
本帖最后由 radio2radio 于 2018-11-26 15:51 编辑 * i+ W# Q' v1 q: B+ m6 u

8 `* D7 C, L1 f/ P: S# ^  o2 H  O虽然这个话题是程序员的基本功,但是,每一次实际使用时都要“重新编程+除错”折腾一番。' A- R( H0 H5 V! K9 B1 _2 T  {; A7 G) C
于是,萌发了搞一个“通用的”,目的是,下次用到时,拿过来就用。6 Q7 X$ _9 E: n" E
大家看看我的方法是不是最佳的,欢迎提出改进方案。; N3 H1 J: q2 H6 ]1 j

, [7 C) L& N$ ]: ~, C由MCU的ADC读到的“真实世界”的数据,0~1023对应10bit的ADC,0~4095对应12bit,0~65535对应16bit。通常,这些数据都要通过简单的数据处理,变换成电压/电流/温度/压力/等等意义明确的数值,用于传输或者显示。4 s- t) ~% j2 P( Y( t* ]9 G( K
5 r  o; E( d  \/ u* P+ Z
线性插值,就是最最常用的数据处理方法。 直线函数公式:
% D; [. `+ m3 q; z* G+ n My Formula.jpg
7 [0 U, ~) R5 ]1 Q! y2 e" h$ q
* G1 r# n- y7 z6 Y8 r( J. c5 m- s( V: H* r
应用实例,某电池的“电压—容量”测量估算结果,大致如下图所示:  {9 z: U0 |0 l: ^0 l% I
BatteryCap vs Data.JPG $ {) |5 l& K3 v+ t* H5 w

+ R# q6 T: K, V, ^由曲线上面可以看出,虽然已经有了10组实测数据,但是只要取其中黄色的4组数据,也就是用3段直线进行线性插值,就可以得到很好的“近似结果”。
2 e0 b$ e/ p$ d% C/ u2 x/ K" ?下图,就是用我的“通用线性插值程序”得到的计算结果,看图形,基本上一样的。" H. F. r& C! p# r# L% ^
(注意,ADC数据所对应的电池电压值,只是测量ADC数据时用可调电源代替电池的外加电压,它们并不参与运算。 直接由ADC数据插值出电池的剩余电量。)
: |: y5 x2 s6 n, I  F, M8 L Test result-1.JPG
: w0 f9 f5 |9 j1 Q8 B9 h1 F5 l3 t
% @3 h4 s6 {2 K9 a( S

; l0 h; k7 }3 |) h4 h$ C8 S7 ?正弦曲线测试实例,使用37个X轴等间隔的数据(每10度一个),线性插值出0-360度的范围一段正弦曲线的结果:
. B6 ^5 d* `. t. d# @(为了提高转换精度,合理的做法是在曲线变化剧烈的部分,密集取点;线性好的部分,少量取点。而不是采用等间隔的方式取点。)
2 J7 h( t% N7 J! `" _ Test result-2.JPG
8 E9 g) d: `; f. X' P  h4 o+ g  a! E( c, R$ f, D
# k) y3 v; D$ z2 K
' l& E# J% T( Z% y
最后,给出子程序:
8 A, ]" \2 g' }6 N+ p( V需要说明的是,笔者对有符号的整数(int)和浮点数(float)有“原始的抵触”,喜欢使用无符号整数类型(uint)。所以只做出了整数类型的。- b0 i: V8 U- T" r, a# j8 w
9 Q4 K( D$ N( U

  1. 3 Y9 ?2 I6 F) Q, ^* R) k
  2. //General integer Linear Interpolation+ c0 `2 F' U* I7 ?
  3. //
    , x  i# V7 D: Z4 ~( u4 l# x* E1 z
  4. //setup: uint16_t Y[size] = {Y0, Y1, Y2, , , Ysize-1};8 o% g4 E9 d% P( S; `
  5. //setup: uint16_t X[size] = {X0, X1, X2, , , Xsize-1};
    1 C# H7 ]! z/ l" k- W( `1 o2 H1 X" e
  6. // - Two Arrays in integer format, Unsigned, no negative values.2 B) `. J$ b& Z6 R
  7. // - X[0]<X[1]<X[2]......<Xn, must increasing.
    0 m% Y' L- p) Q. q' ]: `
  8. 7 Y# ~2 o; F# m% ]$ q6 K+ w
  9. //Test data-1, battery capacity:
    , m5 p; p8 X2 u: s+ y  l
  10. const uint16_t X[] = {31778, 33442, 39398, 40421};- q  P& v# _% K: O
  11. const uint16_t Y[] = {0,     29,    94,    100  };* S, t5 x: p8 p$ N

  12. ! Q! a- t2 f7 R9 l( s
  13. //Test data-2, sine wave:
    6 w; c. D3 ?8 f# I
  14. //const uint16_t X[] = {0,10,20,30,40,50,60,70,80,90,+ }! H0 \" @% x% S* @9 y6 h  c
  15. //                      100,110,120,130,140,150,160,170,180,190,. w: Z6 ?# _. c- u5 i4 f9 S8 m
  16. //                      200,210,220,230,240,250,260,270,280,290,( A' A, k' N) E% ]$ D: F1 U
  17. //                      300,310,320,330,340,350,360};) d, [1 S* `; R; Q5 u3 r6 }0 l- s+ r
  18. //const uint16_t Y[] = {2000,2174,2342,2500,2643,2766,2866,2940,2985,3000,
    8 W7 x9 _* Y5 P7 u7 h2 x# u
  19. //                      2985,2940,2866,2766,2643,2500,2342,2174,2000,1826,% n$ f  e# j. i' J" a) l4 N  u
  20. //                      1658,1500,1357,1234,1134,1060,1015,1000,1015,1060,  i0 C. K+ g) q. l' a
  21. //                      1134,1234,1357,1500,1658,1826,2000};
    3 z2 e% ]7 {% H. [8 f

  22. 5 |5 {/ m) W" @2 S

  23. ( D9 l7 H* Y' R' d( B% A
  24. uint16_t u16LinearInterpolation(uint16_t xdata)
    5 o) S, U1 k7 v: _3 L
  25. {7 Z6 B! A; }$ C& I7 X9 ^: ^
  26.   uint32_t u32Temp;, d- v0 Z8 B. `5 I. `- a0 l0 n
  27.   int i,size;! J  \6 h7 V9 I5 L( M
  28.   
    1 q2 }- }9 O+ A2 H0 o# _
  29.   size = sizeof(X)/2; //get the array numbers, uint16_t occupied 2 bytes.) V7 y  V. V% ]1 w! ?0 M* r* b
  30.   + g: j! v" U; T  e
  31.   if (xdata <= X[0]) return Y[0];
    7 r2 m  J' F/ |/ V
  32.   if (xdata >= X[size-1]) return Y[size-1];
    + H1 S. g% L! R: ~" _; L2 n
  33.   
    + f/ r. A+ {1 o/ ~5 }
  34.   for (i=0; i<(size-1); i++)
    % ]  n# d& {5 o2 Y: a- u) o2 n7 x" h
  35.   {7 y3 b9 k0 ?! D) [
  36.     if ((xdata >= X[i]) && (xdata < X[i+1])) break;    , \4 L4 T2 s, {5 Q( e5 w6 w
  37.   }* ]+ r# A" \# s6 G
  38.   # j6 T8 @  q1 u/ N6 q6 g2 |( A
  39.   if ((xdata == X[i]) || (Y[i] == Y[i+1])) return Y[i];" y2 c% H" z( b! c! I. P
  40.   
    ) b* Z2 H8 Y) Q# ^$ w4 [6 M1 H
  41.   //Y(x)=[Yi*(Xi+1-x)+Yi+1*(x-Xi)]/(Xi+1-Xi)
    9 Y+ ]) O* E  V" W0 F
  42.   u32Temp = Y[i]*(X[i+1]-xdata);
    1 x7 J+ M7 v$ X* z( l& h
  43.   u32Temp += Y[i+1]*(xdata-X[i]);
    & A) ?" d7 p( T
  44.   u32Temp /= X[i+1]-X[i];
    8 }! `4 K+ D. [) s: c; ~+ [6 i- T
  45. . s. U; w/ _! E3 Q' d7 b; T0 N
  46.   return (uint16_t) u32Temp;
    5 d. Y9 b7 D  L4 W
  47. }
    : \! `8 s# n$ X: K. w# @9 y
复制代码

, r. s1 ~5 F4 E) D4 c* v
6 T: `# |* [$ f, I) t; m! ?: W
6 B2 _, G2 {' ^5 }" \
5 {) h& R& y! t7 q- k9 d& l' u9 o& W
收藏 2 评论3 发布时间:2018-11-25 23:46

举报

3个回答
STM1024 回答时间:2018-11-26 10:11:41
尽量避免使用有符号整数和浮点数是比较明智的做法~~甚至不要去假定int就是32位的
zjczm 回答时间:2018-11-26 10:36:30
很不错。
legenderw 回答时间:2019-1-31 14:11:23
不错!收了

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版