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

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

[复制链接]
radio2radio 发布时间:2018-11-25 23:46
本帖最后由 radio2radio 于 2018-11-26 15:51 编辑
( c9 H8 L/ Y9 E6 f
# ]: b: Y9 Y, a0 \) I- D' X虽然这个话题是程序员的基本功,但是,每一次实际使用时都要“重新编程+除错”折腾一番。
* M: q  V& u& u( Y, f5 z于是,萌发了搞一个“通用的”,目的是,下次用到时,拿过来就用。6 v- t. }: r) h" Y1 }4 D
大家看看我的方法是不是最佳的,欢迎提出改进方案。& h$ ?% {$ K  {+ }, J
* \& u1 G0 X) l
由MCU的ADC读到的“真实世界”的数据,0~1023对应10bit的ADC,0~4095对应12bit,0~65535对应16bit。通常,这些数据都要通过简单的数据处理,变换成电压/电流/温度/压力/等等意义明确的数值,用于传输或者显示。7 j1 m! x1 G2 c6 J5 p

, i: X1 e* G! Z2 ]( q2 S* H. H线性插值,就是最最常用的数据处理方法。 直线函数公式:* S4 S3 n5 }: m; x- Z8 Y
My Formula.jpg
" ~2 Q! b6 Z+ I8 v9 i8 J$ A
1 u! g% o& a5 A7 e
  ?8 ?. }4 N0 K* A# b, E/ N* `应用实例,某电池的“电压—容量”测量估算结果,大致如下图所示:% x9 z+ L- x) k- n9 \7 W# ?
