Lado Oscuro MH-Z19

Que otra vez Cuanto puedes

Sí, hoy hablaremos nuevamente sobre nuestro querido sensor de dióxido de carbono Winsen MH-Z19. No, no habrá repeticiones *.



* casi

Como habrás notado, las historias de terror sobre los peligros de las altas concentraciones de CO2 en la habitación aparecen regularmente en las páginas de este recurso. Y aunque las afirmaciones de que las concentraciones superiores a 1000 ppm acarrean el infierno y la muerte son un poco exageradas ( Wikipedia dice que al menos algunos efectos comienzan con 1%, es decir, 10,000 ppm, mientras que el sensor tiene el rango completo de 5000 ppm) - CO2 puede servir como un indicador de la presencia de otras cosas malas debido a una ventilación insuficiente. Por lo tanto, también decidí unirme al fascinante mundo de la medición de CO2 y obtuve el sensor mencionado.

Lo primero, por supuesto, lo conecté a Arduino. Copié (con los cambios necesarios) el código del artículo , los números apreciados aparecieron en la pantalla.

Pero mientras copiaba, un gusano de duda se metió en mi alma: ¿por qué este sensor emitió nueve bytes y solo dos bytes representaron CO2 de ellos? Tal vez él quiere decirme algo más?

Una búsqueda en Internet me llevó a una página tan interesante . El autor experimenta con el MH-Z19 y revela su reacción a los comandos indocumentados (y documentados). Todavía no ha probado todos los equipos, por lo que todavía hay espacio para nuestra parte de diversión. Esto es lo que haremos.

En primer lugar, trataremos con el equipo "clásico" 0x86 (o simplemente 134), con el que obtenemos la concentración de CO2. Revspace informa:

Una respuesta al comando 0x86 generalmente se ve así:
0xFF CM HH LL TT SS Uh Ul CS
donde
CM es el comando que se repite
HH / LL es el valor de ppm de CO2, parte alta / baja
TT es la temperatura en grados Celsius, más 40. Por ejemplo, cuando la temperatura es de 25 grados C, entonces TT = 0x41
SS es algún tipo de byte de estado, ¡este byte siempre tiene un solo bit establecido!
Uh / Ul es un valor desconocido, tal vez relacionado con la presión? Después de arrancar el sensor, comienza exactamente a 15000, luego generalmente se establece en aproximadamente 10500.
Cs es la suma de comprobación

Es decir, la respuesta del sensor a este comando también contiene la temperatura T (desplazada 40 grados) y dos valores de destino desconocidos: un byte S y dos bytes U. S toma valores de dos grados, y U cuando el sensor arranca, cae de 15,000 a un poco más de 10 000

¿Cómo entender lo que significan los números S y U? Por supuesto, ¡necesitas dibujar un gráfico! En cualquier situación incomprensible, dibuja un gráfico.

Detalles técnicos aburridos
Y para dibujar un gráfico, sería bueno llevar las lecturas del sensor a una computadora. Lo que hice con Serial.println (). Cada cinco segundos, el arduin sondea el sensor y escribe sus lecturas en USB-UART, solo necesita leerlas en su computadora y guardarlas en un archivo. Hago esto (en Linux) así:

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


No patear
Sí, sé que puede hacer solo cat / dev / ttyACM0> .., pero por alguna razón esto no siempre funciona para mí, a veces este comando termina inmediatamente en silencio. También me gusta el comando dado (rlwrap cat | cu -l / dev / ttyACM0) porque le permite comunicarse convenientemente con el microcontrolador en modo interactivo (aunque esto no es necesario en este caso). Seguramente hay mejores herramientas para este propósito, pero, desafortunadamente, no las conozco.

En otra ventana de terminal, puede ver este archivo en tiempo real:

 tail -f sensor_.log 

Resulta una hoja de números como esta:

 ... 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 línea contiene CO2, T, S, U (U se repite dos veces, como dos bytes y un número de dos bytes, no pregunte por qué).

Ahora puedes construir gráficos. Haré esto con 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 


Entonces, el gráfico de CO2:

En principio, parece ser cierto. Triste solo explosiones periódicas. Parece que esto se debe a que el sensor simplemente está acostado sobre la mesa, y con la más mínima brisa se pierden sus lecturas.

