Côté obscur MH-Z19

Quoi encore? Combien pouvez-vous?

Oui, nous reparlerons aujourd'hui de notre capteur de dioxyde de carbone Winsen MH-Z19 bien-aimé. Non, il n'y aura pas de répétitions *.



* presque

Comme vous l'avez peut-être remarqué, des histoires d'horreur sur les dangers des concentrations élevées de CO2 dans la pièce apparaissent régulièrement dans les pages de cette ressource. Et bien que les affirmations selon lesquelles des concentrations supérieures à 1000 ppm portent l'enfer et la mort soient légèrement exagérées ( Wikipedia dit qu'au moins certains effets commencent par 1%, soit 10000 ppm, alors que le capteur a toute la plage de 5000 ppm) - le CO2 peut servir d'indicateur de la présence d'autres mauvaises choses en raison d'une ventilation insuffisante. Par conséquent, j'ai également décidé de rejoindre le monde fascinant de la mesure du CO2 et j'ai mis la main sur le capteur mentionné.

La première chose, bien sûr, je l'ai connecté à Arduino. J'ai copié (avec les modifications nécessaires) le code de l' article , les chiffres chéris sont apparus à l'écran.

Mais pendant que je le copiais, un ver de doute s'est glissé dans mon âme - pourquoi ce capteur a-t-il donné neuf octets, et seulement deux octets représentent le CO2 d'eux? Peut-être qu'il veut me dire autre chose?

Une recherche sur Internet m'a conduit à une page aussi intéressante . L'auteur expérimente avec le MH-Z19 et révèle sa réaction aux commandes non documentées (et documentées). Il n'a pas encore essayé toutes les équipes, donc il y a encore de la place pour notre part de plaisir. Voilà ce que nous allons faire.

Tout d'abord, nous traiterons de l'équipe «classique» 0x86 (ou simplement 134), avec laquelle nous obtenons la concentration de CO2. Rapports Revspace:

Une réponse à la commande 0x86 ressemble généralement à ceci:
0xFF CM HH LL TT SS Uh Ul CS

CM est la commande répétée en arrière
HH / LL est la valeur CO2 ppm, partie haute / basse
TT est la température en degrés Celcius, plus 40. Par exemple, lorsque la température est de 25 ° C, alors TT = 0x41
SS est une sorte d'octet d'état, cet octet n'a toujours qu'un seul bit défini!
Uh / Ul est une valeur inconnue, peut-être liée à la pression? Après avoir démarré le capteur, il démarre à 15 000 exactement, puis s'installe généralement à environ 10 500.
Cs est la somme de contrôle

Autrement dit, la réponse du capteur à cette commande contient également la température T (décalée de 40 degrés) et deux valeurs de destination inconnues - un octet S et deux octets U. S prend des valeurs de deux degrés, et U lorsque le capteur démarre, passe de 15 000 à un peu plus de 10 000

Comment comprendre la signification des nombres S et U? Bien sûr, vous devez dessiner un graphique! Dans toute situation incompréhensible, tracez un graphique.

Détails techniques ternes
Et pour dessiner un graphique, ce serait bien de conduire les lectures du capteur dans un ordinateur. Ce que j'ai fait avec Serial.println (). Toutes les cinq secondes, l'arduin interroge le capteur et écrit ses lectures sur USB-UART, il ne reste plus qu'à les lire sur l'ordinateur et à les enregistrer dans un fichier. Je fais ça (sous Linux) comme ceci:

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


Ne donne pas de coups de pied
Oui, je sais que vous pouvez faire juste cat / dev / ttyACM0> .., mais pour une raison quelconque, cela ne fonctionne pas toujours pour moi, parfois cette commande se termine immédiatement en silence. J'aime aussi la commande donnée (rlwrap cat | cu -l / dev / ttyACM0) car elle vous permet de communiquer facilement avec le microcontrôleur en mode interactif (bien que dans ce cas ce ne soit pas nécessaire). Il existe certainement de meilleurs outils à cet effet, mais, malheureusement, je ne les connais pas.

Dans une autre fenêtre de terminal, vous pouvez regarder ce fichier en temps réel:

 tail -f sensor_.log 

Il se trouve une telle feuille de chiffres:

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

Chaque ligne contient CO2, T, S, U (U est répété deux fois - comme deux octets et un nombre à deux octets, ne demandez pas pourquoi).

Vous pouvez maintenant créer des graphiques. Je vais le faire avec 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 


