ESP32 ADC自动校准

伙计们,今天我们将讨论“ ESP32 ADC自动校准 ”。这似乎是一个非常技术性的主题,但我发现您对此有所了解非常重要。这是因为它不仅是ESP32,甚至不是ADC校准,还与您可能要阅读的模拟传感器有关。大多数传感器不是线性的,因此让我们介绍一个用于数字模拟转换器的自动校准器原型。尽管如此,让我们通过为ESP32执行AD修复来进行实验。

使用资源

·杜邦线

·1个面包板

·1个ESP WROOM 32   DevKit

·1条USB线

·2个10k电阻

·1个6k8电阻器或1x 10k机械电位计,用于分压器调整

·1个X9C103-10k数字电位器

·1个LM358运算放大器

使用电路

在该电路中,LM358是处于“电压缓冲器”配置的运算放大器,隔离了两个分压器,以使它们不会相互影响。由于R1和R2可以很好地近似于RB,因此可以简化表达式。

输出电压随数字电位计变化X9C103

根据电路的表达式,这是将数字电位器从0更改为10k时其输出的电压曲线。

控制X9C103

·要控制我们的X9C103数字电位器:

·我们将以5V电压为它供电,该电压来自为ESP32供电的同一USB,并以Vcc连接。

·我们将UP / DOWN引脚连接到GPIO12。

·我们将引脚INCREMENTALLY连接到GPIO13。

·我们在GND上连接DEVICE SELECT(CS)和Vss。

·我们将VH / RH连接到5V电源

·我们将VL / RL连接到GND。

·我们将RW / VW连接到电压缓冲器输入。

连接数

示波器捕获上升和下降斜坡

我们可以观察到ESP32代码生成的两个斜坡。

斜率值将被捕获并发送到C#软件,以评估和确定校正曲线。

预期与已读

改正

让我们使用误差曲线来校正ADC。为此,我们将使用C#编写一个包含ADC值的程序。它将计算读取值与期望值之间的差,从而根据ADC值创建ERROR曲线。

知道此曲线的行为,我们将知道错误并可以对其进行纠正。

要知道这条曲线,C#程序将使用一个执行多项式回归的库(就像先前视频中所做的那样)。

预期与校正后读取

C#程序执行

等待来自斜坡的START消息

ESP32源代码-校正函数示例及其使用

 {  // OBS: TROCAR A VÍRGULAS POR PONTOS CASO SEJA NECESSÁRIO.return 108.441301852859
         + 0.406040363240515 * x
         + -0.000518376038637707 * x * x
         + 2.75596287776397E-07 * x * x * x
         + -5.11930314783709E-11 * x * x * x * x
         + -8.55999917386865E-16 * x * x * x * x * x
         + 6.96385006018707E-19 * x * x * x * x * x * x;
}

与先前技术的比较

ESP32源代码

const int PinUD = 12; //pino responsável pela direção de contagem (UP ou DOWN)
const int PinAD = 34; //pino de leitura do ADC
const int intervalo = 100; //intervalo entre cada coleta de dados
const int larguraDoPulso = 100; //duração do nível baixo e do nível alto do pulso de incremento/decremento
const int numeroDeAmostras = 200; //número de amostras coletadas para cálculo do valor médio (ameniza ruídos)
 
void setup()
{
  Serial.begin(250000); //inicial a serial
  pinMode(PinINC, OUTPUT);//pino de incremento/decremento como saída
  pinMode(PinUD, OUTPUT); //pino de direção da contagem como saída
  pinMode(PinAD, INPUT); //pino do ADC como entrada
 
  digitalWrite(PinINC, LOW); //inicia o pino de incremento/decremento em nível baixo
  digitalWrite(PinUD, HIGH); //inicia o pino de direção como alto (Alto para incremento)
  delay(5000); //aguarda 5 segundos
}

声明和setup()

const int PinUD = 12; //pino responsável pela direção de contagem (UP ou DOWN)
const int PinAD = 34; //pino de leitura do ADC
const int intervalo = 100; //intervalo entre cada coleta de dados
const int larguraDoPulso = 100; //duração do nível baixo e do nível alto do pulso de incremento/decremento
const int numeroDeAmostras = 200; //número de amostras coletadas para cálculo do valor médio (ameniza ruídos)
 
