ADC电量检测方案


1. 需求概述
1.1 目的
  • 提高ADC采样的准确性,消除板级差异。
1.2 背景
  • 实现采集的电压信息准确,覆盖电池容量0~100。
  • 在进入充电或退出充电时,消除跳跃大的电量跳变。
  • 保证各样品之间的一致性,消除板级间差异。
1.3 定义
  • kR:Adc分压网络的电阻系数比
  • kV:Adc参考电压与精度的系数比
  • k:分压网络电阻系数与adc参考电压的乘积
1.4 参考资料

ADC采样电路

2. 问题分析
2.1 采样原理
kR = 1 + R21 / R20

已知R21 = 2.2M,R20 = 1.5M,计算理论值 kR = 2.467。

Vbat = kR * Vdet

考虑R21和R20存在1%误差,则:

kRmax = 1 + (1.01*R21) / (0.99*R20) = 1.012kR
kRmin = 1 + (0.99*R21) / (1.01*R20) = 0.988kR

假设adc的基准电压为Vref,精度为Prec,adc采集到的adc数值为AdcValue,则:

kV = Vref /Prec
Vdec = kV * AdcValue
Vbat = kR * kV * AdcValue

仅考虑采样电阻的偏差

VbatMax = 1.012Vbat;
VbatMin = 0.988Vbat;
2.2 误差影响

如下表,为某型号电池电压与电量的对应关系

电压 电量 电压 电量 电压 电量 电压 电量 电压 电量
3.001 0 3.219 1 3.333 2 3.416 3 3.474 4
3.517 5 3.547 6 3.572 7 3.587 8 3.599 9
3.608 10 3.616 11 3.622 12 3.628 13 3.634 14
3.643 15 3.648 16 3.655 17 3.660 18 3.665 19
3.669 20 3.674 21 3.678 22 3.682 23 3.686 24
3.690 25 3.693 26 3.695 27 3.698 28 3.701 29
3.704 30 3.707 31 3.709 32 3.712 33 3.714 34
3.717 35 3.719 36 3.721 37 3.725 38 3.728 39
3.730 40 3.733 41 3.736 42 3.739 43 3.743 44
3.746 45 3.749 46 3.753 47 3.757 48 3.761 49
3.765 50 3.770 51 3.774 52 3.779 53 3.783 54
3.787 55 3.792 56 3.797 57 3.802 58 3.808 59
3.813 60 3.818 61 3.824 62 3.830 63 3.836 64
3.842 65 3.848 66 3.855 67 3.861 68 3.868 69
3.874 70 3.881 71 3.889 72 3.897 73 3.904 74
3.912 75 3.919 76 3.927 77 3.934 78 3.943 79
3.952 80 3.960 81 3.968 82 3.978 83 3.988 84
3.997 85 4.007 86 4.017 87 4.027 88 4.036 89
4.045 90 4.055 91 4.064 92 4.074 93 4.084 94
4.095 95 4.105 96 4.116 97 4.128 98 4.141 99

如下图,为该型号的电池曲线
电量百分比
从图中可看出,当电量在30%附近时变化最缓慢,取实际电池电压为3.7V时

VbatMax = 1.012Vbat = 1.012 * 3.7 = 3.7444V;
VbatMin = 0.988Vbat = 0.988 * 3.7 = 3.6556V;
VbatMax - VbatMin = 3.744 - 3.6556 = 0.0888V = 88.8mV;

因此不理想的状态下,板级偏差可达88.8mv,此时分别对应的百分比是44%和14%,同一块电池在这两类情况下测量的电量相差达到30%。

3. 方案设计
3.1 校准原理

因为板级之间存在差异,需要校准kA * kV的系数乘积,又

Vbat = kR * kV * AdcValue = kR * Vref / Prec * AdcValue

从上述公式中可知,Adc的精度Prec是固定的,kR * Vref是造成差异性的原因,令

k = kR * Vref

则有

Vbat = k * AdcValue / Prec

在此方案中,因此给定已知的Vbat,则根据采样的adc数值可推出系数k。

3.2 校准接口

读取校准系数

/**
 * @fn Bool ReadAdcCoefficient(DWord *pdwCalibMark, float *pfCoefficient)
 * @brief Read the calibration mark and calibration coefficient of ADC
 * @details If the reading fails, the contents of the passed-in parameters will not be modified
 * @param[in] pdwCalibMark is Memory address of calibration mark
 * @param[in] pfCoefficient is Memory address of calibration coefficient
 * @return TRUE if read successfully, FALSE if not
 * @note None
 * @attention The valid byte of Flash read by this function is 8 lengths
 */
static Bool ReadAdcCoefficient(DWord *pdwCalibMark, float *pfCoefficient)
{
    Bool bRet = TRUE;
    UDat4Byte UDat;
    STFlashPage stFlashPage = {0u};

    //读取Flash的某一页内容 一共64字节
    bRet = FlashReadPage(&stFlashPage, FLASH_PAGE_MIN_NUM);

    //读取成功且长度正确 将读取的校准标记和校准系数进行替换
    if((bRet == TRUE) && (stFlashPage.wLen == 8u))
    {
        *pdwCalibMark = stFlashPage.adwDat[0u];
        UDat.dwDat = stFlashPage.adwDat[1u];
        *pfCoefficient = UDat.fDat;
    }
    //读取失败 保留之前的采样系数
    else
    {
        bRet = FALSE;
    }

    return bRet;
}

