Lado escuro MH-Z19

O que de novo? Quanto você pode?

Sim, hoje falaremos novamente sobre o nosso amado sensor de dióxido de carbono Winsen MH-Z19. Não, não haverá repetições *.



* quase

Como você deve ter notado, histórias de horror sobre os perigos de altas concentrações de CO2 na sala aparecem regularmente nas páginas deste recurso. E embora as alegações de que concentrações acima de 1000 ppm carreguem o inferno e a morte sejam um pouco exageradas (a Wikipedia diz que pelo menos alguns efeitos começam com 1%, ou seja, 10.000 ppm, enquanto o sensor tem toda a faixa de 5000 ppm) - o CO2 pode servir como um indicador da presença de outras coisas ruins devido à ventilação insuficiente. Portanto, eu também decidi me juntar ao mundo fascinante da CO2-metry e me apossar do sensor mencionado.

A primeira coisa, é claro, eu o conectei ao arduino. Copiei (com as alterações necessárias) o código do artigo , os números estimados apareceram na tela.

Mas enquanto eu o copiava, uma minhoca de dúvida surgiu em minha alma - por que esse sensor forneceu nove bytes e apenas dois bytes foram responsáveis ​​por CO2? Talvez ele queira me dizer outra coisa?

Uma pesquisa na Internet me levou a uma página tão interessante . O autor experimenta o MH-Z19 e revela sua reação a comandos não documentados (e documentados). Ele ainda não tentou todas as equipes, então ainda há espaço para a nossa parte se divertir. É isso que faremos.

Antes de tudo, trataremos da equipe "clássica" 0x86 (ou simplesmente 134), com a qual obtemos a concentração de CO2. Relatórios do Revspace:

Uma resposta ao comando 0x86 geralmente se parece com isso:
0xFF CM HH LL TT SS Uh Ul CS
onde
CM é o comando repetido de volta
HH / LL é o valor de CO2 ppm, parte alta / baixa
TT é a temperatura em graus Celsius, mais 40. Por exemplo, quando a temperatura é de 25 graus C, TT = 0x41
SS é algum tipo de byte de status, esse byte sempre tem apenas um bit definido!
Uh / Ul é algum valor desconhecido, talvez relacionado à pressão? Depois de inicializar o sensor, ele inicia exatamente às 15000 e, em seguida, geralmente se instala em cerca de 10500.
Cs é a soma de verificação

Ou seja, a resposta do sensor a esse comando também contém a temperatura T (deslocada em 40 graus) e dois valores de destino desconhecidos - um byte S e dois bytes U. S recebe valores de dois graus e U, quando o sensor inicia, cai de 15.000 para pouco mais de 10 000

Como entender o que os números S e U significam? Claro, você precisa desenhar um gráfico! Em qualquer situação incompreensível, desenhe um gráfico.

Detalhes técnicos maçantes
E para desenhar um gráfico, seria bom direcionar as leituras do sensor para um computador. O que fiz com Serial.println (). A cada cinco segundos, o arduin examina o sensor e grava suas leituras no USB-UART, tudo o que resta é lê-las no computador e salvá-las em um arquivo. Eu faço isso (no Linux) assim:

rlwrap cat | cu -l /dev/ttyACM0 > sensor_$(date '+%Y%m%d_%H%M%S').log 


Não chute
Sim, eu sei que você pode fazer apenas cat / dev / ttyACM0> .., mas por algum motivo isso nem sempre funciona para mim, às vezes esse comando termina imediatamente em silêncio. Também gosto do comando fornecido (rlwrap cat | cu -l / dev / ttyACM0) porque permite que você se comunique convenientemente com o microcontrolador no modo interativo (embora isso não seja necessário neste caso). Certamente existem ferramentas melhores para esse fim, mas, infelizmente, eu não as conheço.

Em outra janela do terminal, você pode assistir a este arquivo em tempo real:

 tail -f sensor_.log 

Acontece que uma folha de números:

 ... 1188 62 64 42 38 10790 1188 62 64 42 38 10790 1190 62 64 42 38 10790 1191 62 64 42 38 10790 1192 62 64 42 38 10790 1193 62 64 42 38 10790 1195 62 64 42 38 10790 ... 