Ainsi, le graphique CO2:

En principe, cela semble être vrai. Tristes éclats seulement périodiques. Il semble que ce soit parce que le capteur est simplement posé sur la table, et à la moindre brise ses lectures sont perdues.

Température:

Le moment où j'ai ouvert la fenêtre est clairement visible. Pivote de 1 à 2 degrés, ce qui n'est pas mauvais pour une opportunité non documentée. Cependant, si nous rappelons le principe du capteur NDIR , nous pouvons comprendre qu'il ne faut pas s'attendre à une grande précision du thermomètre intégré. Ces instruments mesurent l'absorption de la lumière dans l'infrarouge lointain, et la bonne vieille ampoule d'Ilyich est utilisée pour générer cette lumière, et vous pouvez même voir à travers les fenêtres comment elle s'allume toutes les cinq secondes (un tel moment est pris sur le KDPV). Et cette ampoule consomme beaucoup d'énergie et, par conséquent, chauffe tout le capteur, et combien elle le chauffe dépend de la conjoncture momentanée des flux d'air.

Nous abordons les plus intéressants. Valeur S:

Ne dit rien? Moi aussi. Avec chagrin, nous dessinons CO2 et S sur le même graphique et augmentons légèrement:

Ouais! Maintenant, tout est clair! Lorsque tout va bien, S est 64, et lorsque le capteur de CO2 commence à faire des saucisses, il tombe à 4. Ainsi, vous pouvez utiliser S pour savoir à quel point le capteur se sent bien et à quel point ses lectures sont précises.

Il reste, comme disent les parachutistes, la valeur extrême est U:

Malheureusement, une astuce de superposition ne fait pas grand-chose ici. Il est seulement visible que, comme promis par revspace, il est au début égal à 15 000, puis tombe à un peu plus de 10 000 (mais il peut tomber un peu après longtemps). Et une fois par jour, le cycle se répète.

Mais quand j'ai connecté la puissance du capteur non pas à 5, mais à 3,3 volts d'arduino, la situation a changé:

3,3 volts sur l'arduino proviennent de la puce LP2985, qui est un stabilisateur linéaire de 160 milliampères. Et l'ampoule, à en juger par les articles sur Internet, mange à peu près autant. En regardant le capteur, il est à noter que l'ampoule avec cette alimentation s'embrase plus longtemps qu'à cinq volts. Et la valeur de U est une fois et demie plus élevée.

L'hypothèse suivante émerge - le capteur détermine automatiquement le temps qu'il faut pour allumer l'ampoule pour obtenir suffisamment de rayonnement infrarouge, et s'il n'y a pas assez de courant, il brûle l'ampoule plus longtemps. Et la valeur de U reflète simplement le temps de combustion de l'ampoule (ou une autre valeur associée, par exemple, l'énergie dépensée).

Pour tester cette hypothèse, nous alimentons le capteur à partir d'une batterie lithium-ion, qui peut évidemment produire un courant beaucoup plus important:

En effet, U tombe parfois en dessous de 10 000! Cependant, ce n'est évidemment pas une preuve absolue, et après 24 heures, tout devient presque le contraire. L'hypothèse n'est donc qu'une hypothèse, mais je n'ai rien trouvé de mieux.

UPD: Cher unsvp a résolu l' énigme de la valeur U. Je lui donne la parole:

la valeur de U est évidemment la valeur minimale de l'absorption mesurée d'IR CO2 par jour, dans certaines unités de mesure internes.

Rien à ajouter, sauf que le planning:

Pourquoi n’y ai-je pas pensé moi-même? Tout est simple. J'ai dessiné un graphique de quatre valeurs à la fois et je me suis installé là-dessus. Mais il était nécessaire de tirer deux quantités (comme dans l'image ci-dessus), puis les déchets étrangers face à la magnitude S n'interféreraient pas avec la perception. Ne répétez pas mes erreurs.

J'ajouterai peut-être ceci: voyez-vous une étape supérieure à 1000 ppm à 48 heures? Ce capteur est ainsi calibré automatiquement. Dans ce cas, la valeur de U a chuté par rapport à ce qu'elle était avant l'étalonnage. Alors qu'il est évident que la concentration réelle de CO2 durant cette période n'a fait qu'augmenter. La conclusion de ceci est très simple - la valeur U n'est pas une valeur d'absorption très «brute», mais est calculée déjà ajustée pour l'étalonnage actuel, représentant apparemment une certaine différence dans les lectures minimales dans les cycles d'étalonnage actuels et précédents.

