Ajustando as leituras de um sensor de CO2

Tempo de leitura: 8 minutes

Brincando com o MH-Z19 vi que ele tinha uma saída analógica, além da saída digital através de uma porta serial, e achei interessante brincar com ele caso, por algum motivo, não tivéssemos a porta serial disponível e porque aqueles de nós que estão com Arduino há algum tempo Parece que nos dá mais confiança do que a porta COM.

Então cheguei nele e descobri que a saída analógica não seguia uma regra clara de proporcionalidade com a medição digital direta, então achei interessante fazer um tutorial de como ajustar a leitura em volts para partes por milhão.

Ficou imediatamente claro que não havia fator de conversão linear, e é por isso que me pareceu que entrar em uma sessão sobre como ajustar os valores com uma função polinomial simples poderia ser interessante neste e em outros casos, em que você deseja calibrar a saída de um sensor como este CO2 com outros sensores mais profissionais ou simplesmente certificados.

Parece que chegou a tempo porque vários centros me disseram que estão realizando projetos de medição de CO2 e comprando mais sensores profissionais para calibrar os projetos com os alunos. E é disso que trata este novo tutorial:

 

Sensores de CO2: MH-Z19

  • Use a saída analógica do sensor MH-Z19.
  • Compare a saída analógica e digital do mesmo
  • Mostre um método de ajuste linear de leituras.
  • Veja um exemplo de um ajuste polinomial.

 

Material Necessário

  • Arduino Mega
  • Sensor HX-Z19
  • ProtoBoard

 

Leitura da saída analógica do MHZ19

Muitos dos sensores que costumamos usar no Arduino possuem uma saída analógica proporcional ao valor medido e normalmente nós pro Arduinomers estamos bastante acostumados a usar esse tipo de interface, então é o mais natural para nós.

O MH-Z19 possui uma saída analógica além da saída digital via porta serial e parece natural querer usá-lo vindo de uma antiga tradição de sensores com essas saídas, então me pareceu bastante razoável usá-lo em um de nossos tutoriais . , para que, se por algum motivo você não puder ou não quiser usar uma porta serial, poderá puxar a saída analógica.

Além disso, isso nos permitirá falar de um tópico um pouco mais técnico, que eu queria entrar há algum tempo, que é o ajuste dos sensores para corrigir suas leituras, quando usamos um mecanismo de calibração externo, ou pelo menos menos, referência.

A leitura da concentração de CO2 com o MH-Z19, através da porta serial em ppm (Partes por milhão) e através da saída analógica em volts, nos permite fazer um magnífico exemplo de como ajustar a medição da concentração de gás com o segundo, mantendo a primeiro como referência de calibração.

Certamente, embora o MHZ19 seja auto-calibrado, ele requer um tempo que não tive paciência para deixá-lo, então assumir que a saída digital serial está calibrada como referência é demais para supor, mas… de qualquer forma, nos servirá perfeitamente, perfeito para o exemplo que mais me interessa, que é calcular o ajuste da saída analógica para partes por milhão de gás, usando a saída digital como referência.

O procedimento de ajustar a saída de um sensor para uma referência calibrada é bastante comum e há muito tempo queria falar um pouco sobre isso (não consigo evitar) e se possível, desenvolver um procedimento ou método de uso geral para outras ocasiões e sensores.

Fiquem à vontade, vamos para a bagunça.

 

Leitura da saída analógica e digital do MHZ19

A primeira coisa são as conexões. Repetimos o diagrama da sessão anterior para conectar o MHZ19 ao Arduino MEGA e também adicionamos a conexão da saída analógica do sensor à porta A0 do MEGA:

Agora podemos passar para a parte do programa, que é muito semelhante à que usamos da última vez. Começamos com a biblioteca e definindo uma instância do sensor:

#include <MHZ19.h>
MHZ19 mhz(&Serial1);

Vamos para Setup():

void setup()
{ 
  Serial.begin(115200);
  Serial.println("Starting...");
  Serial1.begin(9600);

  Serial.print("Digital");
  Serial.print(","); 
  Serial.println("Analog");
}