Temperatura:

El momento en que abrí la ventana es claramente visible. Pivotes de 1 a 2 grados, lo que no es malo para una oportunidad indocumentada. Sin embargo, si recordamos el principio del sensor NDIR , podemos entender que uno no debería esperar una gran precisión del termómetro incorporado. Estos instrumentos miden la absorción de luz en el rango del infrarrojo lejano, y la buena bombilla de Ilyich se usa para generar esta luz, e incluso se puede ver a través de las ventanas cómo se ilumina cada cinco segundos (un momento así queda atrapado en el KDPV). Y esta bombilla consume mucha energía y, como resultado, calienta todo el sensor, y cuánto lo calienta depende de la coyuntura momentánea de los flujos de aire.

Nos acercamos a los más interesantes. Valor S:

¿No dice nada? Yo tambien Con pena, dibujamos CO2 y S en el mismo gráfico y aumentamos ligeramente:

Si! ¡Ahora todo está claro! Cuando todo está bien, S es 64, y cuando el sensor de CO2 comienza a producir salchichas, se reduce a 4. Por lo tanto, puede usar S para averiguar qué tan bien se siente el sensor y qué tan precisas son sus lecturas.

Queda, como dicen los paracaidistas, el valor extremo es U:

Desafortunadamente, un truco de superposición hace poco aquí. Solo es visible que, como prometió revspace, al principio es igual a 15,000, y luego cae a un poco más de 10,000 (pero puede caer un poco después de mucho tiempo). Y una vez al día el ciclo se repite.

Pero cuando conecté la potencia del sensor no a 5, sino a 3,3 voltios de arduino, la situación cambió:

3.3 voltios en el arduino se toman del chip LP2985, que es un estabilizador lineal de 160 miliamperios. Y la bombilla, a juzgar por los artículos en Internet, come casi lo mismo. Al mirar el sensor, se nota que la bombilla con esta fuente de alimentación se enciende en más tiempo que a cinco voltios. Y el valor de U es una vez y media más alto.

La siguiente hipótesis surge: el sensor determina automáticamente cuánto tiempo se tarda en encender la bombilla para obtener suficiente radiación infrarroja, y si no hay suficiente corriente, se quema la bombilla más tiempo. Y el valor de U simplemente refleja el tiempo de combustión de la bombilla (o algún otro valor relacionado, por ejemplo, la energía gastada).

Para probar esta suposición, alimentamos el sensor desde una batería de iones de litio, que obviamente puede producir una corriente mucho mayor:

De hecho, ¡U a veces cae por debajo de 10,000! Sin embargo, esto obviamente no es una prueba absoluta, y después de 24 horas, todo se vuelve casi lo contrario. Entonces, la hipótesis sigue siendo solo una hipótesis, pero no se me ocurrió nada mejor.

UPD: Dear unsvp resolvió el enigma del valor U. Le doy la palabra:

El valor de U es obviamente el valor mínimo de la absorción medida de CO2 IR por día, en algunas unidades internas de medida.

Nada que agregar, excepto que el horario:

¿Por qué no pensé en esto yo mismo? Todo es simple Dibujé un gráfico de cuatro valores a la vez y me decidí por esto. Pero era necesario dibujar dos cantidades (como en la imagen de arriba), luego la basura extraña frente a la magnitud S no interferiría con la percepción. No repitas mis errores.

Quizás agregue esto: ¿ve un paso mayor de 1000 ppm a las 48 horas? Este sensor se calibra automáticamente. En este caso, el valor de U cayó en comparación con lo que era antes de la calibración. Mientras que es obvio que la concentración real de CO2 durante este período solo aumentó. La conclusión de esto es muy simple: el valor de U no es un valor de absorción muy "crudo", pero se calcula ya ajustado para la calibración actual, aparentemente representando alguna diferencia en las lecturas mínimas en los ciclos de calibración actuales y anteriores.

En general, en mi opinión, la autocalibración (al menos en la forma en que se implementa en el MH-Z19) es mala. Revspace dice que se puede deshabilitar usando el comando 0x79: ABC logic on / off.