Cada linha contém CO2, T, S, U (U é repetido duas vezes - como dois bytes e um número de dois bytes, não pergunte o porquê).

Agora você pode criar gráficos. Eu farei isso com o ipython --pylab.

 y = map(lambda a: map(int, a.split()), open("sensor1.log", "r").readlines()) #     ,     ,    yt = transpose(y) x = arange(len(yt[0])) / 720. #    ,        figure() plot(x, yt[0]) # CO2 figure(); plot(x, yt[1], "g"); # T figure(); plot(x, yt[2], "r"); # S figure(); plot(x, yt[-1], "m"); # U 


Então, o gráfico de CO2:

Em princípio, parece ser verdade. Tristes apenas explosões periódicas. Parece que isso ocorre porque o sensor está simplesmente deitado sobre a mesa e, com a menor brisa, suas leituras são perdidas.

Temperatura:

O momento em que abri a janela é claramente visível. Pivôs de 1 a 2 graus, o que não é ruim para uma oportunidade não documentada. No entanto, se recordarmos o princípio do sensor NDIR , podemos entender que não se deve esperar grande precisão do termômetro embutido. Esses instrumentos medem a absorção de luz na faixa do infravermelho distante, e a boa e velha lâmpada de Ilyich é usada para gerar essa luz, e você pode até ver através das janelas como ela se ilumina a cada cinco segundos (um momento assim é detectado no KDPV). E essa lâmpada consome muita energia e, como resultado, aquece todo o sensor, e quanto ele aquece depende da conjuntura momentânea dos fluxos de ar.

Abordamos o mais interessante. Valor S:

Não diz nada? Eu também Com o luto, desenhamos CO2 e S no mesmo gráfico e aumentamos ligeiramente:

Sim! Agora está tudo claro! Quando tudo está bem, S é 64, e quando o sensor de CO2 começa a salsicha, ele cai para 4. Portanto, você pode usar S para descobrir como o sensor se sente e qual a precisão de suas leituras.

Resta, como dizem os pára-quedistas, o valor extremo é U:

Infelizmente, um truque de sobreposição faz pouco aqui. É visível apenas que, como o revspace prometeu, no início é igual a 15.000 e depois cai para pouco mais de 10.000 (mas pode cair um pouco depois de muito tempo). E uma vez por dia o ciclo se repete.

Mas quando conectei a potência do sensor não a 5, mas a 3,3 volts de arduino, a situação mudou:

3,3 volts no arduino são retirados do chip LP2985, que é um estabilizador linear de 160 miliamperes. E a lâmpada, a julgar pelos artigos na Internet, come tanto. Ao olhar para o sensor, é perceptível que a lâmpada com esta fonte de energia acende mais tempo do que em cinco volts. E o valor de U é uma vez e meia maior.

A hipótese a seguir emerge - o sensor determina automaticamente quanto tempo leva para acender a lâmpada para obter radiação infravermelha suficiente e, se não houver corrente suficiente, queima a lâmpada por mais tempo. E o valor de U reflete apenas o tempo de queima da lâmpada (ou algum outro valor relacionado, por exemplo, a energia gasta).

Para testar essa suposição, alimentamos o sensor a partir de uma bateria de íons de lítio, que obviamente pode produzir uma corrente muito maior:

De fato, U às vezes cai abaixo de 10.000! No entanto, isso obviamente não é uma prova absoluta e, após 24 horas, tudo se torna quase o oposto. Portanto, a hipótese permanece apenas uma hipótese, mas não criei nada melhor.

UPD: Caro unsvp resolveu o enigma do valor U. Dou a ele a palavra:

o valor de U é obviamente o valor mínimo da absorção medida de CO2 por dia, em algumas unidades de medida internas.

Nada a acrescentar, exceto que a programação:

Por que eu não pensei nisso? Tudo é simples. Desenhei um gráfico de quatro valores de uma vez e resolvi isso. Mas era necessário desenhar duas quantidades (como na figura acima), para que o lixo estranho em face da magnitude S não interferisse na percepção. Não repita meus erros.

