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

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

[复制链接]
radio2radio 发布时间:2018-11-25 23:46
本帖最后由 radio2radio 于 2018-11-26 15:51 编辑
( g1 a% h$ _: W/ x: T4 k: g4 Z; d& a% T
虽然这个话题是程序员的基本功,但是,每一次实际使用时都要“重新编程+除错”折腾一番。, @9 r8 \. n7 ~( r3 v$ c
于是,萌发了搞一个“通用的”,目的是,下次用到时,拿过来就用。4 P9 L! x, b) \& n+ a3 ]
大家看看我的方法是不是最佳的,欢迎提出改进方案。
  }5 n! S5 r& X: y
9 Q$ O/ C! U* v. d' i! {由MCU的ADC读到的“真实世界”的数据,0~1023对应10bit的ADC,0~4095对应12bit,0~65535对应16bit。通常,这些数据都要通过简单的数据处理,变换成电压/电流/温度/压力/等等意义明确的数值,用于传输或者显示。
; D3 ^- L7 D& k) a/ ~8 B, E+ N! M  V7 v  x* g4 k5 h
线性插值,就是最最常用的数据处理方法。 直线函数公式:, u  A# T/ w1 G/ P2 ~* m
My Formula.jpg ! F) V1 x& S1 j1 m8 ]
/ c$ B4 i- r( ~& L: Y5 \% G* s
. Z4 b3 ]' y2 r) ?# ^4 t
应用实例,某电池的“电压—容量”测量估算结果,大致如下图所示:% v3 ]/ R7 }: U( {, h$ L1 B3 ^
BatteryCap vs Data.JPG : M8 R$ \1 q7 b6 ~( n0 L- e9 o
  v8 Z6 q: G: {. |$ f! S
由曲线上面可以看出,虽然已经有了10组实测数据,但是只要取其中黄色的4组数据,也就是用3段直线进行线性插值,就可以得到很好的“近似结果”。3 b4 Z2 T1 Z" q
下图,就是用我的“通用线性插值程序”得到的计算结果,看图形,基本上一样的。* N4 q. Y" i* X! _# s% O7 V6 X7 F, Z
(注意,ADC数据所对应的电池电压值,只是测量ADC数据时用可调电源代替电池的外加电压,它们并不参与运算。 直接由ADC数据插值出电池的剩余电量。). m( H/ q4 o! v1 ~6 r
Test result-1.JPG
( l, [6 `! V% o" q1 Z; o: d
6 x! ~* x5 z0 B, e6 o' u
+ y- S2 I/ [! D2 o1 T5 n, ?
# Z  m# i$ M; |' I0 ]7 [6 Y正弦曲线测试实例,使用37个X轴等间隔的数据(每10度一个),线性插值出0-360度的范围一段正弦曲线的结果:
, g! l; _% g$ m9 h(为了提高转换精度,合理的做法是在曲线变化剧烈的部分,密集取点;线性好的部分,少量取点。而不是采用等间隔的方式取点。)
& h+ [5 i. w8 K+ u3 \- ?0 ^ Test result-2.JPG : l+ \# Y* {; i
! }2 [4 G. Q9 H! ~" D* }! H; h

7 b+ ~. O7 y: ]) T8 b5 G$ h
) i  g" ~) ~- p8 o5 n- S8 p! P最后,给出子程序:
- H+ G6 Z% s0 \% ?- _7 I/ o. ?- \需要说明的是,笔者对有符号的整数(int)和浮点数(float)有“原始的抵触”,喜欢使用无符号整数类型(uint)。所以只做出了整数类型的。
6 [) E# f5 f2 j* Z" \
5 i0 Z- m2 @: e" w: Z* L9 V

  1. + V5 `" ~1 V* F3 K* i) e
  2. //General integer Linear Interpolation
    ( m8 l" v6 s2 [6 a1 U
  3. //
    $ l; u  x8 J* U
  4. //setup: uint16_t Y[size] = {Y0, Y1, Y2, , , Ysize-1};
    0 C. x- G' R" d. G( r; |. s! L
  5. //setup: uint16_t X[size] = {X0, X1, X2, , , Xsize-1};
    : P( T4 C7 }( B( g6 Z; B  @
  6. // - Two Arrays in integer format, Unsigned, no negative values.
    5 y! v" w& B! m+ Q0 Z* Y4 k
  7. // - X[0]<X[1]<X[2]......<Xn, must increasing.
    * `: N2 _! B/ A9 m/ w0 t% v; l

  8. - }$ A) P) ~. `3 C7 X- g! I" I& Z
  9. //Test data-1, battery capacity:
    " r1 ]7 O( N6 W8 ^
  10. const uint16_t X[] = {31778, 33442, 39398, 40421};' P/ V5 P- x* b2 ~& `
  11. const uint16_t Y[] = {0,     29,    94,    100  };
    % m9 ^* g, P- c5 Z1 Q( m
  12.   G; _) J, C; S9 q5 ^
  13. //Test data-2, sine wave:
    . i$ w" O/ b1 e) G' k* u# Y5 O9 A
  14. //const uint16_t X[] = {0,10,20,30,40,50,60,70,80,90,
    1 t( P3 j% I: W) x* ]0 ~) e. @
  15. //                      100,110,120,130,140,150,160,170,180,190,
    ; f, }$ p. q7 N  {8 m5 H( |
  16. //                      200,210,220,230,240,250,260,270,280,290,
    # [; C8 g5 D4 D* r, ]/ @' i( d
  17. //                      300,310,320,330,340,350,360};
    * g3 R1 G! z1 h
  18. //const uint16_t Y[] = {2000,2174,2342,2500,2643,2766,2866,2940,2985,3000,
    4 g, x/ ?' ~8 b/ t7 }
  19. //                      2985,2940,2866,2766,2643,2500,2342,2174,2000,1826,! e2 g$ C' |9 t3 V6 \! A+ H. @
  20. //                      1658,1500,1357,1234,1134,1060,1015,1000,1015,1060,4 ~( S0 h$ N" [! x! L# U
  21. //                      1134,1234,1357,1500,1658,1826,2000};* J) g. m$ O# T6 w' v

  22. / g8 b" ~: Q3 a( a
  23. - C0 R- i& l& T' z" X# E2 M9 m" R  Z
  24. uint16_t u16LinearInterpolation(uint16_t xdata)3 J0 T# q1 R. A' g7 @3 j" p) g
  25. {
    3 j. z. ~2 h8 b# _& d& v
  26.   uint32_t u32Temp;
    ; U( P# y/ R/ C4 u. R+ _* i
  27.   int i,size;2 f# i) H; ~* p( @6 G) ]; K; `
  28.   
    , x2 F3 f3 J; c' g
  29.   size = sizeof(X)/2; //get the array numbers, uint16_t occupied 2 bytes.9 I6 \+ P& _- e6 n* k
  30.   
    7 C% f* `1 H1 \# `9 [1 a8 g
  31.   if (xdata <= X[0]) return Y[0];. Q4 e9 b  X3 v/ l" V% L. n
  32.   if (xdata >= X[size-1]) return Y[size-1];
      I' D0 r0 h9 D6 T
  33.   
    # j- F* g' d3 r! x% t, j1 X# p
  34.   for (i=0; i<(size-1); i++)4 Z# @  v' u7 u) v! M2 M
  35.   {
    2 ~5 ?) k/ N7 R1 A! z" Y
  36.     if ((xdata >= X[i]) && (xdata < X[i+1])) break;      a. n% S3 l) j5 g9 f  i$ o$ G
  37.   }
    7 Z  M2 K1 `9 e/ Q
  38.   
    7 s, W( h$ T- t) v
  39.   if ((xdata == X[i]) || (Y[i] == Y[i+1])) return Y[i];: I- X4 s, ]. {
  40.   
    , o7 Q" V1 Z6 V
  41.   //Y(x)=[Yi*(Xi+1-x)+Yi+1*(x-Xi)]/(Xi+1-Xi)
    9 v/ G9 A6 |$ T: Y$ a
  42.   u32Temp = Y[i]*(X[i+1]-xdata);
    + H; s3 z' ~: M
  43.   u32Temp += Y[i+1]*(xdata-X[i]);+ U6 H  s. Z5 |: @" @+ q* u- w
  44.   u32Temp /= X[i+1]-X[i];8 `  F( U5 C, K4 J9 t
  45. ; u" x+ @. X7 P1 H1 R+ n
  46.   return (uint16_t) u32Temp;" H8 a$ I: z8 X4 _( G. J! U
  47. }
    1 P( M; Z5 D3 {, _/ o7 ]4 S3 u
复制代码

  c% M7 u+ I  B4 `9 r, V+ ]7 N3 e  m3 n2 \$ u

" i! d( @+ H! D1 X0 a6 I# d: Z/ I8 Q4 V/ u, V0 @- n
: g/ b# ~- T* e7 b' T( {# B
收藏 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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版