0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

ADC的读取调整

454398 来源:网络整理 作者:网络整理 2019-11-13 09:03 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

步骤1:什么是AD转换器

AD转换器是一种能够将模拟(连续)量转换为数字(离散)值的电路。这意味着什么?这意味着尽管数字值只能假设零和一的组合所形成的离散值,但模拟量可以假设范围内的任何值。例如,如果我们测量理想AA电池的电压,则可以找到0V至1.5V之间的任何值,因为这是模拟量。理想灯的输出状态必须仅假设两个状态(关闭或打开),这是一个离散的幅度。由于微控制器使用这种离散逻辑工作,因此我们需要一种能够将模拟量转换为数字量(或离散量)的电路。

步骤2:使用的资源

•一根Lolin32 Lite卡v1.0.0

•一台用于捕获的Tektronix TDS1001C示波器

•一根用于ESP32USB电缆

•将Hantek DSO4102C示波器用作信号发生器

步骤3:ESP32 ADC

根据Espressif数据,ESP32芯片可能在测量结果中,从一个芯片到另一个芯片的误差为+/- 6%。

此外,该转换对于每个可用的读取范围都没有线性答案。乐鑫提供了一种校准方法,建议用户在认为有必要达到所需精度时采用其他方法。

我们将进行数据采集,并从中显示ADC响应和应用数学过程读取调整的示例。

有几种(更简单或更复杂的)方法可以完成这些修正。由您决定最适合您的项目。

此处显示的内容具有说明性目的,并尝试解决在调整过程中可以观察到的有趣点。

步骤4:使用的电路

我使用了示波器,其信号发生器的频率高达25 MHz,即Hantek DSO4102C。我们产生了由ESP A/D和示波器读取的波形。收集的数据记录在csv和电子表格中,我将在文章末尾进行下载。

第5步:使用过的符号

我们选择了一个低频梯形信号,该信号可以访问整个转换范围内的斜坡。

步骤6:示波器获得的数据

捕获由示波器执行。数据存储在csv文件中。请注意信号的上升和下降斜率上的轻微弯曲。

步骤7:示波器获得的数据(Excel中的csv文件)

我们在这里进行采样。

步骤8:ADC获得的数据

通过更改传输串行速率,我们可以查看ADC捕获的数据。观察梯形信号的变形。

Arduino IDE串行绘图仪上观察到的数据

步骤9:ADC获得的数据-Excel

使用更高的速率和串行终端,我们可以捕获值并将其应用到Excel中进行比较。

步骤10:爬坡的比较

我们比较两个挡块的两个攀登坡道。

请注意两个坡道上出现的曲率。

请注意同样,对于相同的斜坡,ESP32的采样数要比示波器多。

步骤11:计算采样数

由于ESP32提供的样本数量比示波器多,因此我们需要将这些值均等化,因为它们将用作比较两条曲线的指标。

为此,我们将进行直接比较。

我们有305个示波器斜坡样本和2365个ADC斜坡样本。

因为这些斜坡属于在相同的范围内,可以说每个示波器大约有7.75个ADC采样。

将每个示波器采样的索引乘以相同的曲线,但是索引等于ADC和重新分配的数据。

要填充新职位的缺失数据,我们将应用一条曲线,以统计方式拟合已知数据。

步骤12:填补空白-趋势线

选择已知数据(蓝点),方法是单击,然后用右键单击,我们选择:“添加趋势线。. 。”

在出现的窗口中,我们选择多项式类型(阶数2就足够了。)

我们还选中了“在图表中查看方程式”和“显示”图表中的R平方值”。

我们单击“关闭”。

步骤13:填补空白-2级多项式曲线

Excel为我们提供了两条新信息:

请记住,距离1越近,方程越合适。

我们不需深入研究所涉及的数学,而仅将其用作工具即可。

步骤14:填补空白-评估函数

让我们填补用等式生成的数据在采样间隙中。然后,逐点比较它们。

y = -9E-08x2 + 0,0014x + 0,1505

R²= 0 ,9999

示波器电压= -9E-08 * index2 + 0,0014 * index + 0,1505

步骤15:将示波器电压转换为等效值以与ADC进行比较

让我们利用这一点还将示波器电压的值转换为等效ADC

由于在ESP32的ADP中获得的最高值为4095,相当于相同索引的2.958V读数,我们可以这样说:

每个示波器的测量电压大约等于AD的1384.4单位。因此,我们可以将示波器的所有测量值乘以该值。

步骤16:比较获得的两个斜坡

可视化

步骤17:ADC读数差异的行为(错误)

下面的曲线显示了ADC读数的差异如何随测量变化的行为。通过收集这些数据,我们可以找到校正函数。

要找到此曲线,我们只需绘制每个度量中的差异作为每个可能AD位置(0至4095)的函数即可。