void setup()
{
  Serial.begin(250000); //inicial a serial
  pinMode(PinINC, OUTPUT);//pino de incremento/decremento como saída
  pinMode(PinUD, OUTPUT); //pino de direção da contagem como saída
  pinMode(PinAD, INPUT); //pino do ADC como entrada
 
  digitalWrite(PinINC, LOW); //inicia o pino de incremento/decremento em nível baixo
  digitalWrite(PinUD, HIGH); //inicia o pino de direção como alto (Alto para incremento)
  delay(5000); //aguarda 5 segundos
}

loop()

{
  long medida = 0; //variável que armazenará a medidaint contadorDeAmostras = 0; //variável para contagem de amostras
 
  while (contadorDeAmostras < numeroDeAmostras) //Enquanto a contagem de amostras for menor que o número de amostras definidas...
  {
    contadorDeAmostras++; //incrementa o número de amostras
    medida = medida + analogRead(PinAD); //Lê um valor e acumula na variável medidas
  }
 
  medida = medida / numeroDeAmostras; //encontra a média das medidas amostradas//medida = medida + f(medida); //usado quando a função de correção estivel pronta
 
  if ((medida == 0) && !(digitalRead(PinUD)))// se é o início da rampa...
  {
    digitalWrite(PinUD, HIGH);//define Alto para incrementar
    Serial.println("INICIO"); //envia uma mensagem indicando o início da rampa de subida
 
  }
   
  Serial.println(medida);//envia a medida
   
  if (medida >= 4095)//Se o máximo valor foi obtido ...
  {
    digitalWrite(PinUD, LOW);//define baixo para iniciar a curva de descida.
    Serial.println("FIM"); //envia uma mensagem de fim da rampa de subidaint i = 0; //cria um indice temporário para decrementar o contador interno do X9C103while (i <= 100)//enquanto o número de pulsos for menor ou igual a 100...
    {
      i++;//incrementa o contador de pulsos
      pulso();//executa um pulso
    }
  }
  pulso(); //executa um pulso
  delay(intervalo); //aguarda o intervalo entre as medidas
}

Pulso()

当前内容已被隐藏,您需要登录才能查看

C#程序源代码

C#程序执行

图书馆

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.IO.Ports;
using MathNet.Numerics;

命名空间,类和全局变量

{
     public class PortChat//definição da classe
     {
          static bool _continue; //variável sinalizadora de continuidade do programastatic SerialPort _serialPort; //variável que receberá o objeto que representa a porta serialstatic List medidas = new List(); //lista para recebimento das medidas enviadas pelo ESP32

regPol()

{
       const int degree = 6; //define o grau para o polinômio resultante
        
       int tamanhoY = medidas.Count();//determina o número de medidas recebidas pelo tamanho da lista 'medidas'if (tamanhoY < 1) return;//se o tamanho for menor que 1, algo deu errado, saia . . .
 
       double[] x = new double[tamanhoY];//cria uma matriz para os valores x da função, como o tamanho da listadouble[] y = new double[tamanhoY];//cria uma matriz para os valores y da função, como o tamanho da lista
 
       int indice = 0; //cria um indice temporáriodouble incremento = 4095.0 / tamanhoY; //divide o intervalo do ADC pelo número de medidas realizadas//esse valor e o índice determinarão a reta de referência.foreach (double item in medidas) //para cada valor na lista 'medidas'...
       {
 
             x[indice] = item; //...armazene a medida no matriz x...
             y[indice] = (indice * incremento) - item;//...e determine o seu ERRO para armazenar na matriz y
             indice++; //incremente o índice
 
       }

       //de regressão polinomial disponível em MathNet.Numerics//Mais informações sobre esta biblioteca, visite:// https://www.mathdotnet.com/var p = Fit.Polynomial(x, y, degree); //a variável 'p' contém os coeficientes do polinômio
 
       Console.WriteLine();//salta uma linha
 
       //monta a string com a função e o polinomio já para ser copiada para o código do usuáriostring str = "double f(double x)\n {\n\treturn " +
       p[0].ToString() + "\n\t + " +
       p[1].ToString() + " * x\n\t + " +
       p[2].ToString() + " * x * x\n\t + " +
       p[3].ToString() + " * x * x * x\n\t + " +
       p[4].ToString() + " * x * x * x * x\n\t + " +
       p[5].ToString() + " * x * x * x * x * x\n\t + " +
       p[6].ToString() + " * x * x * x * x * x * x;\n}";
 
       //imprime a string montada, substituindo as virgulas por pontos 
       Console.WriteLine(str.Replace(",", "."));
 
       medidas.Clear(); //limpa a lista medidas
       Console.ReadKey(true); //aguarda pressionar de uma tecla
}

@文章来源·fernandok

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论