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

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

[复制链接]
radio2radio 发布时间:2018-11-25 23:46
本帖最后由 radio2radio 于 2018-11-26 15:51 编辑
3 R0 s  a. i# X+ i/ R
$ E7 o' `9 c# A  i7 r  _虽然这个话题是程序员的基本功,但是,每一次实际使用时都要“重新编程+除错”折腾一番。
+ p  A# M/ d/ f1 ?. |& h" t于是,萌发了搞一个“通用的”,目的是,下次用到时,拿过来就用。
* S; N  u7 {$ A- }7 a2 K& H大家看看我的方法是不是最佳的,欢迎提出改进方案。+ B) g2 A& L" u! _' j
" Y3 }' k* M1 |5 U0 K2 }
由MCU的ADC读到的“真实世界”的数据,0~1023对应10bit的ADC,0~4095对应12bit,0~65535对应16bit。通常,这些数据都要通过简单的数据处理,变换成电压/电流/温度/压力/等等意义明确的数值,用于传输或者显示。) T# E2 z' @1 A! }1 c

6 x) p  Q; {( i+ X0 `1 i8 E  j$ M线性插值,就是最最常用的数据处理方法。 直线函数公式:
6 C# y: s5 j; n! q# p" Q My Formula.jpg
" V, M+ P/ M; |% _* a6 L& A9 F' j. b5 w0 J9 {

( w7 z' R7 K; E0 v/ l* q应用实例,某电池的“电压—容量”测量估算结果,大致如下图所示:: q8 J; ~+ F2 ^) f9 Q7 [
BatteryCap vs Data.JPG
5 n8 a% T7 ?5 a' H3 ~% B" l6 P/ s% R; x7 v1 j% M7 T2 H
由曲线上面可以看出,虽然已经有了10组实测数据,但是只要取其中黄色的4组数据,也就是用3段直线进行线性插值,就可以得到很好的“近似结果”。
0 a" \: M$ ]  c9 Y下图,就是用我的“通用线性插值程序”得到的计算结果,看图形,基本上一样的。
' L" `, }7 P5 W6 I, T$ h8 B(注意,ADC数据所对应的电池电压值,只是测量ADC数据时用可调电源代替电池的外加电压,它们并不参与运算。 直接由ADC数据插值出电池的剩余电量。), y5 `8 e: R9 ^6 N# q. {
Test result-1.JPG
: d$ B0 t4 O# W: d, }1 g" O
$ Q- b5 P* p  N$ d! ]7 I( b2 w! p* q3 x+ ^9 a+ e' w: Z
' l: w3 v( I- R! f) A; p
正弦曲线测试实例,使用37个X轴等间隔的数据(每10度一个),线性插值出0-360度的范围一段正弦曲线的结果:9 a* I" W/ P) S
(为了提高转换精度,合理的做法是在曲线变化剧烈的部分,密集取点;线性好的部分,少量取点。而不是采用等间隔的方式取点。)% H) r+ d! b1 @$ B1 T' D5 f
Test result-2.JPG
, W- Q2 y' g! G! u  x- C, j" }- A3 f2 f6 ?( u8 M! m
+ G1 }# I3 v0 e/ S: r
! E& Y5 `: f& f1 H
最后,给出子程序:
! \9 y5 N* `' O2 A9 Y9 ?需要说明的是,笔者对有符号的整数(int)和浮点数(float)有“原始的抵触”,喜欢使用无符号整数类型(uint)。所以只做出了整数类型的。
- Z4 z8 E$ @; ~/ J6 p0 j% r, p5 A
2 T( ?, O* K2 @, N

  1. - u2 B9 x  F- _" b, D$ L" m
  2. //General integer Linear Interpolation
    # \" w" e6 l8 F
  3. //( w$ w, J# Y0 \# X; j5 g
  4. //setup: uint16_t Y[size] = {Y0, Y1, Y2, , , Ysize-1};
    . h1 q: g+ j, j- @: {. e
  5. //setup: uint16_t X[size] = {X0, X1, X2, , , Xsize-1};
    - E' v% v9 h& t: \. Z5 I
  6. // - Two Arrays in integer format, Unsigned, no negative values.
    ! a4 d3 J7 `9 ?% M
  7. // - X[0]<X[1]<X[2]......<Xn, must increasing.
    % }. N# K3 a3 j6 d; G  T
  8. 5 B6 a) q% f! N6 G3 M
  9. //Test data-1, battery capacity:" _3 _: y5 \; C; W; ~9 s( r) B2 n& g& p0 ^
  10. const uint16_t X[] = {31778, 33442, 39398, 40421};
    ; {* E0 l  G! z# m' ~) s( G9 p
  11. const uint16_t Y[] = {0,     29,    94,    100  };
    ' N" M) K4 E7 Q. n) ]1 e
  12. , r! i3 g) n( O$ m5 u: d5 N( O! }/ y
  13. //Test data-2, sine wave:3 M3 u5 U6 g2 M  v4 y
  14. //const uint16_t X[] = {0,10,20,30,40,50,60,70,80,90,; c+ t3 K7 n; W% A5 t, d- a" f! H$ v' f
  15. //                      100,110,120,130,140,150,160,170,180,190,
    - F+ i- C# I9 z$ z$ B( |% x& M5 [
  16. //                      200,210,220,230,240,250,260,270,280,290,
    1 o  @$ u& c0 r% o$ g7 x) a2 B3 Z
  17. //                      300,310,320,330,340,350,360};
    & j' U$ W7 _- x
  18. //const uint16_t Y[] = {2000,2174,2342,2500,2643,2766,2866,2940,2985,3000,
      H) _! K+ g( }: x
  19. //                      2985,2940,2866,2766,2643,2500,2342,2174,2000,1826,, B6 m) M3 J: D  k6 r
  20. //                      1658,1500,1357,1234,1134,1060,1015,1000,1015,1060,9 y: i9 @! r. e1 v
  21. //                      1134,1234,1357,1500,1658,1826,2000};
    8 ^1 P; H( H- T  t  j

  22. $ S8 }; l) n* G% y- }

  23. " [" _( @* n6 C' W
  24. uint16_t u16LinearInterpolation(uint16_t xdata)
    % N* d  J. ]# q5 U
  25. {( m: U& |  C1 @6 u
  26.   uint32_t u32Temp;
    3 d3 t! F9 j) V2 X! V
  27.   int i,size;! k# _' V* V9 @9 I" \6 E4 n
  28.   
    ( K" p5 n. L' H# m6 J
  29.   size = sizeof(X)/2; //get the array numbers, uint16_t occupied 2 bytes.
    ) k1 @, u$ _& S
  30.   
    % D6 H5 h& W, H- V$ M. u
  31.   if (xdata <= X[0]) return Y[0];
    ' g. H' ^' \9 H/ F# O
  32.   if (xdata >= X[size-1]) return Y[size-1];
    % Y$ f* N2 |7 _3 x
  33.   
    + u' ]% [% v+ r2 J
  34.   for (i=0; i<(size-1); i++)
    + Y$ [- t( e5 {9 {! r' r
  35.   {" b5 h' u& A( Z6 G7 v+ s4 j: s$ o
  36.     if ((xdata >= X[i]) && (xdata < X[i+1])) break;    , w" S; c8 u5 b, z
  37.   }
    : B' \) c# W  D* a/ K. R
  38.   
    ) I% G0 a: u7 W/ L. `
  39.   if ((xdata == X[i]) || (Y[i] == Y[i+1])) return Y[i];. o7 z! X" b0 F! R; L* |2 |
  40.   
    - a0 i: z4 i' x% n
  41.   //Y(x)=[Yi*(Xi+1-x)+Yi+1*(x-Xi)]/(Xi+1-Xi)
    ; B) ?- T3 {3 L  B, n
  42.   u32Temp = Y[i]*(X[i+1]-xdata);
    % H: a5 b* a8 ~* h1 C; I+ V
  43.   u32Temp += Y[i+1]*(xdata-X[i]);
    ) o3 L1 H* F4 q/ j# J3 M' B' s
  44.   u32Temp /= X[i+1]-X[i];
    % D: G; W- y7 [/ _1 R6 \
  45. $ S! c" A/ v6 d2 o" N
  46.   return (uint16_t) u32Temp;
    # j6 l1 Z8 K5 q3 s6 \" M! ^
  47. }; S; ?8 a6 L$ b" Q0 i# Q$ R5 r+ a" q
复制代码
$ i- C) A* @% i) F

5 X/ b9 t) \4 n) f* L& J/ W! F+ e) W% q* v
, \% j. J5 h/ C. i! e, F4 v2 S& m
8 M- W( @* R9 g3 R0 C' f
赞 收藏 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管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版