A primeira coisa é definir a velocidade das portas seriais, 115.200 para as mensagens que enviamos para o console (ou plotter serial) e 9.600 para a comunicação com o sensor de CO2. E o que vale comentar é a seguinte linha para finalizar o Setup

Serial.print("Digital"); 
Serial.print(","); 
Serial.println("Anal

Vou querer usar o plotter serial para representar graficamente os valores do homem, em digital (através da porta serial) e em analógico, para os valores que lemos na porta A0, para o que eu quero, coloque alguns rótulos do que é cada coisa no plotter serial.

Para ser sincero, passei muito tempo procurando como exibir vários valores na plotadora serial do Arduino na Internet, sem sucesso, e no final, por puro acaso, encontrei a maneira de fazer isso, que é isso:

  • Imprima uma vez os títulos separados por vírgulas no console,
  • Em seguida, imprima repetidamente os valores, separados por vírgulas na mesma ordem que fizemos com a impressão dos textos.
  • O sistema permite imprimir 3, 4 ou mais valores com cor e etiquetas próprias.
  • Tenho certeza de que está documentado em algum lugar, mas não consegui encontrá-lo.

Com esta primeira linha, simplesmente definimos os rótulos a serem exibidos na plotadora serial e agora podemos ir para loop(), que também não faz muito. Fazemos um pedido para ler os dados

MHZ19_RESULT response = mhz.retrieveData();

E agora se a recepção foi satisfatória

 if (response == MHZ19_RESULT_OK)
 { 
     int Digital = mhz.getCO2();
     int Analog = analogRead(A0) ;

     Serial.print(Digital); 
     Serial.print(","); 
     Serial.println(Analog);
   //Serial.print(F("Temperatura: "));
   //Serial.println( mhz.getTemperature()) ;
   //float F = mhz.getTemperature() ;
   //float C = (F -32) * 5 / 9.0 ;
  } else {
       Serial.print(F("Error, code: "));
       Serial.println(response);
  }
  delay(1000);
}

O último atraso define o tempo entre as leituras e, em um caso real, você provavelmente teria que espaçá-las com mais de um segundo de intervalo.

 

Analisando os Dados

Lembro muito de um professor de laboratório da Uní, que nos dizia que os instrumentos de medida sempre davam uma medida. O problema é que às vezes você não precisa acreditar porque existem mil razões para falsificar as leituras. Um especialista é aquele que calmamente diz ao ler um instrumento que não acredita nele, e de certa forma o resto desta sessão é sobre isso. Vejamos um exemplo gráfico de nossas leituras de sensores:

Aqui vemos como o sensor HXz19 está lendo baixas concentrações de CO2 e de repente um aumento acentuado na concentração que representa o momento em que estou soprando nele para causar o aumento. Mas repare que o sinal analógico não segue um padrão tão acentuado, longe disso,

Pode-se ver com os olhos que o sinal digital não é apenas muito maior em sua reação, mas também nos permite ver que o sinal analógico não é simplesmente uma versão linear em uma escala menor do sinal digital e isso quase certamente significa que temos Temos que ajustar essa saída para dar valores em ppm se quisermos que estejam corretos. A questão agora é como fazer essa correção razoavelmente.

Eu gostaria de tirar os valores de ambas as leituras do console, para que eu possa copiá-los (Basta selecionar e copiar) Então, se repetirmos o experimento com o console, obteremos uma série de valores semelhantes a este

1275,171
1275,170
1288,171
1288,171
1288,171
1288,171
1288,171
………..

E se colarmos todos esses valores em um arquivo de texto e salvarmos com extensão .csv ou separados por vírgulas, podemos importá-los diretamente para o Excel para processá-los.

O resultado que você obterá será algo assim, se você colocar cabeçalhos:

Para calcular a terceira coluna simplesmente calculei a razão da primeira coluna para a segunda, para ver o fator de proporcionalidade e tentar igualar a leitura analógica à digital simplesmente multiplicando-a por uma constante. Mas como esses fatores são diferentes, o que está na célula E4 é a média de todos esses fatores: 8.371.

Segue os dados que usei:

Leitura (programa Arduino, dados csv e planilha excel)

