Sisi Gelap MH-Z19

Apa lagi? Seberapa banyak Anda bisa?

Ya, hari ini kita akan berbicara lagi tentang sensor karbon dioksida Winsen MH-Z19 yang kita cintai. Tidak, tidak akan ada pengulangan *.



* hampir

Seperti yang mungkin telah Anda perhatikan, kisah - kisah horor tentang bahaya konsentrasi tinggi CO2 di dalam ruangan secara teratur muncul di halaman-halaman sumber daya ini. Dan meskipun klaim bahwa konsentrasi di atas 1000 ppm membawa neraka dan kematian sedikit dilebih-lebihkan ( Wikipedia mengatakan bahwa setidaknya beberapa efek dimulai dengan 1%, yaitu 10.000 ppm, sedangkan sensor memiliki seluruh kisaran 5000 ppm) - CO2 dapat berfungsi sebagai indikator adanya hal-hal buruk lainnya karena ventilasi yang tidak memadai. Karena itu, saya juga memutuskan untuk bergabung dengan dunia metana-CO2 yang menakjubkan dan mendapatkan sensor yang disebutkan di atas.

Hal pertama, tentu saja, saya menghubungkannya ke Arduino. Saya menyalin (dengan perubahan yang diperlukan) kode dari artikel , angka-angka yang dihargai muncul di layar.

Tetapi ketika saya menyalin, cacing keraguan merayap ke dalam jiwa saya - mengapa sensor ini memberikan sembilan byte, dan hanya dua byte yang menghasilkan CO2 dari mereka? Mungkin dia ingin memberitahuku sesuatu yang lain?

Pencarian di internet membawa saya ke halaman yang begitu menarik . Penulis bereksperimen dengan MH-Z19 dan mengungkapkan reaksinya terhadap perintah yang tidak berdokumen (dan didokumentasikan). Dia belum mencoba semua tim, jadi masih ada ruang bagi kita untuk bermain-main. Ini yang akan kita lakukan.

Pertama-tama, kita akan berurusan dengan tim "klasik" 0x86 (atau hanya 134), yang dengannya kita mendapatkan konsentrasi CO2. Laporan revspace:

Respons terhadap perintah 0x86 biasanya terlihat seperti ini:
0xFF CM HH LL TT SS Uh Ul CS
dimana
CM adalah perintah yang diulang kembali
HH / LL adalah nilai CO2 ppm, tinggi / rendah
TT adalah suhu dalam derajat Celcius, ditambah 40. Misalnya, ketika suhu 25 derajat C, maka TT = 0x41
SS adalah semacam byte status, byte ini selalu hanya memiliki satu bit yang ditetapkan!
Uh / Ul adalah nilai yang tidak diketahui, mungkin terkait dengan tekanan? Setelah mem-boot sensor, sensor ini dimulai pada 15000 persis, kemudian biasanya mencapai sekitar 10500.
Cs adalah checksum

Yaitu, respons sensor terhadap perintah ini juga mengandung suhu T (bergeser 40 derajat) dan dua nilai tujuan yang tidak diketahui - satu byte S dan dua byte U. S mengambil nilai dua derajat, dan U saat sensor dimulai, turun dari 15.000 menjadi sedikit lebih dari 10 000

Bagaimana memahami apa yang dimaksud dengan angka S dan U? Tentu saja, Anda perlu menggambar grafik! Dalam situasi yang tidak dapat dipahami, gambarkan grafik.

Rincian teknis yang membosankan
Dan untuk menggambar grafik, alangkah baiknya untuk mengarahkan pembacaan sensor ke komputer. Yang saya lakukan dengan Serial.println (). Setiap lima detik, arduin menyurvei sensor dan menulis pembacaannya ke USB-UART, yang tersisa adalah membacanya di komputer dan menyimpannya ke file. Saya melakukan ini (di Linux) seperti ini:

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