/ UPD

Bueno, con un equipo resuelto. ¡Es hora de ir más allá, y luego el artículo se acerca al final, y otros 255 equipos no han sido probados!

En el artículo revspace, la lista de comandos probados termina así:

comando 0x89-0x8F
No se devuelve ninguna respuesta, sin embargo, el comando 0x8d parece restablecer el sensor.

comando 0x99 (rango)
...

Además, los equipos con números más bajos no están todos verificados. Por lo tanto, queda un poco más de la mitad del número total de equipos desconocidos.

Sin más preámbulos, decidí dar comandos al azar (más precisamente, pseudoaleatoriamente). Y esto es lo que obtuve:

 ... 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 ... 

Aquí el comando es lo que se envió al sensor (el número de comando en sí es el tercer número desde el principio), la respuesta es lo que respondió el sensor, no puede mirar el resto (CRC es la suma de comprobación calculada / real, CO2 / t / s / u es el resultado de la descomposición respuesta del sensor a cuatro números, como si estuviera respondiendo a un comando "predeterminado").

Como puedes ver, no mucho. Además, desde algún punto en adelante, el sensor se negó por completo a dar otra cosa que no fueran ceros. Lo último que obtuve del sensor fue:

 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 

Y luego ceros. Traté de ingresar comandos secuencialmente, comenzando con 0x8e, nuevamente ceros. Traté de dar el comando "estándar" 0x86 - ceros. ¿Maté el sensor? En verdad, todas las condiciones para esto están presentes: ingreso pequeños comandos indocumentados, así que también conecto la interfaz del sensor directamente a la arduina de cinco voltios, aunque la hoja de datos dice explícitamente que está diseñada para 3.3 voltios.

En primer lugar, probé la vieja y buena receta de cualquier enikeyshchik: apáguelo y vuelva a encenderlo. Es decir, lo sacó y lo pegó al sensor más la alimentación con todo lo demás funcionando. El sensor produjo aproximadamente lo mismo que en el último pasaje citado (pero con números ligeramente diferentes). Sí, eso significa que el sensor no murió por completo y dice algo en cada arranque, adivinó los shtirlits.

Luego le di a mi cerebro un poco más y adiviné incluso antes de una verdad: esos ceros que vimos arriba no son la respuesta del sensor en absoluto. De hecho, el sensor está en silencio, y mi programa dibuja lo que dio la función Arduin de recibir n bytes (por ejemplo, ceros). Y si cada vez antes de la recepción para asegurarse de que hay algo para llevar, resulta que no hay nada que aceptar. Excepto en los casos en que el sensor acaba de reiniciarse.

Resulta que el sensor dejó de aceptar por completo cualquier comando. Aparentemente, 5 voltios en la interfaz serial no fueron en vano. Sí, el artículo no preguntó de alguna manera. Gracias a todos por su atención. No estamos de acuerdo, no hay nada que mirar.

Oh espera ...

¿Ves estos números al final?

 13 10 

¿No se parece a nada?

¡Por supuesto, este es un buen avance de línea antiguo! En otras palabras, 0x0D 0x0A: esta es la forma de traducir una cadena, por ejemplo, en Windows (y en Unix lo hacen más fácil: 0x0A, porque algunos archivos pierden saltos de línea cuando se abren en un cuaderno de Windows).

Entonces, ¿tal vez el sensor quiere decirnos algo en lenguaje humano? Sin embargo, si este idioma es chino, no me ayudará mucho. Esperemos que este sea un lenguaje más comprensible, y decodifique el mensaje de acuerdo con la tabla 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 

Recibió hasta seis letras. Y esto es lo que dijo el mismo sensor al cargar un poco antes:

 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 

La diferencia es obvia: la línea KB200 ha cambiado a la línea MODBUS. El resto, parece que no es en absoluto texto, ni siquiera caracteres chinos, aunque solo sea porque la mayoría de ellos cambian de vez en cuando.

Entonces, ¿qué nos dice el sensor? A pedido de KB200, una búsqueda en Internet produce un teclado, un muestreador central, una plancha, una mesa para cambiar pañales, un controlador para controlar cámaras PTZ, un mezclador, excepto uno calvo. Bueno, pero no está claro cómo aplicar este conocimiento a nuestro caso. Bueno, busquemos MODBUS. Esta vez Wikipedia está a nuestro servicio:

