请选择 进入手机版 | 继续访问电脑版

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

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

[复制链接]
radio2radio 发布时间:2018-11-25 23:46
本帖最后由 radio2radio 于 2018-11-26 15:51 编辑 ; \5 `/ l! Z  U' h8 y5 g8 K: ?

7 L; W) F! B# L: l' ~% N! W虽然这个话题是程序员的基本功,但是,每一次实际使用时都要“重新编程+除错”折腾一番。
7 N* w) V; A0 m: k0 u# ^* X2 R于是,萌发了搞一个“通用的”,目的是,下次用到时,拿过来就用。9 m* |5 E' X- [- x, @9 |: V
大家看看我的方法是不是最佳的,欢迎提出改进方案。
1 R; `4 ?; y' o" X
, X6 ?8 `8 Q: A* z. L$ s( h) k由MCU的ADC读到的“真实世界”的数据,0~1023对应10bit的ADC,0~4095对应12bit,0~65535对应16bit。通常,这些数据都要通过简单的数据处理,变换成电压/电流/温度/压力/等等意义明确的数值,用于传输或者显示。  D3 N; X  r: l+ E; A
& O4 [9 C9 r, y
线性插值,就是最最常用的数据处理方法。 直线函数公式:- d# y6 m  {+ ^: E
My Formula.jpg
; D8 g5 Y! A0 D$ y6 E( H2 x6 W$ q7 W5 f
$ T! w" z; ?) l7 j, D5 E
应用实例,某电池的“电压—容量”测量估算结果,大致如下图所示:
6 }0 {2 R+ X+ s BatteryCap vs Data.JPG
# S7 V1 J" a0 P: U3 n7 m- Z2 @6 F' q  C3 R( @
由曲线上面可以看出,虽然已经有了10组实测数据,但是只要取其中黄色的4组数据,也就是用3段直线进行线性插值,就可以得到很好的“近似结果”。6 z" G# n' P6 l4 A1 i3 E
下图,就是用我的“通用线性插值程序”得到的计算结果,看图形,基本上一样的。. [" ?3 s& o, `  v$ G. N  }5 I
(注意,ADC数据所对应的电池电压值,只是测量ADC数据时用可调电源代替电池的外加电压,它们并不参与运算。 直接由ADC数据插值出电池的剩余电量。)
' C( P$ h8 f! H4 ?" D Test result-1.JPG / c5 n9 u/ E3 `
# w/ P4 O, b! t