Jangan menendang
Ya, saya tahu bahwa Anda hanya dapat melakukan cat / dev / ttyACM0> .., tetapi untuk beberapa alasan ini tidak selalu berhasil untuk saya, kadang-kadang perintah ini segera berakhir dengan diam-diam. Saya juga menyukai perintah yang diberikan (rlwrap cat | cu -l / dev / ttyACM0) karena memungkinkan Anda berkomunikasi dengan mudah dengan mikrokontroler dalam mode interaktif (walaupun dalam hal ini tidak diperlukan). Tentunya ada alat yang lebih baik untuk tujuan ini, tetapi, sayangnya, saya tidak tahu mereka.

Di jendela terminal lain, Anda dapat menonton file ini secara real time:

 tail -f sensor_.log 

Ternyata selembar angka:

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

Setiap baris mengandung CO2, T, S, U (U diulang dua kali - sebagai dua byte dan nomor dua byte, jangan tanya mengapa).

Sekarang Anda dapat membuat grafik. Saya akan melakukan ini dengan 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 


Jadi, grafik CO2:

Pada prinsipnya, tampaknya itu benar. Sedih hanya semburan berkala. Sepertinya ini karena sensornya hanya tergeletak di atas meja, dan dengan sedikit angin bacaannya hilang.

Suhu:

Momen ketika saya membuka jendela terlihat jelas. Berputar dengan 1 - 2 derajat, yang tidak buruk untuk kesempatan tidak berdokumen. Namun, jika kita mengingat prinsip sensor NDIR , kita dapat memahami bahwa kita seharusnya tidak mengharapkan akurasi yang besar dari termometer bawaan. Instrumen-instrumen ini mengukur penyerapan cahaya dalam jangkauan inframerah jauh, dan bola lampu Ilyich yang baik digunakan untuk menghasilkan cahaya ini, dan Anda bahkan dapat melihat melalui jendela bagaimana cahaya menyala setiap lima detik (momen seperti itu tertangkap di KDPV). Dan bola lampu ini menghabiskan banyak energi dan, sebagai hasilnya, memanaskan seluruh sensor, dan seberapa banyak memanaskannya tergantung pada konjungsi sesaat dari aliran udara.

Kami mendekati yang paling menarik. Nilai S:

Tidak mengatakan apa-apa? Saya juga. Dengan kesedihan, kami menggambar CO2 dan S pada grafik yang sama dan sedikit meningkat:

Ya! Sekarang semuanya jelas! Ketika semuanya baik-baik saja, S adalah 64, dan ketika sensor CO2 mulai sosis, itu turun menjadi 4. Dengan demikian, Anda dapat menggunakan S untuk mengetahui seberapa baik sensor merasakan dan seberapa akurat pembacaannya.

Masih ada, seperti dikatakan pasukan terjun payung, nilai ekstremnya adalah U:

Sayangnya, trik overlay tidak banyak berpengaruh di sini. Hanya terlihat bahwa, seperti dijanjikan revspace, pada awalnya itu sama dengan 15.000, dan kemudian turun menjadi sedikit lebih dari 10.000 (tetapi bisa turun sedikit setelah waktu yang lama). Dan sekali sehari siklusnya berulang.

Tetapi ketika saya menghubungkan daya sensor bukan ke 5, tetapi ke arduino 3,3 volt, situasinya berubah:

3,3 volt pada Arduino diambil dari chip LP2985, yang merupakan penstabil linier 160 miliamp. Dan bola lampu, dilihat dari artikel-artikel di Internet, memakan sebanyak mungkin. Saat melihat sensor, terlihat bahwa bola lampu dengan catu daya ini menyala lebih lama daripada lima volt. Dan nilai U satu setengah kali lebih tinggi.

Hipotesis berikut muncul - sensor secara otomatis menentukan berapa lama yang dibutuhkan untuk menyalakan bola lampu untuk mendapatkan radiasi infra merah yang cukup, dan jika tidak ada cukup arus, ia akan membakar bola lampu lebih lama. Dan nilai U hanya mencerminkan waktu pembakaran bola lampu (atau nilai terkait lainnya, misalnya, energi yang dikeluarkan).

Untuk menguji asumsi ini, kami menyalakan sensor dari baterai lithium-ion, yang jelas dapat menghasilkan arus yang jauh lebih besar:

Memang, kadang-kadang Anda jatuh di bawah 10.000! Namun, ini jelas bukan bukti absolut, dan setelah 24 jam semuanya menjadi sebaliknya. Jadi hipotesisnya tetap hanya hipotesis, tetapi saya tidak menemukan sesuatu yang lebih baik.