Talvez eu acrescente o seguinte: você vê um passo maior que 1000 ppm em 48 horas? Este sensor é calibrado automaticamente. Nesse caso, o valor de U caiu em comparação com o que era antes da calibração. Considerando que é óbvio que a concentração real de CO2 durante esse período apenas aumentou. A conclusão disso é muito simples - o valor U não é um valor de absorção muito "bruto", mas já está calculado ajustado para a calibração atual, aparentemente representando alguma diferença nas leituras mínimas nos ciclos de calibração atual e anterior.

Em geral, na minha opinião, a calibração automática (pelo menos na forma em que é implementada no MH-Z19) é ruim. O Revspace diz que pode ser desabilitado usando o comando 0x79: ABC logic on / off.

/ UPD

Bem, com uma equipe resolvida. É hora de ir mais longe, e o artigo está chegando ao fim e outras 255 equipes não foram testadas!

No artigo revspace, a lista de comandos testados termina assim:

comando 0x89-0x8F
Nenhuma resposta é retornada, no entanto, o comando 0x8d parece redefinir o sensor.

comando 0x99 (intervalo)
...

Além disso, as equipes com números mais baixos não são todas verificadas. Assim, pouco mais da metade do número total de equipes desconhecidas permanece.

Sem mais delongas, decidi dar comandos aleatoriamente (mais precisamente, pseudo-aleatoriamente). E aqui está o que eu tenho:

 ... Command: 255 1 47 0 0 0 0 0 208 Response: 0 0 0 0 0 0 0 0 0 CRC: 00 CO2/t/s/u: 0 0 0 0 Command: 255 1 17 0 0 0 0 0 238 Response: 0 0 0 0 0 0 0 0 0 CRC: 00 CO2/t/s/u: 0 0 0 0 Command: 255 1 45 0 0 0 0 0 210 Response: 0 0 0 0 0 0 0 0 0 CRC: 00 CO2/t/s/u: 0 0 0 0 Command: 255 1 5 0 0 0 0 0 250 Response: 0 0 0 0 0 0 0 0 0 CRC: 00 CO2/t/s/u: 0 0 0 0 Command: 255 1 88 0 0 0 0 0 167 Response: 0 0 0 0 0 0 0 0 0 CRC: 00 CO2/t/s/u: 0 0 0 0 Command: 255 1 245 0 0 0 0 0 10 Response: 0 0 0 0 0 0 0 0 0 CRC: 00 CO2/t/s/u: 0 0 0 0 Command: 255 1 107 0 0 0 0 0 148 Response: 0 0 0 0 0 0 0 0 0 CRC: 00 CO2/t/s/u: 0 0 0 0 Command: 255 1 214 0 0 0 0 0 41 Response: 0 0 0 0 0 0 0 0 0 CRC: 00 CO2/t/s/u: 0 0 0 0 Command: 255 1 136 0 0 0 0 0 119 Response: 0 0 0 0 0 0 0 0 0 CRC: 00 CO2/t/s/u: 0 0 0 0 Command: 255 1 7 0 0 0 0 0 248 Response: 0 0 0 0 0 0 0 0 0 CRC: 00 CO2/t/s/u: 0 0 0 0 Command: 255 1 153 0 0 0 0 0 102 Response: 255 153 1 0 0 0 0 0 102 CRC: 102102 CO2/t/s/u: 256 0 0 0 Command: 255 1 146 0 0 0 0 0 109 Response: 0 0 0 0 0 0 0 0 0 CRC: 00 CO2/t/s/u: 0 0 0 0 Command: 255 1 72 0 0 0 0 0 183 Response: 96 249 2 211 215 212 17 215 204 CRC: 159204 CO2/t/s/u: 723 215 212 4567 Command: 255 1 51 0 0 0 0 0 204 Response: 93 151 80 143 212 255 255 255 217 CRC: 185217 CO2/t/s/u: 20623 212 255 -1 Command: 255 1 98 0 0 0 0 0 157 Response: 16 136 252 75 66 50 48 48 13 CRC: 9313 CO2/t/s/u: -949 66 50 12336 Command: 255 1 65 0 0 0 0 0 190 Response: 10 0 0 0 0 0 0 0 0 CRC: 0 0 CO2/t/s/u: 0 0 0 0 Command: 255 1 243 0 0 0 0 0 12 Response: 0 0 0 0 0 0 0 0 0 CRC: 0 0 CO2/t/s/u: 0 0 0 0 Command: 255 1 13 0 0 0 0 0 242 Response: 0 0 0 0 0 0 0 0 0 CRC: 0 0 CO2/t/s/u: 0 0 0 0 Command: 255 1 35 0 0 0 0 0 220 Response: 0 0 0 0 0 0 0 0 0 CRC: 0 0 CO2/t/s/u: 0 0 0 0 Command: 255 1 229 0 0 0 0 0 26 Response: 0 0 0 0 0 0 0 0 0 CRC: 0 0 CO2/t/s/u: 0 0 0 0 Command: 255 1 95 0 0 0 0 0 160 Response: 0 0 0 0 0 0 0 0 0 CRC: 0 0 CO2/t/s/u: 0 0 0 0 Command: 255 1 48 0 0 0 0 0 207 Response: 0 0 0 0 0 0 0 0 0 CRC: 0 0 CO2/t/s/u: 0 0 0 0 Command: 255 1 209 0 0 0 0 0 46 Response: 0 0 0 0 0 0 0 0 0 CRC: 0 0 CO2/t/s/u: 0 0 0 0 Command: 255 1 200 0 0 0 0 0 55 Response: 0 0 0 0 0 0 0 0 0 CRC: 0 0 CO2/t/s/u: 0 0 0 0 ... 