p》

步骤18:ADC读取差异行为-查找校正函数

我们可以在Excel中通过添加趋势线来确定校正函数,现在已达到较高的程度,直到它完全适合我们的数据为止。

步骤19:使用其他软件

用于确定曲线的其他有趣软件是PolySolve,可直接在以下链接上使用:https://arachnoid.com/polysolve/或作为Java应用程序下载

它允许应用高级多项式回归和格式化函数以及其他功能的交付。

要使用它,只需在第一行文本中输入数据即可。框。数据必须遵循X,Y的顺序,并以逗号或制表符分隔。请谨慎使用正确的点作为小数点。

如果正确设置了输入数据的格式,则会在下一个框中显示一个图表。

这是我们ADC误差曲线的变化方式。

此窗口将显示回归的结果,包括函数充足性数据,该数据可以用几种方式格式化其输出:作为C/C ++函数,系数列表,函数

注意:注意小数点分隔符

步骤20:常量和设置()

I在此处指出用于模拟捕获的GPIO。我初始化了串行端口以及用于模拟捕获的引脚。

const int pin_leitura = 36; //GPIO usado para captura analógica

void setup() {

Serial.begin(1000000); //Iniciciando a porta serial somente para debug

pinMode(pin_leitura, INPUT); //Pino utilizado para captura analógica

}

步骤21:循环()和校正函数

我们会捕获调整后的电压,然后打印带有或不带有正确校正的值。

void loop() {

int valor_analogico = analogRead(pin_leitura); //realiza a captura da tensão ajustada

//Serial.print(valor_analogico + f(valor_analogico)); //imprime os valores para debug (COM CORREÇÃO)

Serial.print(valor_analogico); //imprimime os valores para debug (SEM CORREÇÃO)

Serial.print(“,”);

Serial.print(4095);//cria uma linha para marcar o valor máximo de 4095

Serial.print(“,”);

Serial.println(0); //cria uma linha para marcar o valor mínimo de 0

}

第12行中的通知中,我们可以选择使用

步骤22:使用PolySolve校正函数

在这里,我们在Arduino IDE内部使用PolySolve函数

/*

Mode: normal

Polynomial degree 6, 2365 x,y data pairs

Correlation coefficient (r^2) = 9,907187626418e-01

Standard error = 1,353761109831e+01

Output form: C/C++ function:

Copyright © 2012, P. Lutus -- http://www.arachnoid.com. All Rights Reserved.

*/

double f(double x) {

return 2.202196968876e+02

+ 3.561383996027e-01 * x

+ 1.276218788985e-04 * pow(x, 2)

+ -3.470360275448e-07 * pow(x, 3)

+ 2.082790802069e-10 * pow(x, 4)

+ -5.306931174991e-14 * pow(x, 5)

+ 4.787659214703e-18 * pow(x, 6);

}

注意逗号分隔作为小数点分隔符。

步骤23:带有校正的捕获-绘图仪序列

步骤24:计算成本

要执行多项式计算,处理器必须处理此任务。这可能会导致执行延迟,具体取决于源代码和可用的计算能力。

在这里,我们看到了使用多项式多项式的测试结果表。注意使用pow()函数的时间与不使用pow()函数的时间之间的时差。

步骤25:测试代码-设置()和循环启动()

在这里,我们有测试中使用的代码。

void setup() {

Serial.begin(1000000); //Iniciando a porta serial somente para debug

}

void loop() {

float valor_analogico = 500.0; //um valor arbtrario

float quantidade = 10000.0; //quantidade de chamadas

float contador = 0.0; //contador de chamadas

步骤26:测试代码-循环()和处理

我使用了micros()函数来获取以微秒为单位的值。

//============= inicia o processo

float agora = micros(); //marca o instante inicial

while (contador 《 quantidade) {

//v(valor_analogico); //função vazia

//r(valor_analogico); //função com retorno

//f0(valor_analogico); //grau 0

//f1(valor_analogico); //grau 1

//f2(valor_analogico); //grau 2

//f3(valor_analogico); //grau 3

//f4(valor_analogico); //grau 4

//f5(valor_analogico); //grau 5

//f6(valor_analogico); //grau 6

//f13_semPow(valor_analogico); //grau 13º SEM a função POW

//f13_comPow(valor_analogico); //grau 13º COM a função POW

contador++;

}

agora = (micros() - agora) / quantidade; //determina o intervalo que se passou para cada iteração

//============= finaliza o processo

步骤27:测试代码-循环()-结果

我们打印从13级函数返回的值(带有和不带有POW进行比较)以及处理间隔。

//imprime o valor retornado da função de grau 13 com e sem POW para comparação

Serial.print(f13_semPow(valor_analogico)); //grau 13º SEM a função POW

Serial.print(“ - ”);

Serial.print(f13_comPow(valor_analogico)); //grau 13º COM a função POW

Serial.print(“ - ”);

//imprime o intervalo do processamento

Serial.println(agora, 6);

}