UPD: Dear unsvp memecahkan teka - teki nilai U. Saya beri dia lantai:

nilai U jelas merupakan nilai minimum dari penyerapan IR CO2 yang diukur per hari, di beberapa unit pengukuran internal.

Tidak ada yang ditambahkan, kecuali jadwalnya:

Mengapa saya tidak memikirkannya sendiri? Semuanya sederhana. Saya menggambar grafik empat nilai sekaligus dan menyelesaikannya. Tapi itu perlu untuk menggambar dua kuantitas (seperti pada gambar di atas), maka sampah asing di hadapan besarnya S tidak akan mengganggu persepsi. Jangan ulangi kesalahan saya.

Mungkin saya akan menambahkan ini: apakah Anda melihat langkah lebih besar dari 1000 ppm pada 48 jam? Sensor ini dikalibrasi secara otomatis. Dalam hal ini, nilai U turun dibandingkan dengan sebelum kalibrasi. Padahal jelas bahwa sebenarnya konsentrasi CO2 selama periode ini hanya meningkat. Kesimpulan dari ini sangat sederhana - nilai U bukan nilai serapan yang sangat "kasar", tetapi dihitung sudah disesuaikan untuk kalibrasi saat ini, tampaknya mewakili beberapa perbedaan dalam pembacaan minimum dalam siklus kalibrasi saat ini dan sebelumnya.

Secara umum, menurut pendapat saya, kalibrasi otomatis (setidaknya dalam bentuk penerapannya dalam MH-Z19) adalah jahat. Revspace mengatakan bahwa itu dapat dinonaktifkan menggunakan perintah on / off logika 0x79: ABC.

/ UPD

Nah, dengan satu tim beres. Saatnya melangkah lebih jauh, dan artikelnya sudah mendekati akhir, dan 255 tim lainnya belum diuji!

Dalam artikel revspace, daftar perintah yang diuji berakhir seperti ini:

perintah 0x89-0x8F
Tidak ada respons yang dikembalikan, namun perintah 0x8d tampaknya mengatur ulang sensor.

perintah 0x99 (rentang)
...

Selain itu, tim dengan angka lebih rendah tidak semuanya diverifikasi. Dengan demikian, sedikit lebih dari setengah dari jumlah tim yang tidak diketahui yang tersisa.

Tanpa basa-basi lagi, saya memutuskan untuk memberikan perintah secara acak (lebih tepatnya, pseudo-acak). Dan inilah yang saya dapat:

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

Di sini Perintah adalah apa yang dikirim ke sensor (nomor perintah itu sendiri adalah nomor ketiga dari awal), Respon adalah apa yang dijawab sensor, Anda tidak dapat melihat sisanya (CRC adalah perhitungan / checksum aktual, CO2 / t / s / u adalah hasil kerusakan sensor menanggapi empat angka, seolah-olah merespons perintah "default").

Seperti yang Anda lihat, tidak banyak. Selain itu, dari beberapa titik, sensor sepenuhnya menolak untuk memberikan apa pun selain nol. Hal terakhir yang saya dapatkan dari sensor adalah:

 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 

Dan kemudian nol. Saya mencoba memasukkan perintah secara berurutan, dimulai dengan 0x8e - lagi nol. Saya mencoba memberikan perintah "standar" 0x86 - nol. Apakah saya membunuh sensor? Sebenarnya, semua kondisi untuk ini ada - saya memasukkan sedikit perintah tidak berdokumen, jadi saya juga menghubungkan antarmuka sensor langsung ke arduine lima volt, meskipun datasheet secara eksplisit mengatakan bahwa ia dirancang untuk 3,3 volt.

Pertama-tama, saya mencoba resep lama yang baik dari setiap enikeyshchik - matikan dan nyalakan lagi. Artinya, ia mengeluarkannya dan menempelkannya di sensor plus daya dengan segala sesuatu bekerja. Sensor yang dihasilkan kira-kira sama seperti pada kutipan terakhir (tetapi dengan angka yang sedikit berbeda). Ya, itu berarti sensornya tidak sepenuhnya mati dan mengatakan sesuatu di setiap boot, tebak semua shtirlits.