写入校准系数

/**
 * @fn Bool WriteAdcCoefficient(Word wAdcCalibValue, float fCalibBatVol)
 * @brief The calibration coefficient is calculated and stored by the incoming adc
 * and the expected voltage value
 * @details If the calculated coefficient is unreasonable, it will not be stored
 * @param[in] wAdcCalibValue: Adc value for calibration
 * @param[in] fCalibBatVol: Voltage for calibration
 * @return Returns TRUE if writing is successful, otherwise returns FALSE
 * @note None
 * @attention The reasonable interval range is adjusted according to the demand
 */
static Bool WriteAdcCoefficient(Word wAdcCalibValue, float fCalibBatVol)
{
    Bool bRet = TRUE;
    UDat4Byte UDat;
    STFlashPage stFlashPage = {0u};

    //通过传入校准的采样值和预期电压值计算校准系数
    UDat.fDat = fCalibBatVol / wAdcCalibValue * ADC_PRECISION;

    //系数在合理范围内
    if((UDat.fDat >= ADC_MIN_COEFFICIENT) && (UDat.fDat <= ADC_MAX_COEFFICIENT))
    {
        stFlashPage.adwDat[0u] = ADC_CALIBRATION_MARK;
        stFlashPage.adwDat[1u] = UDat.dwDat;
        stFlashPage.wLen = 8u;
        bRet = FlashWritePage(&stFlashPage, FLASH_PAGE_MIN_NUM);
    }
    else
    {
        bRet = FALSE;
    }

    return bRet;
}
3.3 上电校准方案

上电给定稳定的校准电源,校准方法如下:

上电读取Flash判断是否已校准?

是:通过给定的输入电压进行校准系数k,将系数k存储到Flash,并标记校准完成;
否:读取校准系数k。

    //读取校准系数
    ReadAdcCoefficient(&g_dwAdcCalibMark, &g_fAdcKRVCoefficient);
    if(g_dwAdcCalibMark != ADC_CALIBRATION_MARK)
    {
        //没有校准过 进入出厂校准模式
        if(WriteAdcCoefficient(ADC_GetSmpleValue(ADC_CHANNEL1, 5u), ADC_FACTORY_CALIB_BAT))
        {
            ReadAdcCoefficient(&g_dwAdcCalibMark, &g_fAdcKRVCoefficient);
        }
    }

优点:

  • 校准一次即可。

缺点:

  • 依赖给定的校准电压,与生产流程息息相关,给定校准电压的一致性决定了系数的可靠性。
3.4 满电校准方案

重新上电时使用默认校准系数k,不需要校准源,满电时自校准,校准方法如下:

每次采样过程中判断是否在充电状态

  • 存储充电过程中采集的最大adcValue值;
  • 如果检测到电压满电,通过已知的满电电压和最大的adcValue值校准系数k;
  • 如果新的校准系数k在合理范围内,则存储校准系数k到内部Flash中。
  1. 存储充电过程中采集的最大adcValue值。
    //从非充满到充满状态时  写入新的采样系数
    if((bIsChgFull == ENABLE) && (g_bChargFull != ENABLE))
    {
        byBatPercent = CHARGED_FULL_BAT;
        //新的系数保存 判断是否在合理范围里 不合理将使用默认的参数
        if(TRUE == WriteAdcCoefficient(s_wMaxAdcVal, ADC_FULL_CALIB_BAT))
        {
            ReadAdcCoefficient(&g_dwAdcCalibMark, &g_fAdcKRVCoefficient);
        }
        s_wMaxAdcVal = 0u;
    }

    //充满状态变化
    if(bIsChgFull != g_bChargFull)
    {
        g_bChargFull = bIsChgFull;
    }

优点:

  • 自动校准系数,不依赖校准电压和生产流程。

缺点:

  • 第一次充满前使用默认系数k,可能是不准的。
3.5 上电或满电校准方案

MCU实现自校准功能,通过上电校准或满电时校准,校准方法如下:

满足上电校准方案逻辑,只允许出厂时校准一次;
满足满电校准方案逻辑,每次满电重新校准。

优点:

  • 自动校准系数,不强制依赖校准电压和生产流程。

缺点:

  • 如果未进行上电校准,第一次充满前使用默认系数k,可能是不准的。
3.6 确保电量呈现步进变化
  • 周期性检测电池容量(30s),根据当前的采集到的电压值,计算电量百分比;
  • 考虑到电量可能检测不到100%的情况,当软件检测到充满时,将电量百分比强制变更为100%;
  • 当处于充电状态时,此次采集的电量百分比大于当前百分比,百分比自增1;
  • 当处于放电状态时,此次采集的电量百分比小于当前百分比,百分比自减1。
    //充电且满足电量百分比在向上变化 每次加1个百分比
    if((bIsCharge == ENABLE) && (byBatPercent > g_byBatteryPercentage))
    {
        g_byBatteryPercentage += 1u;
    }
    //当没在充电 电量百分比只能每次向下掉1个百分比
    else if((bIsCharge == DISABLE) && (byBatPercent < g_byBatteryPercentage))
    {
        g_byBatteryPercentage -= 1u;
    }

优点:

  • 无复杂的滤波方法,效率高。
  • 保证每次变化的电量百分比不超过预期。
  • 对插入充电和拔除充电有比较好的效果。

缺点:

  • 与实际采集有偏差,带延迟。

2021-08-18 李不清的烦恼,总结篇。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