步骤28:测试代码-使用的函数

空度为0和1的函数(仅带返回)。

//FUNÇÃO VAZIA

double v(double x) {

}

//FUNÇÃO SOMENTE COM RETORNO

double r(double x) {

return x;

}

//FUNÇÃO DE GRAU 0

double f0(double x) {

return 2.202196968876e+02;

}

//FUNÇÃO DE GRAU 1

double f1(double x) {

return 2.202196968876e+02

+ 3.561383996027e-01 * x;

}

2、3和4级函数。

//FUNÇÃO DE GRAU 2

double f2(double x) {

return 2.202196968876e+02

+ 3.561383996027e-01 * x

+ 1.276218788985e-04 * pow(x, 2);

}

//FUNÇÃO DE GRAU 3

double f3(double x) {

return 2.202196968876e+02

+ 3.561383996027e-01 * x

+ 1.276218788985e-04 * pow(x, 2)

+ -3.470360275448e-07 * pow(x, 3);

}

//FUNÇÃO DE GRAU 4

double f4(double x) {

return 2.202196968876e+02

+ 3.561383996027e-01 * x

+ 1.276218788985e-04 * pow(x, 2)

+ -3.470360275448e-07 * pow(x, 3)

+ 2.082790802069e-10 * pow(x, 4);

}

5和6级函数。

//FUNÇÃO DE GRAU 5

double f5(double x) {

return 2.202196968876e+02

+ 3.561383996027e-01 * x

+ 1.276218788985e-04 * pow(x, 2)

+ -3.470360275448e-07 * pow(x, 3)

+ 2.082790802069e-10 * pow(x, 4)

+ -5.306931174991e-14 * pow(x, 5);

}

//FUNÇÃO DE GRAU 6

double f6(double x) {

return 2.202196968876e+02

+ 3.561383996027e-01 * x

+ 1.276218788985e-04 * pow(x, 2)

+ -3.470360275448e-07 * pow(x, 3)

+ 2.082790802069e-10 * pow(x, 4)

+ -5.306931174991e-14 * pow(x, 5)

+ 4.787659214703e-18 * pow(x, 6);

}

使用POW的13级函数。

//FUNÇÃO DE GRAU 13 USANDO O POW

double f13_comPow(double x) {

return 2, 161282383460e+02

+ 3, 944594843419e-01 * x

+ 5, 395439724295e-04 * pow(x, 2)

+ -3, 968558178426e-06 * pow(x, 3)

+ 1, 047910519933e-08 * pow(x, 4)

+ -1, 479271312313e-11 * pow(x, 5)

+ 1, 220894795714e-14 * pow(x, 6)

+ -6, 136200785076e-18 * pow(x, 7)

+ 1, 910015248179e-21 * pow(x, 8)

+ -3, 566607830903e-25 * pow(x, 9)

+ 5, 000280815521e-30 * pow(x, 10)

+ 3, 434515045670e-32 * pow(x, 11)

+ -1, 407635444704e-35 * pow(x, 12)

+ 9,871816383223e-40 * pow(x,13);

}

不使用13级函数POW。

//FUNÇÃO DE GRAU SEM USAR O POW

double f13_semPow(double x) {

return 2, 161282383460e+02

+ 3, 944594843419e-01 * x

+ 5, 395439724295e-04 * x * x

+ -3, 968558178426e-06 * x * x * x

+ 1, 047910519933e-08 * x * x * x * x

+ -1, 479271312313e-11 * x * x * x * x * x

+ 1, 220894795714e-14 * x * x * x * x * x * x

+ -6, 136200785076e-18 * x * x * x * x * x * x * x

+ 1, 910015248179e-21 * x * x * x * x * x * x * x * x

+ -3, 566607830903e-25 * x * x * x * x * x * x * x * x * x

+ 5, 000280815521e-30 * x * x * x * x * x * x * x * x * x * x

+ 3, 434515045670e-32 * x * x * x * x * x * x * x * x * x * x * x

+ -1, 407635444704e-35 * x * x * x * x * x * x * x * x * x * x * x * x

+ 9, 871816383223e-40 * x * x * x * x * x * x * x * x * x * x * x * x * x;

}