Lalu saya memberi otak saya sedikit lebih banyak dan menebak-nebak bahkan sebelum satu kebenaran - nol yang kita lihat di atas bukanlah jawaban sensor sama sekali. Sebenarnya, sensornya diam, dan program saya menggambarkan apa yang diberikan fungsi Arduin untuk menerima n byte (untuk mengatakan nol). Dan jika setiap kali sebelum resepsi memastikan bahwa ada sesuatu untuk diambil, ternyata tidak ada yang bisa diterima. Kecuali dalam kasus di mana sensor baru saja reboot.

Ternyata sensor sepenuhnya berhenti menerima perintah apa pun. Rupanya, 5 volt pada antarmuka serial tidak sia-sia. Ya, artikel itu entah bagaimana tidak bertanya. Terima kasih atas perhatiannya. Kami tidak setuju, tidak ada yang bisa dilihat.

Oh tunggu ...

Lihat angka-angka ini di akhir?

 13 10 

Tidak menyerupai apa pun?

Tentu saja, ini merupakan umpan lama yang bagus! Dengan kata lain, 0x0D 0x0A - ini adalah cara untuk menerjemahkan string, misalnya, pada Windows (dan pada Unix mereka melakukannya dengan lebih mudah - 0x0A, karena beberapa file kehilangan jeda baris ketika dibuka di notebook Windows).

Jadi mungkin sensor ingin memberi tahu kami sesuatu dalam bahasa manusia? Namun, jika bahasa ini adalah bahasa Cina, itu tidak akan banyak membantu saya. Jadi mari kita berharap bahwa ini adalah bahasa yang lebih dimengerti, dan mendekode pesan sesuai dengan tabel 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 

Menerima sebanyak enam huruf. Dan inilah yang dikatakan sensor yang sama saat memuat sedikit lebih awal:

 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 

Perbedaannya jelas - garis KB200 telah berubah menjadi jalur MODBUS. Sisanya - tampaknya sama sekali bukan teks, bahkan bukan karakter Cina - jika hanya karena sebagian besar dari mereka berubah dari waktu ke waktu.

Jadi, apa yang diceritakan oleh sensor kepada kita? Atas permintaan KB200, pencarian Internet menghasilkan keyboard, sampler inti, setrika, meja ganti, pengontrol kontrol kamera PTZ, mixer, kecuali yang botak. Ya, tetapi tidak jelas bagaimana menerapkan pengetahuan ini pada kasus kami. Baiklah, mari kita cari MODBUS. Kali ini Wikipedia sendiri siap melayani Anda:

Modbus adalah protokol komunikasi terbuka berdasarkan arsitektur master-slave. Ini banyak digunakan dalam industri untuk mengatur komunikasi antara perangkat elektronik. Dapat digunakan untuk mengirimkan data melalui jalur komunikasi serial RS-485, RS-422, RS-232, serta jaringan TCP / IP (Modbus TCP).

Hipotesis itu sendiri menunjukkan dirinya sendiri - setelah salah satu perintah tidak berdokumen, sensor beralih ke protokol Modbus dan sekarang ini memberi tahu kami tentang hal ini menggunakan metode yang tersedia. Karena tidak ada opsi lain yang diramalkan, kami akan mengambil tes langsung hipotesis ini, yaitu, mari kita coba menghubungi sensor melalui Modbus.

Di Internet, implementasi Modbus untuk arduins ditemukan. Tetapi ini adalah nasib buruk - Arduino Leonardo tidak didukung, tetapi kebetulan saya hanya memiliki Leonardo yang mengerikan.

Tetapi, ketika saya segera menyadari, ini bahkan untuk yang terbaik. Protokol Modbus sesederhana tiga sen. Dan selain itu mirip dengan protokol "asli" MH-Z19. Jadi mengapa menyeret hal-hal buruk dari Internet dan memahaminya dengan menyakitkan ketika Anda dapat mengimplementasikan semua yang Anda butuhkan dalam dua menit (yah, dua jam) sendiri?