8 e  _& Q! z: X
' ]6 ?0 t8 ?- \7 k正弦曲线测试实例,使用37个X轴等间隔的数据(每10度一个),线性插值出0-360度的范围一段正弦曲线的结果:
+ S( `& a) j6 W; \7 m" Z(为了提高转换精度,合理的做法是在曲线变化剧烈的部分,密集取点;线性好的部分,少量取点。而不是采用等间隔的方式取点。): ^; p& @5 v2 f+ [1 x  f/ I
Test result-2.JPG
! ]( ]- a3 W1 {" [) T+ @
& G% M* `' d9 }4 t& R# Q5 M9 M; a) Z( X3 b' }5 w, {$ ^

) P/ P: g5 m: q6 U最后,给出子程序:
: ~; j4 t& z9 q8 _. M2 p需要说明的是,笔者对有符号的整数(int)和浮点数(float)有“原始的抵触”,喜欢使用无符号整数类型(uint)。所以只做出了整数类型的。5 l- V2 r: w8 P& o
, O! y  S+ c% P5 R$ f
  1. 8 \' i% u7 T& f6 _2 \" B$ ~
  2. //General integer Linear Interpolation9 x: l6 s' ^; C5 I
  3. //
    # K5 Z& i% T/ l  k6 i8 Y" J$ }
  4. //setup: uint16_t Y[size] = {Y0, Y1, Y2, , , Ysize-1};
    2 k& e8 Q* s, u$ ~
  5. //setup: uint16_t X[size] = {X0, X1, X2, , , Xsize-1};/ z+ ]. B7 p1 q1 \8 ^
  6. // - Two Arrays in integer format, Unsigned, no negative values.
    ! H  w1 Y# W$ U: @! x/ O5 r
  7. // - X[0]<X[1]<X[2]......<Xn, must increasing.
    3 ^2 n1 F! B2 X; ?

  8. / r( y) Y0 C+ J$ K, V% }, ]9 w$ w
  9. //Test data-1, battery capacity:& I0 W* D2 z* q) A3 Q
  10. const uint16_t X[] = {31778, 33442, 39398, 40421};6 f. _- Z% P0 f; k* z1 A" O8 i5 D
  11. const uint16_t Y[] = {0,     29,    94,    100  };/ o* F! W+ \; T% e1 L, ~

  12. + K% N4 o8 \) M6 O& h
  13. //Test data-2, sine wave:  D+ }* @. Z! y) W, j9 a
  14. //const uint16_t X[] = {0,10,20,30,40,50,60,70,80,90,
    3 c6 {: z, t! U9 M
  15. //                      100,110,120,130,140,150,160,170,180,190,
    3 [, l5 g; e! O4 y. ^1 [
  16. //                      200,210,220,230,240,250,260,270,280,290,6 g" X9 T6 l* U0 N* F  s
  17. //                      300,310,320,330,340,350,360};# D" d% a; C# {; G/ k3 Y, ]
  18. //const uint16_t Y[] = {2000,2174,2342,2500,2643,2766,2866,2940,2985,3000,
    ! j" l, e& }4 A, \' X$ c8 S1 k
  19. //                      2985,2940,2866,2766,2643,2500,2342,2174,2000,1826,
    7 H, C2 C! W5 o+ @2 s; ~
  20. //                      1658,1500,1357,1234,1134,1060,1015,1000,1015,1060,7 E4 [& U. D0 F7 U0 p, Y3 A
  21. //                      1134,1234,1357,1500,1658,1826,2000};9 b4 K: z, j  Z4 C* d9 {

  22. % m0 L7 w" Q4 X# e) k; y/ T
  23. - g  i  n2 B! d. ~, T8 F1 \8 {! P
  24. uint16_t u16LinearInterpolation(uint16_t xdata)
    " O5 f& C$ d4 w" J- b1 s
  25. {
    8 [3 e$ t' z: _& B$ T/ `  o
  26.   uint32_t u32Temp;
    % x7 {4 K2 l  c. c* |
  27.   int i,size;4 W% C  D6 \/ I
  28.   , ^$ o# m; d' |) f0 N
  29.   size = sizeof(X)/2; //get the array numbers, uint16_t occupied 2 bytes.
    2 S, Y/ W7 V) f/ I0 N
  30.   
    $ @% N) Y3 \! H9 ~- n+ t1 N
  31.   if (xdata <= X[0]) return Y[0];" @  I* s6 w1 q0 i0 \# @
  32.   if (xdata >= X[size-1]) return Y[size-1];
    4 t% C; b' W$ j$ g3 v
  33.   
    8 _( M% A9 t3 _8 L- z7 f
  34.   for (i=0; i<(size-1); i++)' e* \9 }- b& q5 _  c
  35.   {
    5 Z4 @1 @; f9 _( d" ~0 S
  36.     if ((xdata >= X[i]) && (xdata < X[i+1])) break;   
    " G8 F9 l0 {' f1 G
  37.   }5 v% ?1 b- O* k8 ~$ r
  38.   
    3 w  h/ h) M3 y: s
  39.   if ((xdata == X[i]) || (Y[i] == Y[i+1])) return Y[i];
    / E0 E0 [- B( G, W
  40.   ( z8 e, f* A. w
  41.   //Y(x)=[Yi*(Xi+1-x)+Yi+1*(x-Xi)]/(Xi+1-Xi)) b7 A3 X% N6 [- F) v9 i
  42.   u32Temp = Y[i]*(X[i+1]-xdata);9 ]2 O+ _: m- \
  43.   u32Temp += Y[i+1]*(xdata-X[i]);) t% s) ]4 s7 ?
  44.   u32Temp /= X[i+1]-X[i];/ N1 u( {0 R6 M# {6 J$ i
  45. ! Y& L0 |. U7 H. E
  46.   return (uint16_t) u32Temp;
    6 V! @  f9 S7 J& u
  47. }
    * @' f, a8 E9 U2 T. \( S0 M
复制代码

4 l7 v2 ]/ L) z/ A) y) ]( \& f8 `) ^* s; ]
+ x2 I& L& C6 R9 m# l9 c

: T9 g- q6 {5 Q1 R
: E( {0 r( O8 j0 p4 U7 x$ ]
收藏 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 手机版