ADC电量检测方案
目录
1. 需求概述
1.1 目的
- 提高ADC采样的准确性,消除板级差异。
1.2 背景
- 实现采集的电压信息准确,覆盖电池容量0~100。
- 在进入充电或退出充电时,消除跳跃大的电量跳变。
- 保证各样品之间的一致性,消除板级间差异。
1.3 定义
- kR:Adc分压网络的电阻系数比
- kV:Adc参考电压与精度的系数比
- k:分压网络电阻系数与adc参考电压的乘积
1.4 参考资料
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中。
- 否
- 存储充电过程中采集的最大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 李不清的烦恼,总结篇。