Modbus es un protocolo de comunicación abierto basado en la arquitectura maestro-esclavo. Es ampliamente utilizado en la industria para organizar comunicaciones entre dispositivos electrónicos. Se puede utilizar para transmitir datos a través de las líneas de comunicación serie RS-485, RS-422, RS-232, así como una red TCP / IP (Modbus TCP).

La hipótesis en sí misma se sugiere a sí misma: después de uno de los comandos no documentados, el sensor cambió al protocolo Modbus y ahora nos informa de esto utilizando los métodos disponibles. Como no se prevén otras opciones, realizaremos una prueba directa de esta hipótesis, es decir, intentemos contactar al sensor a través de Modbus.

En Internet, se encontró una implementación Modbus para arduins. Pero esta es una mala suerte: Arduino Leonardo no es compatible, pero por casualidad tengo solo Leonardo.

Pero, como pronto me di cuenta, esto es incluso lo mejor. El protocolo Modbus es tan simple como tres centavos. Y además dolorosamente similar al protocolo "nativo" MH-Z19. Entonces, ¿por qué arrastrar cosas desagradables de Internet y comprenderlo dolorosamente cuando puede implementar todo lo que necesita en dos minutos (bueno, dos horas) usted mismo?

Entonces, antes, nosotros, queriendo descubrir las lecturas, le pedimos al sensor que las emita de la siguiente manera:

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

O en decimal:

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

Donde 255 es el número mágico, 1 es la dirección del sensor, 134 es el comando, 121 es el byte de la suma de verificación.

¿Y cómo se verá en Modbus? No habrá una coincidencia exacta, pero puede hacer, por ejemplo, esto:

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

1 - dirección del sensor.

4 - número de equipo. Los comandos en Modbus se pueden contar con los dedos, y hasta ahora solo nos interesarán dos de ellos: 3 y 4. Por razones ocultas en la oscuridad de los siglos, se llaman Leer múltiples registros de retención y Leer registros de entrada, pero de hecho dan una orden para leer un determinado El número de números de doble byte en una dirección determinada. El comando 3 lee los números disponibles para lectura / escritura, y el comando 4 solo lee.

0, 0 es la dirección que vamos a leer (en este caso, 0). Si establece la misma dirección con un equipo de 3 o 4, generalmente obtendremos resultados diferentes.

0, 4 - el número de números que queremos leer (en este caso 4). Hay un momento divertido aquí. Aunque puede especificar este número hasta 65535, de hecho, el protocolo le permite leer no más de 125 números a la vez. Y todo porque la respuesta indica el número de bytes de la información enviada, y solo toma un byte (y los números son de dos bytes). Además, según tengo entendido, la longitud de la respuesta en sí está limitada a 255 bytes.

213, 197: dos bytes de una suma de comprobación ( CRC16 ). En general, este es el momento más difícil en toda nuestra implementación. En verdad, ni siquiera profundicé en cómo se considera, sino que simplemente copié el código desde aquí . Como hay un mar de diferentes CRC16, uno debe abordar de manera responsable la elección de la función. Puede verificar si una función particular es adecuada para Modbus, por ejemplo, aquí .

De hecho, eso es todo lo que necesitamos saber sobre Modbus. Al menos para empezar.

Aunque hace tiempo que adivinó que mi atractivo para el MH-Z19 en Modbus fue un éxito, supongamos que la intriga persiste. Hasta ahora, ni siquiera sabemos cuál es la dirección de nuestro sensor (aunque "en el original" es 1, está lejos de ser el mismo en Modbus). Por lo tanto, debe repetir el comando con diferentes direcciones (y solo hay 255 de ellas) y ver a qué responderá nuestro sensor:

 ... 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 la dirección es 2. Repito varios comandos con la dirección 2: no hay respuesta. Cambio la dirección a 1, ¡hay una respuesta! Por lo tanto, la dirección del sensor es la misma que era - 1.