BatteryCap vs Data.JPG
4 u) S2 n$ o( C9 T5 R* ^1 |
2 G+ j3 i& U0 S! D" A由曲线上面可以看出,虽然已经有了10组实测数据,但是只要取其中黄色的4组数据,也就是用3段直线进行线性插值,就可以得到很好的“近似结果”。# s$ G% ?! o, g3 V! H
下图,就是用我的“通用线性插值程序”得到的计算结果,看图形,基本上一样的。, H7 ?* b% X$ L% p4 s
(注意,ADC数据所对应的电池电压值,只是测量ADC数据时用可调电源代替电池的外加电压,它们并不参与运算。 直接由ADC数据插值出电池的剩余电量。)
+ _0 C- Y  r0 F# G% U6 i0 p7 T2 B Test result-1.JPG $ n% O$ g0 S, \. g% o

+ u  P7 n) N0 a! Q  H- n: \
' v: h3 z% [- t2 p$ S8 c( v, S. A- H5 P; P
# V+ \( `1 \* h$ m# c9 ]: [4 Q6 P正弦曲线测试实例,使用37个X轴等间隔的数据(每10度一个),线性插值出0-360度的范围一段正弦曲线的结果:9 q9 y3 V3 b) F% P% j" Q5 ~, l# r
(为了提高转换精度,合理的做法是在曲线变化剧烈的部分,密集取点;线性好的部分,少量取点。而不是采用等间隔的方式取点。)
" c( ]' `1 L- E3 E Test result-2.JPG
& P  U9 g- `8 n5 K
* E" r/ }2 z. v( X. R) i' J& V5 G
# ?$ L' {3 {# m5 x  j6 H* H
最后,给出子程序:
( U$ U/ c: J! y需要说明的是,笔者对有符号的整数(int)和浮点数(float)有“原始的抵触”,喜欢使用无符号整数类型(uint)。所以只做出了整数类型的。
! P/ s0 \: L1 S1 N( b
! R- }( ]% F7 m
  1. ' Z' u$ V0 x0 K$ _
  2. //General integer Linear Interpolation
      w/ i) O4 E- k$ X* _3 {' i: a
  3. //) k4 }/ ?8 O9 y) B! Y8 i* v7 G
  4. //setup: uint16_t Y[size] = {Y0, Y1, Y2, , , Ysize-1};; u9 c0 }. H/ h+ z4 \0 {& r6 P
  5. //setup: uint16_t X[size] = {X0, X1, X2, , , Xsize-1};
    # b9 m* @. J+ _
  6. // - Two Arrays in integer format, Unsigned, no negative values.
    ( N* G$ r5 p* b3 j5 V! ~
  7. // - X[0]<X[1]<X[2]......<Xn, must increasing.% v) E, r" s8 F9 M0 S

  8. ' Z' B* q4 ?& G- _$ o, t
  9. //Test data-1, battery capacity:" W4 f3 h( P5 q" }+ _3 {3 }" Z& K0 V
  10. const uint16_t X[] = {31778, 33442, 39398, 40421};# |+ s' v8 n' A
  11. const uint16_t Y[] = {0,     29,    94,    100  };
    ) X, P& u9 M, H0 Z

  12. * J4 j+ P0 l8 O
  13. //Test data-2, sine wave:* n. ]# O! F! k6 Z7 B" @+ i
  14. //const uint16_t X[] = {0,10,20,30,40,50,60,70,80,90,
    1 W/ F. h4 w3 L1 s
  15. //                      100,110,120,130,140,150,160,170,180,190,) N0 [5 x( f9 ?- Z7 j" }) {4 A- W
  16. //                      200,210,220,230,240,250,260,270,280,290,
    * _- g( P" ]1 o9 O$ W5 V
  17. //                      300,310,320,330,340,350,360};
    9 K# W: Z7 |0 q8 Q3 X
  18. //const uint16_t Y[] = {2000,2174,2342,2500,2643,2766,2866,2940,2985,3000,
    ) Z- }2 g1 b) t1 ^1 v
  19. //                      2985,2940,2866,2766,2643,2500,2342,2174,2000,1826,. G# W8 n9 V, A) o$ u0 X
  20. //                      1658,1500,1357,1234,1134,1060,1015,1000,1015,1060,
    . l- a1 w/ s5 i) m; H- |8 J9 {" O* ~) l1 J
  21. //                      1134,1234,1357,1500,1658,1826,2000};
    8 C6 c9 a8 z4 w- S8 C% O' K

  22. 4 ]' Z: R7 J6 e4 y; S6 r# V
  23. ( z6 f3 j4 A2 q; D$ H$ ^4 b4 j
  24. uint16_t u16LinearInterpolation(uint16_t xdata)# [% I! R7 M/ w& V0 @; R2 l
  25. {% V. T  I: H% c( P# d: H. J2 ?
  26.   uint32_t u32Temp;
    ( |3 R8 ?; o- r6 C& w
  27.   int i,size;
    8 v4 O/ {6 K% d/ k8 q" u1 w/ ]
  28.   
    2 ^& t. ~# q, r/ |; i  N
  29.   size = sizeof(X)/2; //get the array numbers, uint16_t occupied 2 bytes.
    & I7 R3 Z+ h8 E1 N
  30.   , B5 C2 W9 V9 @$ f
  31.   if (xdata <= X[0]) return Y[0];8 d* @8 n8 Z; e7 |! E. N1 v
  32.   if (xdata >= X[size-1]) return Y[size-1];
    3 p- |( q) H3 Q9 h  u
  33.   4 q, b3 w' N' @
  34.   for (i=0; i<(size-1); i++)( m' n& s& S$ c1 S0 a
  35.   {
    * W  u: g* _! S4 v; A4 W
  36.     if ((xdata >= X[i]) && (xdata < X[i+1])) break;   
    * [; H% Y, a* j& e. E
  37.   }9 W0 p9 |" `7 f4 k( G
  38.   
    6 R- ]6 [& e+ V1 L! b, _
  39.   if ((xdata == X[i]) || (Y[i] == Y[i+1])) return Y[i];
    / u, S' M/ R4 |( \9 d$ P8 {3 W; a
  40.   
    / Z* J5 Z! B" q* k8 `" K
  41.   //Y(x)=[Yi*(Xi+1-x)+Yi+1*(x-Xi)]/(Xi+1-Xi). g& R2 b) Z+ B1 Z' n
  42.   u32Temp = Y[i]*(X[i+1]-xdata);0 T0 o( C, h, K, n- T0 V
  43.   u32Temp += Y[i+1]*(xdata-X[i]);: C4 `6 m& @$ ^) M# h* U( Y7 c
  44.   u32Temp /= X[i+1]-X[i];8 w  f- |" E/ k1 T4 a& B1 ]/ f4 W
  45. / Z; M. \* C0 i0 P5 `$ ]: g7 a2 f9 j+ G
  46.   return (uint16_t) u32Temp;
      _0 X/ ~2 J8 ^; h6 ?
  47. }6 v3 X$ d* f4 f4 J7 c5 N
复制代码

: M- g) v$ ^- `- L: J' ], V) ?) v
! {! }5 F% M5 E4 ?9 b) p

  m; O  p" j8 }) ?- `( |) r7 g- p' k
收藏 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 手机版