Se eu multiplicar a coluna B, as leituras analógicas, por esse fator médio obtenho a coluna C, que nos permite fazer um gráfico para ver o quão perto estamos do que queremos, tendo como referência a leitura digital (por isso temos peguei os dois)

Você já pode ver que é uma aproximação, embora não muito boa, pois, ao dimensionar a leitura analógica por um fator constante, amplificamos bastante as falhas do conversor analógico-digital do Arduino (que não é dos melhores) e também e vemos que no máximo não é suficiente dar as leituras que deveria, o que tornaria nosso sensor um nojo notável.

Não parece certo usar apenas um fator multiplicador, então vamos usar um ajuste polinomial (nossa, que palavra), mas isso é realmente bobo. A ideia básica é que, se não podemos simplesmente multiplicar por uma constante de modo que:

Digital = a * Analog      // sendo uma constante

Teremos que tentar ajustar a resposta usando uma fórmula polinomial simples de primeiro grau do tipo:

Digital = a * Analog + b

Será suficiente calcular as constantes a e b para que ao fazer o cálculo acima possamos corrigir nossas leituras analógicas para obter um valor razoável em ppm. Ok, legal e como? Bem, é mais fácil do que parece à primeira vista. Mas teremos que jogar o cálculo do ensino médio.

Se eu pegar a série de valores qq2.csv, tenho que procurar alguns valores da área onde nossa correção anterior mais falha, por exemplo

E agora aplicamos matemática básica para gerar um sistema de duas equações com duas incógnitas. Para fazer isso de forma abstrata e se chamarmos PPM1 e PPM2 as leituras digitais do sensor e Analog1 e Analog2 as leituras da porta analógica correspondente, teríamos:

PPM1 = a * Analog1 + b
PPM2 = a * Analog2 + b

Se subtrairmos ambas as equações obtemos:

PPM2 - PPM1 = a * (Analog2 - Analog1)
a = (PPM2 - PPM1) / (Analog2 - Analog1)

Substituindo os valores na fórmula acima temos:

a = (4532 – 1841) / (392 – 208) = 2.691 / 184
a = 14,625

Uma vez conhecido a, calcular b é trivial, pois a partir da primeira equação:

b = PPM1 / (a * Analog1 )
b = 1841 / (14,625 * 208)
b = -1201

Se calcularmos a terceira coluna da planilha com essa aproximação obtemos este gráfico:

Ok, muito bom, mas quais são esses picos de estimativa e por que o sinal digital não é visto? Bem, os picos são uma amplificação dos valores espúrios que estou obtendo do conversor analógico para digital que precisaremos filtrar. Mas se adicionarmos 200 à terceira coluna, o gráfico que obtemos é:

Onde é apreciado que a aproximação através de um polinômio de primeiro grau o prenda e acima, o sinal estimado é simplesmente sobreposto ao sinal medido digitalmente.

  • Com a desagradável exceção dos espúrios que recebe no conversor ADC que teriam que ser filtrados com um buffer de anel por exemplo e que não me atrevo a desenvolver aqui para não abusar da paciência de quem teve paciência para me aturar até aqui.
  • Observe também que estou usando medições de CO2 bastante altas para encontrar os valores altos e seria necessário provar que a estimativa é boa para valores mais baixos, mas sempre podemos usar diferentes coeficientes a e b para diferentes faixas se a estimativa for não satisfatório, ou seja, alguns coeficientes a e b para valores inferiores a 1000 e outros para valores superiores.
  • Por outro lado, detectei um comportamento estranho do sensor quando conectamos o sinal digital e o analógico a ele simultaneamente. As leituras digitais saltam de 600 para 1000 sem pensar um momento. A mesma coisa aconteceu comigo ao conectar o MH-Z19 e um sensor CCS811 ao mesmo ESP32 para este mesmo experimento, mas vi que as leituras digitais são fortemente falsificadas sem realmente entender o porquê.
  • Eu pensei que poderia ser um problema de energia na fonte (de sua falta, sim), mas o problema não melhorou ao conectar uma fonte externa. Então não tenho certeza qual é a causa, mas parece que conectar as saídas digital e analógica varia a impedância do sensor, o que falsifica as medições.
  • O resumo é que você terá que calcular seus próprios coeficientes para que as medições estejam corretas.