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

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

[复制链接]
radio2radio 发布时间:2018-11-25 23:46
本帖最后由 radio2radio 于 2018-11-26 15:51 编辑
9 [% b3 ^. ]1 M. k  G! z4 H9 W. j+ V; d% Y
虽然这个话题是程序员的基本功,但是,每一次实际使用时都要“重新编程+除错”折腾一番。1 t6 k% d( d8 o( ]% e& }2 X  Y
于是,萌发了搞一个“通用的”,目的是,下次用到时,拿过来就用。
0 S3 l. a4 x1 A大家看看我的方法是不是最佳的,欢迎提出改进方案。
5 u$ i5 a) W. ]  X- D) l: ^2 m2 O5 m* M( f$ ~0 a, P" n6 f
由MCU的ADC读到的“真实世界”的数据,0~1023对应10bit的ADC,0~4095对应12bit,0~65535对应16bit。通常,这些数据都要通过简单的数据处理,变换成电压/电流/温度/压力/等等意义明确的数值,用于传输或者显示。: _( j9 g/ }$ _. Y4 I& O% K8 z4 c
4 e" K6 X- k% _3 Y0 M) O. t
线性插值,就是最最常用的数据处理方法。 直线函数公式:& G; U- N, A! W' X, a
My Formula.jpg 6 g1 P3 I$ M) B, y0 H2 h
; P, W8 W' V8 z8 }2 \5 t  g
! ^) d2 w* i, h* D& ]- k
应用实例,某电池的“电压—容量”测量估算结果,大致如下图所示:6 l# [9 C4 y2 Q+ S, c
BatteryCap vs Data.JPG
6 c- b7 a. ]" x( Z  v9 p0 z
4 D, l' I& w. X# f由曲线上面可以看出,虽然已经有了10组实测数据,但是只要取其中黄色的4组数据,也就是用3段直线进行线性插值,就可以得到很好的“近似结果”。7 C- e% q8 J- c6 i+ G) i. n
下图,就是用我的“通用线性插值程序”得到的计算结果,看图形,基本上一样的。
1 \' H% r0 o8 R2 V7 G' ~2 k8 U(注意,ADC数据所对应的电池电压值,只是测量ADC数据时用可调电源代替电池的外加电压,它们并不参与运算。 直接由ADC数据插值出电池的剩余电量。)8 J4 C7 s; B7 ]  l$ ~7 T! t4 \
Test result-1.JPG
' P2 Y, C! J' F1 r! ?0 C# A" d1 Q4 L+ a5 ^% ^1 V

0 V. O& Y* s! t* N7 ?3 n
  X$ ?4 a+ g7 E  ]; b1 N正弦曲线测试实例,使用37个X轴等间隔的数据(每10度一个),线性插值出0-360度的范围一段正弦曲线的结果:
# |/ z, M. ^" c(为了提高转换精度,合理的做法是在曲线变化剧烈的部分,密集取点;线性好的部分,少量取点。而不是采用等间隔的方式取点。)
* \% A! t$ m8 l/ D! f, b Test result-2.JPG
6 Q3 {: q& ^- w) p. [' C1 J+ ~7 V# c$ G% U

2 p! c! f7 z. J
5 b1 x4 q# f% J: M6 j最后,给出子程序:: v9 u: \! @* t
需要说明的是,笔者对有符号的整数(int)和浮点数(float)有“原始的抵触”,喜欢使用无符号整数类型(uint)。所以只做出了整数类型的。
# S6 x" A& L* w1 w3 g9 e
9 I- v' e- |2 m3 o# e6 Q' Z
  1. ; O) [8 J& }! h& o3 V3 a+ a# U
  2. //General integer Linear Interpolation5 T4 f* |$ i" g! {( H4 g4 t! h
  3. //4 F; I7 Y/ O( ]$ X6 d  G. V
  4. //setup: uint16_t Y[size] = {Y0, Y1, Y2, , , Ysize-1};) ?& }( \( T9 ~8 s
  5. //setup: uint16_t X[size] = {X0, X1, X2, , , Xsize-1};+ O9 r2 o4 C" r& h- `0 d
  6. // - Two Arrays in integer format, Unsigned, no negative values.
    . R1 \: g) B; ^& D8 o' S" _; m
  7. // - X[0]<X[1]<X[2]......<Xn, must increasing.+ N- M9 u* X" X$ s

  8. " J7 m. N1 B1 f
  9. //Test data-1, battery capacity:9 G9 A+ I9 S  Z$ V& i( P' C
  10. const uint16_t X[] = {31778, 33442, 39398, 40421};( F6 E' L' S4 ^# E
  11. const uint16_t Y[] = {0,     29,    94,    100  };
    ' n+ @7 u# B$ v$ z

  12. : a; ^) c. U+ L' j
  13. //Test data-2, sine wave:
    / k! q! [6 O$ ^+ [: H1 t" j
  14. //const uint16_t X[] = {0,10,20,30,40,50,60,70,80,90,/ }9 T; j/ n5 H3 s) A- ^
  15. //                      100,110,120,130,140,150,160,170,180,190,5 f& z5 Y, ^  y2 ?, \- R3 ~: e( z6 _
  16. //                      200,210,220,230,240,250,260,270,280,290,# [8 h# a5 |' @
  17. //                      300,310,320,330,340,350,360};# R6 k3 H+ a7 i- I6 J$ |9 H9 I
  18. //const uint16_t Y[] = {2000,2174,2342,2500,2643,2766,2866,2940,2985,3000,4 v( W% {, h& {) \8 ^; S
  19. //                      2985,2940,2866,2766,2643,2500,2342,2174,2000,1826,
    0 l5 N1 ?/ x: Q0 d
  20. //                      1658,1500,1357,1234,1134,1060,1015,1000,1015,1060,3 r/ w: Q+ c5 P
  21. //                      1134,1234,1357,1500,1658,1826,2000};% Y! I2 f- s, q4 }% z

  22. # L, d" r+ G: k: V/ r
  23. ! m  Y. S1 S. J$ n2 f- ]3 \
  24. uint16_t u16LinearInterpolation(uint16_t xdata)
    2 Q! v0 G# F( p/ G5 n" K- i" H
  25. {  I1 ?2 f' C5 E2 ^* d* ]; c
  26.   uint32_t u32Temp;
    # y# N, i" Y( O9 M* i2 g# k
  27.   int i,size;9 ~) V. E4 @1 m7 O
  28.   1 _( O# |$ G. B3 X, q) Q
  29.   size = sizeof(X)/2; //get the array numbers, uint16_t occupied 2 bytes.
    * O$ l, R! V; ^* H
  30.   - v+ ?. J3 w4 w- f- C! e
  31.   if (xdata <= X[0]) return Y[0];; {" |! H- k; ?
  32.   if (xdata >= X[size-1]) return Y[size-1];
    ) F3 c  ]' }5 R: V2 d7 ]; A% B+ ]
  33.   
    4 R3 o+ G* z# ~: e( }; @1 F
  34.   for (i=0; i<(size-1); i++)
    ' w8 B- n# e; m
  35.   {
    2 {; k; |! c+ F3 Q* p7 f
  36.     if ((xdata >= X[i]) && (xdata < X[i+1])) break;    # ~4 ]3 M" s: e
  37.   }/ J! y% U; C. g1 s6 T) o4 w
  38.   
    # F: I# S3 b3 u7 U; Y- H, K
  39.   if ((xdata == X[i]) || (Y[i] == Y[i+1])) return Y[i];8 M* ~$ I) ?. Q3 e7 o
  40.   
    : p7 f- b" A/ W, T
  41.   //Y(x)=[Yi*(Xi+1-x)+Yi+1*(x-Xi)]/(Xi+1-Xi)2 I) U  r8 x; S! r
  42.   u32Temp = Y[i]*(X[i+1]-xdata);
    % S1 p- M: ]3 J* A- s- z2 l
  43.   u32Temp += Y[i+1]*(xdata-X[i]);
    3 g  H* f1 p$ K; o; V& |
  44.   u32Temp /= X[i+1]-X[i];, ^% d! Z/ v* L2 R. x9 q- R2 Q
  45. ) o5 V3 j3 f, h3 |# q; ~/ j
  46.   return (uint16_t) u32Temp;
    " l' J( _4 ~2 B  q3 _4 ?9 b
  47. }. n7 P& F/ P: A0 b; G
复制代码

) H  H4 N* n! G+ G0 f6 a, S, O5 L0 |" s% d- p: b) b: h$ b
9 h; f+ K, f4 v* p4 D0 v
  M6 ^% `$ g' {  v, \4 P/ H+ ^1 }
3 O; K$ Z6 \% t* u) `' t  A
收藏 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 手机版