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

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

[复制链接]
radio2radio 发布时间:2018-11-25 23:46
本帖最后由 radio2radio 于 2018-11-26 15:51 编辑
! x5 Z5 X8 O- Q0 C5 Y' F5 Z- I& W& ?: X5 \& o0 @
虽然这个话题是程序员的基本功,但是,每一次实际使用时都要“重新编程+除错”折腾一番。- F' o$ Y$ H2 }. ]6 E
于是,萌发了搞一个“通用的”,目的是,下次用到时,拿过来就用。# i) k& p) o; `' V3 b
大家看看我的方法是不是最佳的,欢迎提出改进方案。
* ^: [3 D; y2 D9 w; ~8 I0 m
6 w7 `, B; ?1 o" y" f- s由MCU的ADC读到的“真实世界”的数据,0~1023对应10bit的ADC,0~4095对应12bit,0~65535对应16bit。通常,这些数据都要通过简单的数据处理,变换成电压/电流/温度/压力/等等意义明确的数值,用于传输或者显示。* E' f  A  E- S8 F- p  ~2 ~% H9 c

  x) g- C1 a+ }9 K7 C线性插值,就是最最常用的数据处理方法。 直线函数公式:
% X4 L1 _  K% [+ `) L2 J8 d* f/ \ My Formula.jpg
( w; ?) P* B9 z( [3 ?3 r5 f: ~/ o) \$ w5 N* H) J4 r1 {

1 O0 }+ [# i3 O应用实例,某电池的“电压—容量”测量估算结果,大致如下图所示:
! N* v6 b0 ]2 g  V, f5 \) @! Y) Y BatteryCap vs Data.JPG
( ?* c5 g, u) L" D
0 _3 u$ z0 c4 M, S6 z- K& }0 u由曲线上面可以看出,虽然已经有了10组实测数据,但是只要取其中黄色的4组数据,也就是用3段直线进行线性插值,就可以得到很好的“近似结果”。1 X$ \$ s' l' z+ L5 j
下图,就是用我的“通用线性插值程序”得到的计算结果,看图形,基本上一样的。* i0 w+ {5 N( R' B6 d  l, j
(注意,ADC数据所对应的电池电压值,只是测量ADC数据时用可调电源代替电池的外加电压,它们并不参与运算。 直接由ADC数据插值出电池的剩余电量。)" b3 i0 W. r) Y# f2 n
Test result-1.JPG % W$ |% j6 t2 `3 J% Q: n' _
5 m/ e; [+ W& S5 A# h+ V( Q
7 Z- I& }# o' e# G* E6 t

  \. y8 a: J3 n& ^) K正弦曲线测试实例,使用37个X轴等间隔的数据(每10度一个),线性插值出0-360度的范围一段正弦曲线的结果:1 D# ?* u" p' [% r* G
(为了提高转换精度,合理的做法是在曲线变化剧烈的部分,密集取点;线性好的部分,少量取点。而不是采用等间隔的方式取点。)
1 ]% a( |, ?; Y# K4 d# H Test result-2.JPG
$ _0 G2 Y4 P. s' F  O* s8 x1 Y
" W/ ?/ n& E" \% q4 t
$ L0 Z" h' Y  I6 z2 `9 U8 k
; V. e+ \  Y, x2 f1 T最后,给出子程序:
+ }% b3 v: f& G- y0 O5 V! V需要说明的是,笔者对有符号的整数(int)和浮点数(float)有“原始的抵触”,喜欢使用无符号整数类型(uint)。所以只做出了整数类型的。
. ~0 p0 _9 U4 r
4 t% V, b# I5 q, d( O7 {# r+ [! U

  1. * v, z5 f# W5 _
  2. //General integer Linear Interpolation
    ; s2 p' _9 m7 ]$ [
  3. //
    8 S" ^% G# A0 f* _; X
  4. //setup: uint16_t Y[size] = {Y0, Y1, Y2, , , Ysize-1};2 a) K0 |0 X* h9 H/ A
  5. //setup: uint16_t X[size] = {X0, X1, X2, , , Xsize-1};
    9 Z/ B; |7 t0 y3 d, O: k2 p
  6. // - Two Arrays in integer format, Unsigned, no negative values.8 f" f( L2 D; I# w: ?0 b2 S9 T
  7. // - X[0]<X[1]<X[2]......<Xn, must increasing.1 c& W7 s$ L3 _  I& x2 G4 S5 C; n

  8. & ~2 t5 d" ]7 K, }' \5 ~4 [0 q
  9. //Test data-1, battery capacity:- X) {9 a- W. n/ s
  10. const uint16_t X[] = {31778, 33442, 39398, 40421};
    9 V' \" ?  \0 p6 I+ R* d
  11. const uint16_t Y[] = {0,     29,    94,    100  };1 j1 \% d' m! h8 C; v
  12. , v8 \9 g: I0 d% \0 |% G, i
  13. //Test data-2, sine wave:$ {5 y5 V3 m* k3 t* ~: I
  14. //const uint16_t X[] = {0,10,20,30,40,50,60,70,80,90,
    % U6 m+ H# Z$ U
  15. //                      100,110,120,130,140,150,160,170,180,190,: \& _. ]* m& V" V/ K
  16. //                      200,210,220,230,240,250,260,270,280,290,
    8 I+ {2 z" j" }! j8 d* P! r
  17. //                      300,310,320,330,340,350,360};( e; g; L( M8 e) Y" X7 ]+ h9 z7 n6 t- Q% ]
  18. //const uint16_t Y[] = {2000,2174,2342,2500,2643,2766,2866,2940,2985,3000,
    8 `' \: w7 t) v! d
  19. //                      2985,2940,2866,2766,2643,2500,2342,2174,2000,1826,! ^8 n" W5 k6 O( l8 G
  20. //                      1658,1500,1357,1234,1134,1060,1015,1000,1015,1060,
    ) h* Z3 s+ d6 z6 ?- _
  21. //                      1134,1234,1357,1500,1658,1826,2000};
    # [% n: }! _: o* J/ {
  22. : e2 t0 u; \, j5 h2 R

  23. ) ~0 {1 @" C: O' e; H/ }* n/ Y
  24. uint16_t u16LinearInterpolation(uint16_t xdata)
    0 m' L7 Y+ i4 m' I9 H. B2 ?8 ?" e7 E7 w
  25. {* G" y2 M- |( ^- a
  26.   uint32_t u32Temp;
    . L  M* c( l0 O
  27.   int i,size;' W" l3 t2 g- m- J; t! M
  28.   
    - L' B5 ]" G" n$ m
  29.   size = sizeof(X)/2; //get the array numbers, uint16_t occupied 2 bytes.
    5 \( m8 Y9 o4 H
  30.   $ e5 L: R0 S6 I9 G2 N
  31.   if (xdata <= X[0]) return Y[0];& ?1 j, D1 x8 I
  32.   if (xdata >= X[size-1]) return Y[size-1];
    ( j3 \  G0 U8 f$ f9 m4 O7 T( p' X
  33.   
    0 b1 Z/ U0 K9 O0 F! L
  34.   for (i=0; i<(size-1); i++)/ S7 D1 ^, y5 Z. q" e8 f2 Y
  35.   {" f, z1 }5 i* T# X' S( t
  36.     if ((xdata >= X[i]) && (xdata < X[i+1])) break;    : V4 H5 e! H0 l0 Y
  37.   }. Q# K0 v( V" m3 V1 N6 T& o
  38.   
    # k! V/ w' m8 T! D* U  `
  39.   if ((xdata == X[i]) || (Y[i] == Y[i+1])) return Y[i];
      S8 U: C8 J3 Z1 C' H! Q2 v
  40.   8 F" T; t2 Q5 ~9 R3 X0 h
  41.   //Y(x)=[Yi*(Xi+1-x)+Yi+1*(x-Xi)]/(Xi+1-Xi)
    ( w3 ~+ D* A# t* K
  42.   u32Temp = Y[i]*(X[i+1]-xdata);7 D  \4 e: ~: }% y" s& W' G/ N% ~% r
  43.   u32Temp += Y[i+1]*(xdata-X[i]);
    4 S" p  y0 E: o5 l
  44.   u32Temp /= X[i+1]-X[i];, c6 ^) i0 k* `8 c2 k  d

  45. 8 I0 W3 z% [  @9 I8 W
  46.   return (uint16_t) u32Temp;
    - d' C, m" s- t4 r$ @  Q
  47. }- |( [& b5 G% _& m1 L, h1 `
复制代码

4 |8 d/ {$ g& p; G9 G2 \* y# J/ Q" n3 P6 m% P: Y' n! I
4 q. D. }: `. b$ ?( U( [

" \- T9 W2 u( d6 E; ?  B- V: v' A0 n( U+ @5 Q6 E" y
收藏 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 手机版