伙计们,今天我们将讨论“ 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