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

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

[复制链接]
radio2radio 发布时间:2018-11-25 23:46
本帖最后由 radio2radio 于 2018-11-26 15:51 编辑   O8 D9 g% }( S9 y

& d  t0 _: t6 _( h% ^虽然这个话题是程序员的基本功,但是,每一次实际使用时都要“重新编程+除错”折腾一番。
- e7 Z! A; ^- D8 D于是,萌发了搞一个“通用的”,目的是,下次用到时,拿过来就用。% {! O4 A) g& x: ~
大家看看我的方法是不是最佳的,欢迎提出改进方案。
3 `9 [; ]& l2 G1 M2 s8 [' [5 N& Q
由MCU的ADC读到的“真实世界”的数据,0~1023对应10bit的ADC,0~4095对应12bit,0~65535对应16bit。通常,这些数据都要通过简单的数据处理,变换成电压/电流/温度/压力/等等意义明确的数值,用于传输或者显示。" w6 p5 k" N2 W) Z- K* e1 D/ \
+ {6 g, G  M' W6 l7 l
线性插值,就是最最常用的数据处理方法。 直线函数公式:" f& p/ w  J# A! R8 U# q1 ]
My Formula.jpg
! Y8 d& t! ~- e1 ^5 J
7 s- a7 T8 Q2 W& ~) ^! s9 Q) K3 m2 `; Z6 a+ L! B* A$ ?
应用实例,某电池的“电压—容量”测量估算结果,大致如下图所示:" c$ I5 Y0 E! b5 b9 {
BatteryCap vs Data.JPG $ Z, v/ Y+ I) A* h) Y3 [6 t

1 b* n# I4 Q% G- U由曲线上面可以看出,虽然已经有了10组实测数据,但是只要取其中黄色的4组数据,也就是用3段直线进行线性插值,就可以得到很好的“近似结果”。7 k  E% ^, E. L" Y6 l
下图,就是用我的“通用线性插值程序”得到的计算结果,看图形,基本上一样的。
. o) V' K' l- C" l4 S+ s2 b(注意,ADC数据所对应的电池电压值,只是测量ADC数据时用可调电源代替电池的外加电压,它们并不参与运算。 直接由ADC数据插值出电池的剩余电量。)
! N+ j  m1 W$ R7 @% X0 H- d; b0 `" Q" [ Test result-1.JPG
( \3 i& ]4 S% W
5 n) Q# ]. H# l6 p) N2 N
9 X- n4 a, o9 y: o- t- X. I; e: e% n' u1 I1 P( P' ?
正弦曲线测试实例,使用37个X轴等间隔的数据(每10度一个),线性插值出0-360度的范围一段正弦曲线的结果:$ Y! q0 y7 Z- S/ V
(为了提高转换精度,合理的做法是在曲线变化剧烈的部分,密集取点;线性好的部分,少量取点。而不是采用等间隔的方式取点。). r; a* \  Z7 U- p: _# o/ J9 Q7 e0 c' X
Test result-2.JPG % W7 u. l4 Y& v# \

: @; [7 B) y4 J" q
+ d, w# d+ l# _  D0 R+ H! x6 c; u  c% J  F* ^6 ^8 m
最后,给出子程序:* [/ d& J# Z6 u" o( ]
需要说明的是,笔者对有符号的整数(int)和浮点数(float)有“原始的抵触”,喜欢使用无符号整数类型(uint)。所以只做出了整数类型的。
& V; B. {- S1 O7 n1 i5 H9 b  d' V% t; f9 [' i2 k

  1. 6 q( {% h" i. a( ~7 }
  2. //General integer Linear Interpolation% A/ Z, X% _. T) ~' g5 V
  3. //; {- Y, `0 s) S3 |
  4. //setup: uint16_t Y[size] = {Y0, Y1, Y2, , , Ysize-1};! @5 C) h# c% }( {9 g0 Y7 z
  5. //setup: uint16_t X[size] = {X0, X1, X2, , , Xsize-1};
    9 B( K* c# _+ L
  6. // - Two Arrays in integer format, Unsigned, no negative values.
    8 {1 K* B" }( ?9 |9 O5 v) G
  7. // - X[0]<X[1]<X[2]......<Xn, must increasing.& h  v7 l2 ]- f' n. W+ F" ]$ c9 o

  8. / z: {  ?3 X7 T' f" C) g3 l
  9. //Test data-1, battery capacity:$ q5 }( n8 c' y2 M: b7 g! Q
  10. const uint16_t X[] = {31778, 33442, 39398, 40421};
    3 c( u- \( c1 C0 w$ H7 w- Y
  11. const uint16_t Y[] = {0,     29,    94,    100  };' w8 r' E# p) I) V+ N

  12. ! ^: B' K- ?0 A' N6 O$ d" w
  13. //Test data-2, sine wave:
    % r4 l+ [7 n$ ~& D
  14. //const uint16_t X[] = {0,10,20,30,40,50,60,70,80,90,
    6 V) b& A) i# j4 d* Q
  15. //                      100,110,120,130,140,150,160,170,180,190,2 Z8 ]& S$ U; s8 Y/ j
  16. //                      200,210,220,230,240,250,260,270,280,290,1 T" T) E- d' n* M8 L: f
  17. //                      300,310,320,330,340,350,360};! O; m+ D2 J  Z. K
  18. //const uint16_t Y[] = {2000,2174,2342,2500,2643,2766,2866,2940,2985,3000,# y/ {6 V+ p5 s
  19. //                      2985,2940,2866,2766,2643,2500,2342,2174,2000,1826,) P2 Y, t; t1 ~1 R+ `! ]( z
  20. //                      1658,1500,1357,1234,1134,1060,1015,1000,1015,1060,
    # U6 i) x! U' V' B
  21. //                      1134,1234,1357,1500,1658,1826,2000};3 @5 L' {: M$ W& w  \

  22. % q* V. a/ S7 Y% {8 Y- }
  23. 5 O! q4 O' V1 x. Q& N% S$ c( @
  24. uint16_t u16LinearInterpolation(uint16_t xdata): A& p& @$ \/ F' s8 r, J
  25. {
    7 a# z6 O) L9 [; c/ S' n/ N
  26.   uint32_t u32Temp;
    # @& c2 X( a! C0 g
  27.   int i,size;
    4 h( ?8 [- B+ X$ t+ p2 m3 G
  28.   0 z" I2 D/ z# R( s
  29.   size = sizeof(X)/2; //get the array numbers, uint16_t occupied 2 bytes.3 M( I9 R% y" \
  30.   / t& h- V" _. s% C( o
  31.   if (xdata <= X[0]) return Y[0];
    1 N4 ]8 N; f; r( i: c
  32.   if (xdata >= X[size-1]) return Y[size-1];
    7 {, ~& \+ N  s0 R) |
  33.   
    1 [  c  D4 }  X4 ~
  34.   for (i=0; i<(size-1); i++)
    " o* u1 P& b  O1 m; o
  35.   {* `9 U( r8 |3 s) h. p! L( w
  36.     if ((xdata >= X[i]) && (xdata < X[i+1])) break;   
    - P& O% e* b* z) ]+ }! T
  37.   }
    ; t6 S8 w# j3 T9 A% E  G$ D* |9 O
  38.   : t% `( c1 y2 A6 p' l2 m
  39.   if ((xdata == X[i]) || (Y[i] == Y[i+1])) return Y[i];
    , T7 l5 S; a/ p: s5 \/ `
  40.   $ X$ V5 O& {# f2 F
  41.   //Y(x)=[Yi*(Xi+1-x)+Yi+1*(x-Xi)]/(Xi+1-Xi)
    : u9 A4 _* w0 O; W) E1 _
  42.   u32Temp = Y[i]*(X[i+1]-xdata);
    1 X' p( ^+ Q# k, f* Y3 G
  43.   u32Temp += Y[i+1]*(xdata-X[i]);5 S# w3 v" H  Q& p% ]
  44.   u32Temp /= X[i+1]-X[i];$ J  y0 N: i; a( t) N/ b
  45. & h5 M  b: [" v! j0 L: A: b
  46.   return (uint16_t) u32Temp;
    " R& k. ]; i2 d' R7 w7 B
  47. }
    ; l; M% \. G% n7 o0 n
复制代码
2 a6 }; k# w0 r( y& R0 G3 {
1 K' a# }( Z8 S: f" M, C% G

* F" h% f; I4 X8 q% l
# c, O/ d* e" k5 V- s, C0 E- H! j) F, N1 k
收藏 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 手机版