adc 读取精度 ATMEGA

Posted

技术标签:

【中文标题】adc 读取精度 ATMEGA【英文标题】:adc read accuracy ATMEGA 【发布时间】:2021-12-20 23:35:45 【问题描述】:

我正在尝试使用 ATMEGA328P 读取一组 6 个 Lifepo4 电池,我正在努力将 10 位值转换为电压。

我正在与 TL431 电压参考进行比较,使用我的万用表读数为 5.005 伏

每个 adc 引脚正在读取一个分压电阻对,120k 接地,510k 到每个电池,它的工作电压范围约为 26v 到 5v

我已经尝试过无数次从引脚值到电压的转换,它们总是以接近但超出比例而告终,我不明白为什么。

    #define AREF 501        /* 2 decimal places */
    #define maxVoltage 2630 /* 2 decimal places */

    // read the ADC pin value
    pinValue_Bank1[cellIndex] = analogRead(MPLEX_COM.Pin);

    // convert the pin value to a voltage
    //pinVoltage_Bank1[cellIndex] = ((uint32_t)pinValue_Bank1[cellIndex] * maxVoltage / 1024) * AREF / 500;
    pinVoltage_Bank1[cellIndex] = ((((uint32_t)pinValue_Bank1[cellIndex] * 100)+50) * maxVoltage / 102400) * AREF / 500;

结果是一个带 2 位小数的 int16

+50 将每个值移动 0.5,因为 0 和 1 之间的读数可能是 0v 和 0.0256v 之间的任何电压,我的目标是中间(实际上并没有太大区别)

比较 ATMEGA 和万用表的读数

 MULTIMETER     ATMEGA
 3.468v          3.41v
 6.940v          6.91v
10.440v         10.39v
13.560v         13.55v
24.950v         24.95v

电压读数较低的电池读数偏低,我不明白为什么。

我的转换公式完全错误吗

【问题讨论】:

pinValue_Bank1的数据类型是什么?它是长、双、整数吗? AREF 是什么? 也许我的袖珍计算器坏了,但我看到的差异不到 1%。出了什么问题?万用表还是您使用 ADC 进行的测量?抱歉,大约 5% 是相当不错的。请记住:您的电阻器也可能有 1%,并且 ADC 上存在电噪声和一些非线性。但是你已经得到了 @kiner_shah pinValue_Bank1 是 uint16_t。 AREF 是一个#defined 编译时间常数 @Klaus 谢谢,我认为万用表很好,如果错误,它在 0 到 60v 范围内给我的读数与我的台式电源相同,我的台式电源也是如此,我认为电噪声是好,我有 100uf 上限,关于如何改进结果的任何建议,我写了一个校准偏移量,它在闪存中存储一​​个字节来抵消这个问题,但我宁愿不必校准每个单元除非别无他法,否则这是一个 80v 电池和 3700 节电池运行我的车辆,校准单个电池将是最后的手段 ` * maxVoltage / 102400) ` 我认为除法运算符将优先。您可能需要先乘然后除。尝试将 maxVoltage 放入 () 【参考方案1】:

请注意,您始终可以确定非线性并将其拟合到二/三/四次方程。 从许多板上获取电压读数并绘制结果。 然后对展开进行多项式拟合并将系数应用于您的代码。

例如:

#define ZERO_ORDER_COEFFICIENT 0.25f
#define FIRST_ORDER_COEFFICIENT 1.1f
#define SECOND_ORDER_COEFFICIENT .53f

// read the ADC pin value
pinValue_Bank1[cellIndex] = analogRead(MPLEX_COM.Pin);

// convert the pin value to a voltage
pinVoltage_Bank1[cellIndex] = ((((uint32_t)pinValue_Bank1[cellIndex] * 100)+50) * maxVoltage / 102400) * AREF / 500;

// apply second order equation to minimize error
pinVoltage_Bank1[cellIndex] = SECOND_ORDER_COEFFICIENT * pinVoltage_Bank1[cellIndex] * pinVoltage_Bank1[cellIndex] + FIRST_ORDER_COEFFICIENT * pinVoltage_Bank1[cellIndex] + ZERO_ORDER_COEFFICIENT;

polyfit 可以帮助减少您在硬件中看到的平均错误的传播。

【讨论】:

【参考方案2】:

排除过程我发现了问题。

代码和公式都没有错。

错误在于电池的接线不良。

在我的台式电源使用 120k / 510k 电阻分压器对成功实现 0.03v 增量读数高达 26v 后,我将电线直接点焊到电池上,它工作正常。

我尝试了 5 块相同印刷的不同电路板来检查组件之间的公差,它看起来相当不错(尽管板上的所有组件都可能来自同一批次的下一个由贴片机从色带上取下来的组件,所以我'我不确定测试有多好)

附注是确保 AREF 引脚上有良好的电容,尽可能靠近芯片,我也有快速读取值导致 REF 波动的问题,直到我将电容从 10uf 增加到 100uf,我猜另一种选择是降低为 TL431 基准供电的电阻,但这样会消耗更多功率

我猜你不能相信电池盒中的蹩脚弹簧端子能够建立良好的连接。但如果你下定决心,使用 10 位 ADC 可以获得相当不错的结果。

工作代码如下

#define AREF 501        /* 2 decimal places */
#define maxVoltage 2642 /* 2 decimal places */
uint16_t adcValue = analogRead(pin);
uint16_t voltage = ((((uint32_t)adcValue * 100)+50) * maxVoltage / 102400) * AREF / 500;

结果是 int16,有 2 位小数。

+50 假设每个读数都比来自 adc 的每个读数大 0.5,目标是每个范围内可能值的中间

【讨论】:

以上是关于adc 读取精度 ATMEGA的主要内容,如果未能解决你的问题,请参考以下文章

stm32的ADC功能。读取的是模拟量么?转化为数字量输出?

STM32 ADC详解

STM32中的内置ADC精度分析

单片机提高ADC精度总结

单片机提高ADC精度总结

提高C8051F350中ADC精度应注意的一些问题