Jadi, sebelumnya, kami, ingin mengetahui bacaannya, meminta sensor untuk mengeluarkannya sebagai berikut:

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

Atau dalam desimal:

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

Di mana 255 adalah angka ajaib, 1 adalah alamat sensor, 134 adalah perintah, 121 adalah byte dari checksum.

Dan seperti apa tampilannya di Modbus? Tidak akan ada kecocokan persis, tetapi Anda dapat melakukan, misalnya, ini:

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

1 - alamat sensor.

4 - nomor tim. Perintah di Modbus dapat dihitung dengan jari, dan sejauh ini kita hanya akan tertarik pada dua di antaranya - 3 dan 4. Untuk alasan yang tersembunyi dalam kegelapan abad, mereka disebut Read Multiple Holding Registers dan Read Input Register, tetapi sebenarnya mereka memberikan perintah untuk membaca yang diberikan jumlah angka byte ganda pada alamat yang diberikan. Perintah 3 membaca angka yang tersedia untuk membaca / menulis, dan perintah 4 hanya membaca.

0, 0 adalah alamat yang akan kita baca (dalam hal ini, 0). Jika Anda menetapkan alamat yang sama dengan tim 3 atau 4, kami biasanya akan mendapatkan hasil yang berbeda.

0, 4 - jumlah angka yang ingin kita baca (dalam hal ini 4). Ada momen lucu di sini. Meskipun Anda dapat menentukan nomor ini hingga 65535, pada kenyataannya, protokol ini memungkinkan Anda untuk membaca tidak lebih dari 125 angka sekaligus. Dan semua karena respons menunjukkan jumlah byte informasi yang dikirim, dan hanya membutuhkan satu byte (dan jumlahnya dua byte). Selain itu, seperti yang saya pahami, panjang respons itu sendiri terbatas pada 255 byte.

213, 197 - dua byte checksum ( CRC16 ). Secara umum, ini adalah saat yang paling sulit dalam seluruh implementasi kami. Sebenarnya, saya bahkan tidak menyelidiki bagaimana itu dianggap, tetapi cukup menyalin kode dari sini . Karena ada lautan CRC16 yang berbeda, seseorang harus secara bertanggung jawab mendekati pilihan fungsi. Anda dapat memeriksa apakah fungsi tertentu cocok untuk Modbus, misalnya, di sini .

Sebenarnya, hanya itu yang perlu kita ketahui tentang Modbus. Setidaknya sebagai permulaan.

Meskipun Anda sudah lama menduga bahwa daya tarik saya untuk MH-Z19 di Modbus berhasil, tetapi mari kita berpura-pura bahwa intrik tetap ada. Sejauh ini, kami bahkan tidak tahu apa alamat sensor kami (meskipun "di aslinya" itu 1, jauh dari fakta bahwa itu sama di Modbus). Jadi, Anda perlu mengulangi perintah dengan alamat yang berbeda (dan hanya ada 255 di antaranya) dan melihat apa yang akan ditanggapi oleh sensor kami:

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

Tampaknya alamatnya adalah 2. Saya ulangi beberapa perintah dengan alamat 2 - tidak ada jawaban. Saya mengubah alamat menjadi 1 - ada jawaban! Dengan demikian, alamat sensornya sama dengan - 1.

Dan mengapa bagian 2 mendapatkan alamat 2? Di sini, lagi-lagi ketidakhadiran kode saya merangkak keluar. Setelah mengeluarkan perintah, saya memeriksa apakah ada byte untuk menerima. Tetapi karena saya melakukan ini segera, sensor tidak punya waktu untuk mengirim apa pun, sehingga respons sensor diterima oleh program hanya pada siklus berikutnya. Seperti yang Anda lihat di log yang diberikan - angka pertama dalam jawabannya adalah 1, dan itu hanya menunjukkan alamat sensor. Saya menghindari masalah ini dengan hanya menambahkan penundaan 50 milidetik sebelum menerima respons.

Pertimbangkan respons sensor terhadap perintah kami:

 1 132 2 194 193 

1 - seperti yang telah kita ketahui - alamat sensor.