Aqui Command é o que foi enviado ao sensor (o número do comando em si é o terceiro número desde o início), Response é o que o sensor respondeu, você não pode olhar para o resto (CRC é a soma de verificação calculada / real, CO2 / t / s / u é o resultado da quebra resposta do sensor a quatro números, como se estivesse respondendo a um comando "padrão").

Como você pode ver, não muito. Além disso, a partir de algum ponto, o sensor recusou-se completamente a fornecer algo além de zeros. A última coisa que obtive do sensor foi:

 Command: 255 1 134 0 0 0 0 0 121 Response: 0 0 0 0 0 0 0 0 0 CRC: 0 0 CO2/t/s/u: 0 0 0 0 Command: 255 1 130 0 0 0 0 0 125 Response: 242 98 200 201 207 216 178 130 33 CRC: 50 33 CO2/t/s/u: -14135 207 216 -19838 Command: 255 1 134 0 0 0 0 0 121 Response: 204 91 151 80 143 212 255 255 236 CRC: 93 236 CO2/t/s/u: -26800 143 212 -1 Command: 255 1 200 0 0 0 0 0 55 Response: 181 156 252 77 79 68 66 85 83 CRC: 241 83 CO2/t/s/u: -947 79 68 16981 Command: 255 1 134 0 0 0 0 0 121 Response: 13 10 0 0 0 0 0 0 0 CRC: 246 0 CO2/t/s/u: 0 0 0 0 Command: 255 1 216 0 0 0 0 0 39 Response: 0 0 0 0 0 0 0 0 0 CRC: 0 0 CO2/t/s/u: 0 0 0 0 

E depois zeros. Tentei digitar comandos sequencialmente, começando com 0x8e - novamente zeros. Eu tentei dar o comando "padrão" 0x86 - zeros. Eu matei o sensor? Na verdade, todas as condições estão presentes - insiro pequenos comandos não documentados, portanto também conecto a interface do sensor diretamente ao arduino de cinco volts, embora a folha de dados diga explicitamente que foi projetada para 3,3 volts.

Primeiro de tudo, tentei a boa e velha receita de qualquer enikeyshchik - desligue e ligue novamente. Ou seja, ele o retirou e o prendeu no sensor, além de poder, com todo o resto funcionando. O sensor produziu aproximadamente o mesmo que na última passagem citada (mas com números ligeiramente diferentes). Sim, isso significa que o sensor não morreu completamente e diz algo em cada bota, adivinhou os shtirlits.