责任编辑:wv

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 示波器
    +关注

    关注

    113

    文章

    7123

    浏览量

    196807
  • adc
    adc
    +关注

    关注

    100

    文章

    7946

    浏览量

    556871
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    MPC8378适配程序应该怎么调整

    型号IS43DR16640C-25DBLI,其他物料没有更换,生产调试发现之前的程序不管怎么调试都无法正确读取数据,数据报错,比如程序写的1111,数据读取的是1100,请问我们适配程序应该怎么调整
    发表于 04-01 08:09

    RA MCU众测宝典 | ADC/DAC之【RA2L1】DAC电压输出及ADC电压采集实验

    ,一步步玩转DAC电压输出与ADC电压采集:从12位DAC的引脚配置、ADC的单通道扫描设置,到代码中实现电压值的动态调整与串口打印,一起感受“数字信号转模拟电压
    的头像 发表于 01-20 18:43 5784次阅读
    RA MCU众测宝典 | <b class='flag-5'>ADC</b>/DAC之【RA2L1】DAC电压输出及<b class='flag-5'>ADC</b>电压采集实验

    电力调整器恒压恒流恒功率是什么意思?#电力调整器 #三相电力调整器 #电力调整器工厂

    调整
    苏州合泉仪表科技有限公司
    发布于 :2026年01月13日 08:56:57

    高速ADC:CBM14AD125Q

    ADC
    芯佰微电子
    发布于 :2026年01月09日 15:01:44

    CBM24AD99Q 高精度ADC

    ADC
    芯佰微电子
    发布于 :2025年12月18日 10:57:54

    探索ADC0831-N/ADC0832-N/ADC0834-N/ADC0838-N 8位串行I/O A/D转换器

    转换器。 文件下载: adc0834-n.pdf 关键特性与规格 基本性能 这些转换器具有8位分辨率,能够提供较为精确的模拟到数字的转换。总未调整误差方面,不同型号
    的头像 发表于 12-10 10:55 778次阅读

    ADC 实战:如何精准读取传感器信号

    关键因素。今天,我们就从原理到实战,带你搞懂ADC,帮你精准读取传感器信号。一、ADC基础回顾ADC(Analog-to-DigitalConverter)是将连
    的头像 发表于 11-24 19:04 627次阅读
    <b class='flag-5'>ADC</b> 实战:如何精准<b class='flag-5'>读取</b>传感器信号

    【EK-RA6E2开发指南】ADC获取电压值

    RA6E2有2个ADC单元,每个ADC单元有12位、10位、8位读取数据的格式可以选择,在单元0上有13个ADC通道,而在单元1上有16个ADC
    的头像 发表于 09-23 18:15 2174次阅读
    【EK-RA6E2开发指南】<b class='flag-5'>ADC</b>获取电压值

    怎么用LL命令读取SPI?

    ;hspi1, mrx_data, 3, HAL_MAX_DELAY);命令读取ADC结果3字节,即时优化后也需要1.95us,远远不能匹配ADC的速度。我想也只有LL命令才会快了,测试了很长时间都不成功。 请教怎么用LL命令
    发表于 09-09 08:17

    STM32L152进入STOP模式,WAKEUP by RTC唤醒后ADC读取数值不变了是什么原因导致的?

    如题所示,使用STOP低功耗模式,功耗下来了,STOP模式每次最大只能32秒左右(RTC寄存器满了),所以就循环多次(5分钟就是10次左右)。 启动时读取一次ADC数据(电池电压比如是4.10V
    发表于 07-23 06:09

    使用stm32u575rg通过spi读取外置adc的数据,如何设置才能让spi不需要中断重启持续读取数据?

    我打算使用stm32u575rg通过spi读取外置adc的数据,通过lptim2的ch2提供外置ad的触发信号,ch1提供触发信号给spi1,SPI->TSIZE=1
    发表于 07-10 08:22

    ADC采集精度不良

    ; ADC_EN); // 等待ADC稳定 delay_ms(1); } // 读取ADC值 uint16_t ADC_Read(uin
    发表于 07-09 22:07

    如何使用HAL ADCREAD读取VDDIO?

    ;channel_config); /* 读取相应 ADC 通道的 ADC 转换结果。 */ adc_out = cyhal_adc_rea
    发表于 06-27 06:30

    STM32U575按照历程配置了ADC,参考电压采用默认,Vrefe和VADDA短接,读取的结果为0是怎么回事?

    这是读取的代码 case Q_BATTERY_EVT: extern ADC_HandleTypeDef hadc1; HAL_ADC_Start(&amp;hadc1
    发表于 06-25 06:40

    ADC静态参数全解析:从偏移误差到未调整总误差,一文掌握核心计算!

    ADC性能评估的关键指标如何计算?本文用ADC实例,详解偏移/增益/INL/DNL/TUE六大参数的计算方法,带您掌握从跳变点提取到误差分析的全流程。通过典型ADC数据和交互式图表,直观理解参数间的关联与影响,助您提升测试精度!
    的头像 发表于 06-05 14:50 1209次阅读
    <b class='flag-5'>ADC</b>静态参数全解析:从偏移误差到未<b class='flag-5'>调整</b>总误差,一文掌握核心计算!