C语言 如何更准确地计算LiFePO4 12.8V电池百分比?

dtcbnfnu  于 2023-06-05  发布在  其他
关注(0)|答案(1)|浏览(125)

Grafana Data

static const uint8_t lifepo4[NUM_BATT_READINGS][2] = {
  {144, 100}, {136, 100}, {134,  99}, {133,  90},
  {132,  70}, {131,  40}, {130,  30}, {129,  20},
  {128,  17}, {125,  14}, {120,   9}, {100,   0}
};

int16_t measurements_get_batt_perc(int16_t mv)
{
  int16_t pct = 0;
  int32_t x1, x2, vD, pD;
  int32_t theta;
  if (mv >= lifepo4[0][0]*100)
      pct = lifepo4[0][1]; // cap value at 100%
  else
  {
    for (int i=0; i<NUM_BATT_READINGS-1; i++)
    {
      // put voltages into mV instead of 100s of mV
      x1 = (int32_t)(lifepo4[i][0])*100L;   // Higher value
      x2 = (int32_t)(lifepo4[i+1][0])*100L; // Lower value
      if (mv <= x1 && mv > x2)
      {
        vD = x1-x2;
        pD = (int32_t)(lifepo4[i][1] - lifepo4[i+1][1]);
        if (pD != 0)
          theta = pD*10000/vD;
        else
          theta = 0;
        pct = lifepo4[i][1] - (x1-mv)*theta/10000;
        break;
      }
    }
  }

  return pct;
}

该代码基于下表中的LUT计算电池百分比:

https://www.mobile-solarpower.com/diy-lifepo4-solar-battery1.html
有没有人有一个想法或更好的方法来帮助计算电池百分比?电压随负载变化。是否有已知的公式计算电池百分比与变化的负载等?或者说,融合电流与电压的积分的最佳方法是什么?
电池百分比遵循所提供的图表,但它没有考虑到当前负载,因此没有显示准确的估计值。

exdqitrt

exdqitrt1#

有没有人有一个想法或更好的方法来帮助计算电池百分比?
OP在正确的轨道上。
一些想法:

  • if (mv <= x1 && mv > x2)只需要一个monotonic_function测试。
  • 由于缺乏代码内文档,lifepo4的含义不清楚。
  • 100L进行缩放可能会导致64位数学运算。只需要32位。
  • 考虑四舍五入。
  • 用更好的名字。
  • lifepo4[]驱动BATT_READING_N,而不是相反。
// Untested code!

#include <stdint.h>

// lifepo4[][0] decivolts
// lifepo4[][1] percentage
static const uint8_t lifepo4[][2] = { //
    {144, 100}, {136, 100}, {134, 99}, {133, 90},
    {132, 70}, {131, 40}, {130, 30}, {129, 20},
    {128, 17}, {125, 14}, {120, 9}, {100, 0}};

#define DECIVOLTS2MILLIVOLTS(v)  ((v)*100)
#define BATT_READING_N (sizeof lifepo4/sizeof lifepo4[0])
#define BATT_READING_MIN (DECIVOLTS2MILLIVOLTS(lifepo4[BATT_READING_N-1][0]))
#define BATT_READING_MAX (DECIVOLTS2MILLIVOLTS(lifepo4[0][0]))

int16_t measurements_get_batt_perc(int16_t voltage /* mV */) {
  if (voltage >= BATT_READING_MAX) {
    return 100;
  }

  for (unsigned i = 1; i < BATT_READING_N; i++) {
    int voltage_lo = DECIVOLTS2MILLIVOLTS(lifepo4[i][0]);
    if (voltage >= voltage_lo) {
      int voltage_hi = DECIVOLTS2MILLIVOLTS(lifepo4[i - 1][0]);
      int_least32_t percent_hi = lifepo4[i - 1][1];
      int_least32_t percent_lo = lifepo4[i][1];
      // int percent = (percent_hi - percent_lo)/(voltage_hi - voltage_lo)*(voltage - voltage_lo) + percent_lo;
      int_least32_t numerator = (percent_hi - percent_lo) * voltage
          + voltage_hi * percent_lo - voltage_lo * percent_hi;
      int_least32_t denominator = (int_least32_t) (voltage_hi - voltage_lo);
      // To form a rounded result:
      numerator += denominator / 2;
      return (int16_t) (numerator / denominator);
    }
  }
  return 0;
}

相关问题