En général, à mon avis, l'auto-étalonnage (au moins sous la forme sous laquelle il est implémenté dans le MH-Z19) est mauvais. Revspace indique qu'il peut être désactivé à l'aide de la commande d'activation / désactivation de la logique 0x79: ABC.

/ UPD

Eh bien, avec une équipe triée. Il est temps d'aller plus loin, puis l'article touche à sa fin, et 255 autres équipes n'ont pas été testées!

Dans l'article revspace, la liste des commandes testées se termine comme suit :

commande 0x89-0x8F
Aucune réponse n'est retournée, cependant la commande 0x8d semble réinitialiser le capteur.

commande 0x99 (plage)
...

De plus, les équipes avec des nombres inférieurs ne sont pas toutes vérifiées. Ainsi, il reste un peu plus de la moitié du nombre total d'équipes inconnues.

Sans plus tarder, j'ai décidé de donner des commandes au hasard (plus précisément, de façon pseudo-aléatoire). Et voici ce que j'ai obtenu:

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

Ici, la commande est ce qui a été envoyé au capteur (le numéro de commande lui-même est le troisième nombre depuis le début), la réponse est ce que le capteur a répondu, vous ne pouvez pas regarder le reste (CRC est la somme de contrôle calculée / réelle, CO2 / t / s / u est le résultat de la panne réponse du capteur à quatre chiffres, comme s'il répondait à une commande "par défaut").

Comme vous pouvez le voir, pas beaucoup. De plus, à un moment donné, le capteur a complètement refusé de donner autre chose que des zéros. La dernière chose que j'ai reçue du capteur était:

 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 

Et puis des zéros. J'ai essayé d'entrer des commandes séquentiellement, en commençant par 0x8e - encore des zéros. J'ai essayé de donner la commande "standard" 0x86 - zéros. Ai-je tué le capteur? En vérité, toutes les conditions sont réunies - j'entre de petites commandes non documentées, donc je connecte également l'interface du capteur directement à l'arduine cinq volts, bien que la fiche technique indique explicitement qu'elle est conçue pour 3,3 volts.

Tout d'abord, j'ai essayé la bonne vieille recette de tout enikeyshchik - éteignez-la et rallumez-la. Autrement dit, il l'a sorti et l'a collé au capteur plus la puissance avec tout le reste fonctionnant. Le capteur a produit approximativement les mêmes que dans le dernier passage cité (mais avec des nombres légèrement différents). Oui, cela signifie que le capteur n'est pas complètement mort et dit quelque chose à chaque démarrage, a deviné les shtirlits.

Ensuite, j'ai donné un peu plus à mon cerveau et j'ai deviné même avant une vérité - ces zéros que nous avons vu ci-dessus ne sont pas du tout la réponse du capteur. En fait, le capteur est silencieux et mon programme tire ce que la fonction Arduin de réception de n octets a donné (pour dire des zéros). Et si à chaque fois avant la réception pour s'assurer qu'il y a quelque chose à prendre, il s'avère qu'il n'y a rien à accepter. Sauf dans les cas où le capteur vient de redémarrer.

Il s'avère que le capteur a complètement cessé d'accepter les commandes. Apparemment, 5 volts sur l'interface série n'étaient pas vains. Oui, l'article n'a pas demandé en quelque sorte. Merci à tous pour votre attention. Nous ne sommes pas d'accord, il n'y a rien à regarder.

Oh attends ...

Voir ces chiffres à la fin?

 13 10 

Ça ne ressemble à rien?

Bien sûr, c'est un bon vieux fil de ligne ! En d'autres termes, 0x0D 0x0A - c'est la façon de traduire une chaîne, par exemple, sur Windows (et sur Unix, c'est plus facile - 0x0A, car certains fichiers perdent des sauts de ligne lorsqu'ils sont ouverts dans un bloc-notes Windows).

Alors peut-être que le capteur veut nous dire quelque chose en langage humain? Cependant, si cette langue est le chinois, cela ne m'aidera pas beaucoup. Espérons donc qu'il s'agit d'un langage plus compréhensible, et décodons le message selon la table 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 

Reçu jusqu'à six lettres. Et voici ce que le même capteur a dit lors du chargement un peu plus tôt:

 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 différence est évidente - la ligne KB200 est devenue la ligne MODBUS. Le reste - il semble que ce ne soit pas du tout du texte, pas même des caractères chinois - ne serait-ce que parce que la plupart d'entre eux changent de temps en temps.

Alors, que nous dit le capteur? À la demande de KB200, une recherche sur Internet produit un clavier, un échantillonneur de base, un fer à repasser, une table à langer, un contrôleur pour contrôler les caméras PTZ, un mélangeur, sauf un chauve. Eh bien, mais on ne sait pas comment appliquer ces connaissances à notre cas. Eh bien, recherchons MODBUS. Cette fois, Wikipédia est à notre service:

Modbus est un protocole de communication ouvert basé sur l'architecture maître-esclave. Il est largement utilisé dans l'industrie pour organiser les communications entre les appareils électroniques. Il peut être utilisé pour transmettre des données via des lignes de communication série RS-485, RS-422, RS-232, ainsi qu'un réseau TCP / IP (Modbus TCP).

L'hypothèse elle-même se suggère - après l'une des commandes non documentées, le capteur est passé au protocole Modbus et maintenant il nous en informe en utilisant les méthodes disponibles. Puisqu'aucune autre option n'est prévue, nous allons tester directement cette hypothèse, c'est-à-dire, essayons de contacter le capteur via Modbus.

Sur Internet, une implémentation Modbus pour les arduins a été trouvée. Mais c'est une malchance - Arduino Leonardo n'est pas pris en charge, mais j'ai par hasard monstrueux juste Leonardo.

Mais, comme je m'en suis vite rendu compte, c'est même pour le mieux. Le protocole Modbus est aussi simple que trois centimes. Et d'ailleurs douloureusement similaire au protocole "natif" MH-Z19. Alors, pourquoi faire glisser des choses désagréables sur Internet et le comprendre douloureusement lorsque vous pouvez mettre en œuvre tout ce dont vous avez besoin en deux minutes (enfin, deux heures) vous-même?

Donc, plus tôt, nous, voulant connaître les lectures, avons demandé au capteur de les émettre comme suit:

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

Ou en décimal:

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

Où 255 est le nombre magique, 1 est l'adresse du capteur, 134 est la commande, 121 est l'octet de la somme de contrôle.

Et à quoi cela ressemblera-t-il dans Modbus? Il n'y aura pas de correspondance exacte, mais vous pouvez par exemple faire ceci:

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

1 - adresse du capteur.

4 - numéro d'équipe. Les commandes dans Modbus peuvent être comptées sur les doigts, et jusqu'à présent, nous ne nous intéresserons qu'à deux d'entre elles - 3 et 4. Pour des raisons cachées dans l'obscurité des siècles, elles sont appelées lire plusieurs registres de maintien et lire les registres d'entrée, mais en fait, ils donnent une commande pour lire une donnée le nombre de nombres à deux octets à une adresse donnée. La commande 3 lit les nombres disponibles pour la lecture / l'écriture et la commande 4 lit uniquement.

0, 0 est l'adresse que nous allons lire (dans ce cas, 0). Si vous définissez la même adresse avec une équipe de 3 ou 4, nous obtiendrons généralement des résultats différents.

0, 4 - le nombre de nombres que nous voulons lire (dans ce cas 4). Il y a un moment amusant ici. Bien que vous puissiez spécifier ce nombre jusqu'à 65535, en fait, le protocole vous permet de lire pas plus de 125 nombres à la fois. Et tout cela parce que la réponse indique le nombre d'octets des informations envoyées, et elle ne prend qu'un seul octet (et les nombres sont sur deux octets). De plus, si je comprends bien, la longueur de la réponse elle-même est limitée à 255 octets.

213, 197 - deux octets d'une somme de contrôle ( CRC16 ). En général, c'est le moment le plus difficile de toute notre mise en œuvre. En vérité, je n'ai même pas exploré comment cela est considéré, mais j'ai simplement copié le code d'ici . Puisqu'il y a une mer de différents CRC16, il faut aborder de manière responsable le choix de la fonction. Vous pouvez vérifier si une fonction particulière convient à Modbus, par exemple, ici .

En fait, c'est tout ce que nous devons savoir sur Modbus. Au moins pour commencer.

Bien que vous ayez longtemps deviné que mon appel au MH-Z19 sur Modbus était un succès, mais supposons que l'intrigue persiste. Jusqu'à présent, nous ne savons même pas quelle est l'adresse de notre capteur (bien que "dans l'original" c'est 1, c'est loin d'être le même sur Modbus). Donc, vous devez répéter la commande avec différentes adresses (et il n'y en a que 255) et voir à quoi notre capteur va répondre:

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

Il semble que l'adresse soit 2. Je répète plusieurs commandes avec l'adresse 2 - il n'y a pas de réponse. Je change l'adresse en 1 - il y a une réponse! Ainsi, l'adresse du capteur est la même qu'elle était - 1.

Et pourquoi le passage 2 a-t-il obtenu l'adresse 2? Ici encore, l'hindunisme de mon code rampe. Après avoir émis la commande, je vérifie s'il y a des octets à recevoir. Mais comme je le fais tout de suite, le capteur n'a pas le temps d'envoyer quoi que ce soit, donc la réponse du capteur n'est acceptée par le programme qu'au cycle suivant. Comme vous pouvez le voir dans le journal donné - le premier numéro de la réponse est 1, et il indique simplement l'adresse du capteur. J'ai contourné ce problème en ajoutant simplement un délai de 50 millisecondes avant de recevoir une réponse.

Considérez la réponse du capteur à notre commande:

 1 132 2 194 193 

1 - comme nous l'avons déjà découvert - l'adresse du capteur.

132 - code de commande et code d'erreur. S'il n'y avait pas d'erreur, ce nombre serait le même que la commande envoyée - c'est-à-dire 4. Mais une erreur s'est produite, comme indiqué par le bit le plus significatif mis à 1, donc le nombre est devenu 4 + 128 = 132. Par conséquent, soit dit en passant, une commande dans Modbus ne peut pas avoir un nombre supérieur à 127 - pour une telle commande, le code de réussite serait le même que le code d'erreur.

2 - code d'erreur. Dit exactement quelle erreur s'est produite. Comme le dit Wikipedia, 02 - L'adresse de données spécifiée dans la demande n'est pas disponible. Donc, il n'y a pas de poisson à cette adresse et il n'y a rien à attraper. Nous essaierons d'autres adresses.

194 193 - CRC16.

Maintenant, enfin, il est temps de gratter l'espace d'adressage du capteur pour comprendre où se trouve le poisson. Je l'ai fait simplement - j'ai envoyé une commande pour lire un numéro avec une nouvelle adresse toutes les 0,1 secondes. Étant donné que les adresses sont 65536, ce processus se termine dans environ deux heures. Les résultats sont brièvement les suivants:

Commande 1 (lecture des bobines) - erreur 2 avec n'importe quelle adresse.
Commande 2 (lecture des entrées discrètes) - avec toute erreur d'adresse 2.
Commande 4 (lecture des registres d'entrée) - erreur 2 avec n'importe quelle adresse.
Équipe 3 (lire plusieurs registres de détention) - donne du succès aux adresses de 0 à 289.
Les commandes d'écriture de valeurs (par exemple, 6) semblent fonctionner, mais il semble que la valeur enregistrée soit bientôt remplacée par ce qu'elle était. Mais je n'ai pas étudié cette question de près.

Ainsi, le cercle de recherche se rétrécit - nous avons besoin de nombres à la commande 3 et d'adresses de 0 à 289. L'idée du monde intérieur riche du capteur peut être obtenue à partir de ces lignes:

 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 

Il est vrai que les numéros ont été enregistrés dans l'archive uniquement à l'adresse 255. Ici encore, 1 3 est l'adresse et la commande, 128 est le nombre d'octets transférés, deux octets à la fin sont CRC, et tout le reste est le contenu de la mémoire.

De toute cette splendeur, nous nous intéressons évidemment aux adresses dont le contenu change avec le temps. Et ici, le capteur s'est avéré être deux nouvelles pour moi - bonnes et mauvaises. Bon - il y a de telles adresses. Et le mauvais - il n'y en a que deux - 261 et 264. Comparez avec la «vie passée», quand quatre chiffres étaient donnés sur une seule commande à la fois! J'ai déjà roulé ma lèvre - je pensais avoir accès à toutes les variables internes. Eh bien, deux donc deux.

Il est temps de construire à nouveau des graphiques!

Valeur à l'adresse 261:

Cela ressemble à une concentration de CO2. On peut le voir lorsque j'ai essayé de respirer sur le capteur. Certes, la valeur minimale est sensiblement inférieure à la "référence" 400 ppm, donc l'étalonnage laisse beaucoup à désirer. D'une manière ou d'une autre, le capteur est déclaré ressuscité.

264:

, .

:

— , — «» , 2? , , , . ( ) .

— MH-Z19 . , .

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


All Articles