¿Y por qué el pasaje 2 obtuvo la dirección 2? Aquí, nuevamente, el Hinduness de mi código se arrastra. Después de emitir el comando, verifico si hay bytes para recibir. Pero como hago esto de inmediato, el sensor no tiene tiempo para enviar nada, por lo que el programa solo acepta la respuesta del sensor en el próximo ciclo. Como puede ver en el registro dado, el primer número en la respuesta es 1, y solo indica la dirección del sensor. Eludí este problema simplemente agregando un retraso de 50 milisegundos antes de recibir una respuesta.

Considere la respuesta del sensor a nuestro comando:

 1 132 2 194 193 

1, como ya hemos descubierto, la dirección del sensor.

132 - código de comando y código de error. Si no hubiera ningún error, este número sería el mismo que el comando enviado, es decir, 4. Pero ocurrió un error, como lo indica el bit más significativo establecido en 1, por lo que el número se convirtió en 4 + 128 = 132. Por lo tanto, por cierto, un comando en Modbus no puede tener un número mayor que 127; para dicho comando, el código de éxito sería el mismo que el código de error.

2 - código de error. Dice exactamente qué error ocurrió. Como dice Wikipedia, 02 - La dirección de datos especificada en la solicitud no está disponible. Por lo tanto, no hay peces en esta dirección y no hay nada que atrapar. Intentaremos otras direcciones.

194 193 - CRC16.

Ahora, finalmente, es hora de rascar el espacio de direcciones del sensor para comprender dónde está el pez. Hice esto simplemente: envié un comando para leer un número con una nueva dirección cada 0.1 segundos. Debido a que las direcciones son 65536, este proceso se completa en aproximadamente dos horas. Los resultados son brevemente los siguientes:

Comando 1 (bobinas de lectura): error 2 con cualquier dirección.
Comando 2 (Leer entradas discretas): con cualquier error de dirección 2.
Comando 4 (Leer registros de entrada): error 2 con cualquier dirección.
Equipo 3 (Leer múltiples registros de retención): proporciona éxito en direcciones de 0 a 289.
Los comandos para escribir valores (por ejemplo, 6) parecen funcionar, pero parece que el valor registrado pronto se reemplaza por lo que era. Pero no investigué este problema de cerca.

Entonces, el círculo de búsqueda se estrecha: necesitamos números en el comando 3 y direcciones del 0 al 289. La idea del rico mundo interior del sensor se puede obtener de estas líneas:

 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 

Es cierto, los números se guardaron en el archivo solo en la dirección 255. Aquí, nuevamente, 1 3 es la dirección y el comando, 128 es el número de bytes transferidos, dos bytes al final son CRC, y todo lo demás es el contenido de la memoria.

De todo este esplendor, obviamente estamos interesados ​​en aquellas direcciones cuyo contenido cambia con el tiempo. Y aquí el sensor resultó ser dos novedades para mí: bueno y malo. Bien, hay tales direcciones. Y lo malo, solo hay dos, 261 y 264. ¡Compárelo con la “vida pasada”, cuando se dieron cuatro números en un comando a la vez! Ya rodé el labio: pensé que tendría acceso a todas las variables internas. Bueno, dos, dos.

¡Es hora de construir gráficos nuevamente!

Valor en la dirección 261:

Parece una concentración de CO2. Se puede ver cuando traté de respirar en el sensor. Es cierto que el valor mínimo es notablemente inferior a la "referencia" de 400 ppm, por lo que la calibración deja mucho que desear. De una forma u otra, el sensor se declara resucitado.

Valor en 264:

casi lo mismo, solo en una escala diferente y al revés.

Y ambas cantidades están en el mismo gráfico:

surge una pregunta natural: ¿tal vez una de estas cantidades es el valor muy "bruto" que proviene del ADC y que el sensor convierte a la estimación de CO2 utilizando el método esclavo? Si es así, esto abre grandes oportunidades para recalibrar y mejorar la precisión del sensor, y tal vez para usarlo para otros fines. La respuesta a esta pregunta (y algunas otras) trataremos de obtenerla en la próxima serie.

Se aceptan los comentarios y sugerencias: ¿de qué otra manera burlarse del MH-Z19 en el próximo artículo? Es cierto, no prometo nada.

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


All Articles