132 - kode perintah dan kode kesalahan. Jika tidak ada kesalahan, angka ini akan sama dengan perintah yang dikirim - yaitu 4. Tapi kesalahan terjadi, seperti yang ditunjukkan oleh bit paling signifikan yang diatur ke 1, sehingga jumlahnya menjadi 4 + 128 = 132. Oleh karena itu, omong-omong, perintah di Modbus tidak dapat memiliki angka lebih dari 127 - untuk perintah seperti itu, kode keberhasilan akan sama dengan kode kesalahan.

2 - kode kesalahan. Mengatakan persis kesalahan yang terjadi. Seperti yang dikatakan Wikipedia, 02 - Alamat data yang ditentukan dalam permintaan tidak tersedia. Jadi, tidak ada ikan di alamat ini dan tidak ada yang bisa ditangkap. Kami akan mencoba alamat lain.

194 193 - CRC16.

Sekarang, akhirnya, saatnya menggaruk ruang alamat sensor untuk memahami di mana ikan itu berada. Saya melakukan ini secara sederhana - saya mengirim perintah untuk membaca satu nomor dengan alamat baru setiap 0,1 detik. Karena alamatnya 65536, proses ini selesai dalam waktu sekitar dua jam. Hasilnya singkat sebagai berikut:

Command 1 (Read Coils) - galat 2 dengan alamat apa pun.
Perintah 2 (Baca Input Terpisah) - dengan kesalahan alamat 2
Perintah 4 (Baca Input Register) - kesalahan 2 dengan alamat apa pun.
Tim 3 (Baca Beberapa Holding Register) - memberikan kesuksesan di alamat dari 0 hingga 289.
Perintah untuk menulis nilai (misalnya, 6) tampaknya berhasil, tetapi tampaknya nilai yang direkam segera diganti dengan apa yang sebelumnya. Tapi saya tidak menyelidiki masalah ini dengan cermat.

Jadi, lingkaran pencarian menyempit - kita perlu angka pada perintah 3 dan alamat dari 0 hingga 289. Gagasan dunia batin yang kaya dari sensor dapat diperoleh dari baris-baris ini:

 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 

Benar, angka-angka itu disimpan dalam arsip hanya ke alamat 255. Di sini, sekali lagi, 1 3 adalah alamat dan perintah, 128 adalah jumlah byte yang ditransfer, dua byte pada akhirnya adalah CRC, dan yang lainnya adalah isi dari memori.

Dari semua kemegahan ini, kami jelas tertarik pada alamat-alamat yang isinya berubah seiring waktu. Dan di sini sensornya ternyata menjadi dua berita bagi saya - baik dan buruk. Bagus - ada alamat seperti itu. Dan yang buruk - hanya ada dua - 261 dan 264. Bandingkan dengan "kehidupan lampau", ketika empat angka diberikan pada satu perintah sekaligus! Saya sudah menggulung bibir saya - saya pikir saya akan mendapatkan akses ke semua variabel internal. Nah, dua jadi dua.

Saatnya membangun grafik lagi!

Nilai di alamat 261:

Itu terlihat seperti konsentrasi CO2. Itu bisa dilihat ketika saya mencoba menghirup sensor. Benar, nilai minimum terletak jauh lebih rendah daripada "referensi" 400 ppm, sehingga kalibrasi menyisakan banyak yang diinginkan. Dengan satu atau lain cara, sensor dinyatakan dihidupkan kembali.

Nilai pada 264: Hampir

sama, hanya pada skala yang berbeda dan terbalik.

Dan kedua kuantitas berada pada grafik yang sama:

Sebuah pertanyaan alami muncul - mungkin salah satu dari jumlah ini adalah nilai yang sangat "mentah" yang berasal dari ADC dan yang mana sensornya dikonversi ke estimasi CO2 menggunakan metode slave? Jika demikian, ini membuka peluang besar untuk kalibrasi ulang dan meningkatkan akurasi sensor, dan mungkin untuk menggunakannya untuk tujuan lain. Jawaban untuk pertanyaan ini (dan beberapa lainnya) akan kami coba masuk dalam seri selanjutnya.

Komentar dan saran diterima - bagaimana lagi untuk mengejek MH-Z19 di artikel berikutnya. Benar, saya tidak akan menjanjikan apa pun.

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


All Articles