Depois dei um pouco mais ao meu cérebro e adivinhei antes de uma verdade - os zeros que vimos acima não são a resposta do sensor. De fato, o sensor está silencioso e meu programa desenha o que a função Arduin de receber n bytes forneceu (para dizer zeros). E, todas as vezes antes da recepção, para garantir que haja algo a ser feito, acontece que não há nada para aceitar. Exceto nos casos em que o sensor acabou de reiniciar.

Acontece que o sensor parou completamente de aceitar qualquer comando. Aparentemente, 5 volts na interface serial não foram em vão. Sim, o artigo não perguntou de alguma forma. Obrigado a todos pela atenção. Nós discordamos, não há nada para olhar.

Oh espera ...

Vê esses números no final?

 13 10 

Não se parece com nada?

Obviamente, este é um bom e velho feed de linha ! Em outras palavras, 0x0D 0x0A - esta é a maneira de traduzir uma string, por exemplo, no Windows (e no Unix, eles facilitam - 0x0A, porque alguns arquivos perdem quebras de linha quando abertos em um notebook do Windows).

Então, talvez o sensor queira nos dizer algo na linguagem humana? No entanto, se esse idioma for chinês, não vai me ajudar muito. Então, esperamos que essa seja uma linguagem mais compreensível e decodifique a mensagem de acordo com a tabela ASCII :

 print reduce(lambda a, b: a + b, map(lambda a: chr(int(a)), "255 255 255 250 24 220 207 254 77 79 68 66 85 83 13 10".split()))         MODBUS 

Recebeu até seis letras. E aqui está o que o mesmo sensor disse ao carregar um pouco mais cedo:

 print reduce(lambda a, b: a + b, map(lambda a: chr(int(a)), "96 249 2 211 215 212 17 215 204 93 151 80 143 212 255 255 255 217 16 136 252 75 66 50 48 48 13 10 ".split())) `        ] P         KB200 

A diferença é óbvia - a linha KB200 mudou para a linha MODBUS. O resto - parece que não é de todo texto, nem mesmo caracteres chineses - nem que seja porque a maioria deles muda de tempos em tempos.

Então, o que o sensor nos diz? A pedido do KB200, uma pesquisa na Internet produz um teclado, um amostrador de núcleo, um ferro, uma mesa de troca, um controlador de controle de câmera PTZ, um mixer, exceto um careca. Bem, mas não está claro como aplicar esse conhecimento ao nosso caso. Bem, vamos procurar o MODBUS. Desta vez, a própria Wikipedia está ao nosso serviço:

O Modbus é um protocolo de comunicação aberto baseado na arquitetura mestre-escravo. É amplamente utilizado na indústria para organizar as comunicações entre dispositivos eletrônicos. Pode ser usado para transmitir dados através das linhas de comunicação serial RS-485, RS-422, RS-232, bem como uma rede TCP / IP (Modbus TCP).

A própria hipótese se sugere - após um dos comandos não documentados, o sensor mudou para o protocolo Modbus e agora nos informa isso usando os métodos disponíveis. Como não há outras opções previstas, faremos um teste direto dessa hipótese, ou seja, vamos tentar entrar em contato com o sensor via Modbus.

Na Internet, foi encontrada uma implementação Modbus para arduins. Mas isso é uma má sorte - o Arduino Leonardo não é suportado, mas por acaso monstruoso apenas Leonardo.

Mas, como logo percebi, isso é até o melhor. O protocolo Modbus é tão simples quanto três moedas de um centavo. E, além de dolorosamente semelhante ao protocolo "nativo" MH-Z19. Então, por que arrastar coisas desagradáveis ​​da Internet e entendê-las dolorosamente quando você pode implementar tudo o que precisa em dois minutos (bem, duas horas)?

Então, antes, nós, querendo descobrir as leituras, pedimos ao sensor que as emitisse da seguinte forma:

 0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79 

Ou em decimal:

 255, 1, 134, 0, 0, 0, 0, 0, 121 

Onde 255 é o número mágico, 1 é o endereço do sensor, 134 é o comando, 121 é o byte da soma de verificação.

E como será no Modbus? Não haverá correspondência exata, mas você pode fazer, por exemplo, o seguinte:

 1, 4, 0, 0, 0, 4, 213, 197 

1 - endereço do sensor.

4 - número da equipe. Os comandos no Modbus podem ser contados nos dedos, e até agora estaremos interessados ​​em apenas dois deles - 3 e 4. Por razões ocultas no escuro dos séculos, eles são chamados de Read Multiple Holding Registers e Read Input Registers, mas na verdade eles dão um comando para ler um determinado o número de números de byte duplo em um determinado endereço. O comando 3 lê os números disponíveis para leitura / gravação e o comando 4 lê apenas.

0, 0 é o endereço que vamos ler (neste caso, 0). Se você definir o mesmo endereço com uma equipe de 3 ou 4, geralmente obteremos resultados diferentes.

0, 4 - o número de números que queremos ler (neste caso, 4). Há um momento engraçado aqui. Embora você possa especificar esse número até 65535, na verdade, o protocolo permite que você não leia mais de 125 números por vez. E tudo porque a resposta indica o número de bytes das informações enviadas e são necessários apenas um byte (e os números são de dois bytes). Além disso, pelo que entendi, o tamanho da resposta em si é limitado a 255 bytes.

213, 197 - dois bytes de uma soma de verificação ( CRC16 ). Em geral, este é o momento mais difícil de toda a nossa implementação. Na verdade, eu nem me aprofundei em como isso é considerado, mas simplesmente copiei o código daqui . Como existe um mar de CRC16s diferentes, é preciso abordar com responsabilidade a escolha da função. Você pode verificar se uma função específica é adequada para o Modbus, por exemplo, aqui .

Isso, de fato, é tudo o que precisamos saber sobre o Modbus. Pelo menos para começar.

Embora você adivinhe há muito tempo que meu apelo ao MH-Z19 no Modbus foi um sucesso, mas vamos fingir que a intriga persiste. Até o momento, nem sabemos qual é o endereço do nosso sensor (embora "no original" seja 1, está longe de ser o mesmo no Modbus). Portanto, você precisa repetir o comando com endereços diferentes (e existem apenas 255) e ver a que nosso sensor responderá:

 ... Command: 254 4 0 3 0 1 213 197 CRC: 213 197 Response: Command: 255 4 0 3 0 1 212 20 CRC: 212 20 Response: Command: 0 4 0 3 0 1 192 27 CRC: 192 27 Response: Command: 1 4 0 3 0 1 193 202 CRC: 193 202 Response: Command: 2 4 0 3 0 1 193 249 CRC: 193 249 Response: 1 132 2 194 193 Command: 3 4 0 3 0 1 192 40 CRC: 192 40 Response: Command: 4 4 0 3 0 1 193 159 CRC: 193 159 Response: ... 

Parece que o endereço é 2. Repito vários comandos com o endereço 2 - não há resposta. Eu mudo o endereço para 1 - há uma resposta! Assim, o endereço do sensor é o mesmo que era - 1.

E por que a passagem 2 obteve o endereço 2? Aqui, novamente, a Hinduness do meu código se arrasta. Depois de emitir o comando, verifico se existem bytes a serem recebidos. Mas como eu faço isso imediatamente, o sensor não tem tempo para enviar nada; portanto, a resposta do sensor é aceita pelo programa apenas no próximo ciclo. Como você pode ver no log fornecido - o primeiro número na resposta é 1 e apenas indica o endereço do sensor. Para contornar esse problema, basta adicionar um atraso de 50 milissegundos antes de receber uma resposta.

Considere a resposta do sensor ao nosso comando:

 1 132 2 194 193 

1 - como já descobrimos - o endereço do sensor.

132 - código de comando e código de erro. Se não houvesse erro, esse número seria o mesmo que o comando enviado - ou seja, 4. Mas como ocorreu um erro, conforme indicado pelo bit mais significativo definido como 1, o número passou a ser 4 + 128 = 132. Portanto, a propósito, um comando no Modbus não pode ter um número maior que 127 - para esse comando, o código de sucesso seria o mesmo que o código de erro.

2 - código de erro. Diz exatamente qual erro ocorreu. Como a Wikipedia diz, 02 - O endereço de dados especificado na solicitação não está disponível. Portanto, não há peixe neste endereço e não há nada para capturar. Vamos tentar outros endereços.

194 193 - CRC16.

Agora, finalmente, é hora de arranhar o espaço de endereço do sensor para entender onde está o peixe. Fiz isso com simplicidade - enviei um comando para ler um número com um novo endereço a cada 0,1 segundos. Como os endereços são 65536, esse processo é concluído em aproximadamente duas horas. Os resultados são brevemente os seguintes:

Comando 1 (Read Coils) - erro 2 em qualquer endereço.
Comando 2 (Ler entradas discretas) - com qualquer erro de endereço 2.
Comando 4 (Read Input Registers) - erro 2 com qualquer endereço.
Equipe 3 (Read Multiple Holding Registers) - obtém sucesso nos endereços de 0 a 289.
Os comandos para escrever valores (por exemplo, 6) parecem funcionar, mas parece que o valor registrado é substituído em breve pelo que era. Mas não investiguei esse problema de perto.

Portanto, o círculo de pesquisa se estreita - precisamos de números no comando 3 e endereços de 0 a 289. A idéia do rico mundo interno do sensor pode ser obtida a partir destas linhas:

 Command: 1 3 0 0 0 64 68 58 CRC: 68 58 Response: 1 3 128 0 0 0 255 0 1 0 1 0 255 0 255 0 255 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 158 124 Command: 1 3 0 64 0 64 69 238 CRC: 69 238 Response: 1 3 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 27 165 Command: 1 3 0 128 0 64 69 210 CRC: 69 210 Response: 1 3 128 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 73 82 0 153 0 8 0 17 0 177 0 19 0 19 0 196 0 18 0 20 0 214 0 18 0 21 0 232 0 18 0 22 0 250 0 5 0 24 0 255 0 5 0 18 1 4 0 3 0 23 1 7 0 25 0 0 0 0 0 0 0 0 0 0 0 255 0 255 0 1 0 0 0 5 0 0 0 0 0 0 0 0 0 0 137 122 Command: 1 3 0 192 0 64 68 6 CRC: 68 6 Response: 1 3 128 165 165 0 165 0 0 255 255 255 255 255 255 255 255 0 15 3 232 0 100 0 90 0 0 0 63 128 0 0 255 0 15 0 5 0 10 0 5 0 5 0 30 0 15 0 0 0 20 0 40 0 60 0 80 0 100 0 0 0 5 0 5 3 232 255 255 255 255 165 165 0 165 0 0 16 3 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 163 198 

É verdade que os números foram salvos no arquivo morto apenas no endereço 255. Aqui, novamente, 1 3 é o endereço e o comando, 128 é o número de bytes transferidos, dois bytes no final são CRC e todo o resto é o conteúdo da memória.

De todo esse esplendor, estamos obviamente interessados ​​nos endereços cujo conteúdo muda com o tempo. E aqui o sensor acabou sendo duas novidades para mim - boas e más. Bom - existem esses endereços. E os ruins - existem apenas dois deles - 261 e 264. Compare com a "vida passada", quando quatro números foram dados em um comando ao mesmo tempo! Eu já rolei meu lábio - pensei em ter acesso a todas as variáveis ​​internas. Bem, dois e dois.

Hora de criar gráficos novamente!

Valor no endereço 261:

Parece uma concentração de CO2. Isso pode ser visto quando tentei respirar no sensor. É verdade que o valor mínimo fica visivelmente mais baixo que a "referência" 400 ppm, portanto a calibração deixa muito a desejar. De uma forma ou de outra, o sensor é declarado ressuscitado.

Valor em 264:

praticamente o mesmo, apenas em uma escala diferente e de cabeça para baixo.

E ambas as quantidades estão no mesmo gráfico:

Uma questão natural surge - talvez uma dessas quantidades seja o valor "bruto" que vem do ADC e que o sensor converte na estimativa de CO2 usando o método escravo? Nesse caso, isso abre grandes oportunidades para recalibrar e melhorar a precisão do sensor, e talvez para usá-lo para outros fins. A resposta para esta pergunta (e algumas outras), tentaremos entrar na próxima série.

Os comentários e sugestões são aceitos - como zombar do MH-Z19 no próximo artigo. É verdade que não prometo nada.

Source: https://habr.com/ru/post/pt401363/


All Articles