NEWS
Скрипт для датчика CO2 MH-Z14 (MH-Z19)
-
Датчик:
https://ru.aliexpress.com/item/Free-shi … 6141ebe467
Адаптер:
https://ru.aliexpress.com/item/FT232RL- ... 0.0.DBxfZO
var device_port = '/dev/ttyUSB2'; var buflen = 64; var sleep_time = 200; // Sleep time between request and wait for response. var SerialPort = require('serialport'); var ByteLength = SerialPort.parsers.ByteLength; var ppm; var cmd_init = new Buffer ([0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79]); var cmd_set_zero = new Buffer ([0xFF, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78]); function toHexString(byteArray) { return Array.from(byteArray, function(byte) { return ('0' + (byte & 0xFF).toString(16)).slice(-2); }).join(''); } function co2_gd(cmd,buflen,callback) { var port = new SerialPort(device_port,{ baudrate: 9600, dataBits: 8, parity: 'none' }); const parser = port.pipe(new ByteLength({length: buflen})); port.pipe(parser); port.write(cmd); setTimeout(readport, sleep_time); function readport () { parser.on ('data', function (result) { ppm = null; var CRC_calc=0; var b2 = parseInt(toHexString(result.slice(3,4)),16); var b3 = parseInt(toHexString(result.slice(5,6)),16); var b4 = parseInt(toHexString(result.slice(7,8)),16); var b5 = parseInt(toHexString(result.slice(9,10)),16); var b6 = parseInt(toHexString(result.slice(11,12)),16); var b7 = parseInt(toHexString(result.slice(13,14)),16); var b8 = parseInt(toHexString(result.slice(15,16)),16); var CRC_get = parseInt(toHexString(result.slice(17,18)),16); CRC_calc = (255 - (b2 + b3 + b4 + b5 + b6 + b7 + b8) % 256) + 1; if (CRC_get != CRC_calc) { console.log ('CRC ERROR'); console.log ('result='+JSON.stringify(result)); console.log('b='+b2+' '+b3+' '+b4+' '+b5+' '+b6+' '+b7+' '+b8 ); console.log('CRC_get='+(CRC_get)); console.log('CRC_calc='+(CRC_calc)); } else { //console.log ('CRC CO2 is OK'); //console.log ('result='+JSON.stringify(result)); //console.log('b='+b2+' '+b3+' '+b4+' '+b5+' '+b6+' '+b7+' '+b8 ); //console.log('CRC_get='+(CRC_get)); //console.log('CRC_calc='+(CRC_calc)); var Hibyte = toHexString(result.slice(5,6)); var Lowbyte = toHexString(result.slice(7,8)); ppm = parseInt(Hibyte,16)*256+parseInt(Lowbyte,16); //console.log('Hibyte='+Hibyte); //console.log('Lowbyte='+Hibyte); //console.log('ppm='+ppm); if (ppm> 5000 ) { console.log ('CRC OK'); console.log('Hibyte='+Hibyte); console.log('Lowbyte='+Hibyte); console.log('ppm='+ppm); console.log ('result='+JSON.stringify(result)); console.log('b='+b2+' '+b3+' '+b4+' '+b5+' '+b6+' '+b7+' '+b8 ); console.log('CRC_get='+(CRC_get)); console.log('CRC_calc='+(CRC_calc)); ppm = null; } } if (callback && typeof(callback) === "function") { callback(ppm); } }); //parser.on port.pause(); port.close(); return (ppm); } } //end function co2_gd //co2_gd(cmd_set_zero,18, function(data) {} ); //Set CO2 level as zero (400 ppm) schedule("* * * * *", function () { co2_gd(cmd_init,18, function(data) { //console.log('CO2 ppm='+data); setState("javascript.0.CO2_1f_uart",data); }); });
-
Не работает.
8:10:37.273 [info] javascript.0 Start javascript script.js.common.co2_mh_z19
18:10:37.274 [info] javascript.0 script.js.common.co2_mh_z19: registered 0 subscriptions and 1 schedule
18:11:00.281 [info] javascript.0 script.js.common.co2_mh_z19: request={"type":"Buffer","data":[255,1,134,0,0,0,0,0,121]}
18:11:00.508 [info] javascript.0 script.js.common.co2_mh_z19: –-----------------
18:11:00.509 [info] javascript.0 script.js.common.co2_mh_z19: CRC ERROR
18:11:00.510 [info] javascript.0 script.js.common.co2_mh_z19: result={"type":"Buffer","data":[255,255,134,2,142,86,134,2,142,86,4,4,58,58,137,137,205,205]}
18:11:00.510 [info] javascript.0 script.js.common.co2_mh_z19: b=2 86 2 86 4 58 137
18:11:00.510 [info] javascript.0 script.js.common.co2_mh_z19: CRC_get=205
18:11:00.511 [info] javascript.0 script.js.common.co2_mh_z19: CRC_calc=137
Добавлял отладочный вывод запросов - такое впечатление, что отсылается команда чтения два раза и потом в буфере приемном все перемешано, вот и лажа.
-
А никому не приходилось бороться со странными зависами при setTimeout в скриптах?
Переделал скрипт из темы, несколько раз получил результаты и теперь мертвые висы.
console.log('wait response'); setTimeout(readport, 200); function readport() { console.log('readport enter');
в логе вижу первый вывод в консоль - и все, глухой вис. в top висит процесс iobroker.javascript с 100% загрузкой, драйвер javascript в панели тоже останавливается. Приходится вручную процесс убивать.
Иногда по непонятной причине - проходит, результат получается нормально.
-
Не работает.
CRC ERROR
18:11:00.510 [info] javascript.0 script.js.common.co2_mh_z19: result={"type":"Buffer","data":[255,255,134,2,142,86,134,2,142,86,4,4,58,58,137,137,205,205]}
Добавлял отладочный вывод запросов - такое впечатление, что отсылается команда чтения два раза и потом в буфере приемном все перемешано, вот и лажа. `
Дело в том что мне попадались 2 типа USB-Uart адаптера.
В первом случае ответы дублируются побайтно, а во втором - ответ дублируется целиком.
При чём у разных адаптеров разный % CRC Error.
В вашем случае побайтный дубль (как у меня) и видно - что идёт сбой ответа - не все байты попарно одинаковы.
Длина кабеля?
Уверены что нет просадки напряжения на самом датчике в моменты ИК-свечения (ток вроде 300мА)?
Какой у вас адаптер?
В первые пару минут - CRC error это нормально.
Попробуйте другой адаптер.
У меня на таком FTDI_FT232R_USB_UART_AH05SK6S CRC ошибок менее ~3 %
P.S.Мой скрипт написан для MH-Z14, на MH-Z19 ещё не проверял. Скоро проверю, сам датчик уже есть. Судя по документации логика абсолютно одинаковая.
-
А никому не приходилось бороться со странными зависами при setTimeout в скриптах?
Переделал скрипт из темы, несколько раз получил результаты и теперь мертвые висы.
console.log('wait response'); setTimeout(readport, 200); function readport() { console.log('readport enter');
в логе вижу первый вывод в консоль - и все, глухой вис. в top висит процесс iobroker.javascript с 100% загрузкой, драйвер javascript в панели тоже останавливается. Приходится вручную процесс убивать.
Иногда по непонятной причине - проходит, результат получается нормально. `
Какая OS?Сколько свободной памяти показывает iobroker?
-
Дело в том что мне попадались 2 типа USB-Uart адаптера.
В первом случае ответы дублируются побайтно, а во втором - ответ дублируется целиком.
При чём у разных адаптеров разный % CRC Error.
В вашем случае побайтный дубль (как у меня) и видно - что идёт сбой ответа - не все байты попарно одинаковы.
Длина кабеля?
Уверены что нет просадки напряжения на самом датчике в моменты ИК-свечения (ток вроде 300мА)?
Какой у вас адаптер?
В первые пару минут - CRC error это нормально.
Попробуйте другой адаптер.
У меня на таком FTDI_FT232R_USB_UART_AH05SK6S CRC ошибок менее ~3 %
P.S.Мой скрипт написан для MH-Z14, на MH-Z19 ещё не проверял. Скоро проверю, сам датчик уже есть. Судя по документации логика абсолютно одинаковая. `
адаптер прямо в порту торчит. чип CP2102. датчик - проводочки сантиметров пять. Просадку не смотрел. Два разных адаптера (одинаковых, впрочем, по чипу и схеме).
Скрипт на питоне - работает как из пушки. Ни одной ошибки.
import MySQLdb import string import time import serial from datetime import datetime ser = serial.Serial('/dev/ttyUSB0', baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=1.0) result=ser.write("\xff\x01\x86\x00\x00\x00\x00\x00\x79") s=ser.read(9) if s[0] == "\xff" and s[1] == "\x86": co2 = ord(s[2])*256 + ord(s[3]) print "co2=", co2 ts = time.time() ts1 = int(ts * 1000) print "ts=", ts1 db = MySQLdb.connect(host="localhost", user="xxxx", passwd="xxxxx", db="iobroker", charset="utf8") cursor = db.cursor() sql = """insert iobroker.ts_number(id, ts, val, ack, _from, q) values (12,%(ts)s,%(val)s,0,2,0) """ %{"ts":ts1, "val":co2} print "sql=", sql cursor.execute(sql) db.commit() db.close()
-
Какая OS?
Сколько свободной памяти показывает iobroker? `
Ubuntu 16.04LTS.
Всего RAM - Используется: 325 Мб / Свободно: 176 Мб (9%) [Сервер: atom-nb - 9 процессов]
%Cpu(s): 8,0 us, 2,0 sy, 0,0 ni, 87,0 id, 3,0 wa, 0,0 hi, 0,0 si, 0,0 st
КиБ Mem : 2050484 total, 179628 free, 520800 used, 1350056 buff/cache
КиБ Swap: 8269820 total, 8203072 free, 66748 used. 1233352 avail Mem
-
Какая OS?
Сколько свободной памяти показывает iobroker? `
Ubuntu 16.04LTS.
Всего RAM - Используется: 325 Мб / Свободно: 176 Мб (9%) [Сервер: atom-nb - 9 процессов]
%Cpu(s): 8,0 us, 2,0 sy, 0,0 ni, 87,0 id, 3,0 wa, 0,0 hi, 0,0 si, 0,0 st
КиБ Mem : 2050484 total, 179628 free, 520800 used, 1350056 buff/cache
КиБ Swap: 8269820 total, 8203072 free, 66748 used. 1233352 avail Mem `
У меня драйвер javascript при работе с ком-портами периодически самоперегружается, поэтому я скрипты работающие с ком-портами запускаю в дополнительной инстанции, чтобы сбой не повлиял на работу других скриптов. Причина где то в недрах библиотеки serialport nodejs. По идее надо дебажить и создавать issue на https://github.com/node-serialport/node … ort/issues
-
адаптер прямо в порту торчит. чип CP2102. датчик - проводочки сантиметров пять. Просадку не смотрел. Два разных адаптера (одинаковых, впрочем, по чипу и схеме).
Скрипт на питоне - работает как из пушки. Ни одной ошибки. `
Попробуй поменять в коде на````
var buflen = 9;Ещё вероятно причина в драйвере serialport. Видно же что ответ ненормальный идёт. Сделайте дебаг вывод ответа питона и сравните с nodejs. С питоном также дублированы байты ответа? Когда работает с портом iobroker (nodejs) - другие скрипты на уровне OS (питон) с этим портом не работают?
-
12:25:19.724 [info] javascript.0 script.js.common.Скрипт1: registered 0 subscriptions and 1 schedule
12:26:00.729 [error] javascript.0 at co2_gd (script.js.common.Скрипт1:20:16)
12:26:00.730 [error] javascript.0 at Object. (script.js.common.Скрипт1:93:5)
20 var port = new SerialPort(device_port,{
93 co2_gd(cmd_init,18, function(data) {
с питоном ничего не дублируется, с терминалкой тоже все ок. никаких других скриптов кроме этого вообще нет. питон на время экспериментов остановил.
похоже, что-то в недрах nodejs.serialport очень странно работает.
-
с питоном ничего не дублируется, с терминалкой тоже все ок. никаких других скриптов кроме этого вообще нет. питон на время экспериментов остановил.
похоже, что-то в недрах nodejs.serialport очень странно работает. `
Посмотреть кто занял порт:
fuser /dev/ttyUSB1
Иногда javascript driver надо перезапустить чтобы порт освободить.
Это не помогло?
var buflen = 9;
-
Посмотреть кто занял порт:
fuser /dev/ttyUSB1
Иногда javascript driver надо перезапустить чтобы порт освободить. `
никто не занимает, ну и проверяю в процессах - уже вижу, если висит io.javascript c 100% загрузкой ядра - то ой. почему-то вешается именно при ожидании данных.
сделал себе вот такой вариант скрипта для проверки по этапам:
`createState('CO2_UART'); var device_port = '/dev/ttyUSB0'; var buflen = 64; var sleep_time = 200; // Sleep time between request and wait for response. var SerialPort = require('serialport'); var ByteLength = SerialPort.parsers.ByteLength; var ppm; var cmd_init = new Buffer ([0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79]); var cmd_set_zero = new Buffer ([0xFF, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78]); //var cmd_abc_off = new Buffer ([0xFF, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86]); //var cmd_abc_on= new Buffer ([0xFF, 0x01, 0x79, 0xA0, 0x00, 0x00, 0x00, 0x00, 0xE6]); function co2_gd(cmd,buflen,callback) { var port = new SerialPort(device_port,{ baudRate: 9600, dataBits: 8, parity: 'none', autoOpen: false }); port.open(function (err) { if (err) { return console.log('Error opening port: ', err.message); } console.log('port opened'); console.log ('request='+JSON.stringify(cmd)); const parser = port.pipe(new ByteLength({length: buflen})); port.pipe(parser); port.write(cmd, function(err) { if (err) { return console.log('Error on write: ', err.message); } console.log('message written'); const parser = port.pipe(new ByteLength({length: buflen})); port.pipe(parser); console.log('wait response'); setTimeout(readport, 200); function readport() { console.log('readport enter'); parser.on ('data', function (result) { console.log ('result='+JSON.stringify(result)); var i = 0; while (i < 18) { if (result[i] == result[i+1]) { i += 2; } else { if ((i + 2) < 18) { if (result[i] == result[i+2]) { console.log ('fix data at position ' + i); result[i+2] = result[i+1]; result[i+1] = result[i]; i += 2; } } } console.log('fix cycle ' + i); } ppm = null; var CRC_calc=0; var CRC_get = result[16]; CRC_calc = (255 - (result[2] + result[4] + result[6] + result[8] + result[10] + result[12] + result[14]) % 256) + 1; if (CRC_get != CRC_calc) { console.log ('CRC ERROR'); console.log('CRC_get='+(CRC_get)); console.log('CRC_calc='+(CRC_calc)); } else { ppm = result[4] * 256 + result[6]; console.log('ppm='+ppm); if (ppm> 5000 ) { console.log ('CRC OK'); console.log('ppm='+ppm); console.log('CRC_get='+(CRC_get)); console.log('CRC_calc='+(CRC_calc)); ppm = null; } } if (callback && typeof(callback) === "function") { callback(ppm); } port.pause(); port.close(); return (ppm); }) } }); }); } //end function co2_gd //co2_gd(cmd_set_zero,18, function(data) {} ); //Set CO2 level as zero (400 ppm) schedule("*/15 * * * * *", function () { console.log('co2 request'); co2_gd(cmd_init,18, function(data) { //console.log('CO2 ppm='+data); setState("CO2_UART",data); }); });` ~~[quote]~~ Это не помогло? `~~[code]~~var buflen = 9;[/code]` ` ` неа, в таком виде как скрипт из первого сообщения - вообще не хочет работать. с ошибками.[/i][/i][/i]
-
Скрипт на питоне - работает как из пушки. Ни одной ошибки. `
Что-то не видно проверки CRC на питоне. Понятно что без проверки ошибок нет -
Скрипт на питоне - работает как из пушки. Ни одной ошибки.
Что-то не видно проверки CRC на питоне. Понятно что без проверки ошибок нет :)
то был первый вариант питон принимает строго нужное количество байт, crc совпадает
-
то был первый вариант питон принимает строго нужное количество байт, crc совпадает `
CRC вычисляется в именно в строгом количестве байт, смотрите даташит на датчик. В вашем коде на питоне проверки CRC нет. -
то был первый вариант питон принимает строго нужное количество байт, crc совпадает
CRC вычисляется в именно в строгом количестве байт, смотрите даташит на датчик. В вашем коде на питоне проверки CRC нет.
я же написал, то был первый вариант….
import MySQLdb import string import time import serial from datetime import datetime ser = serial.Serial('/dev/ttyUSB0', baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=1.0) result=ser.write("\xff\x01\x86\x00\x00\x00\x00\x00\x79") s=ser.read(9) str = "" for ch in s: str += hex(ord(ch))+ " " print str crc_get = ord(s[8]) crc_calc = (255 - (ord(s[1]) + ord(s[2]) + ord(s[3]) + ord(s[4]) + ord(s[5]) + ord(s[6]) + ord(s[7]))) % 256 + 1 print "crc calc=" + hex(crc_calc) + " crc get=" + hex(crc_calc) if s[0] == "\xff" and s[1] == "\x86" and crc_calc == crc_get: co2 = ord(s[2])*256 + ord(s[3]) print "crc ok" else: co2 = 0 print "crc error" print "co2=", co2 ts = time.time() ts1 = int(ts * 1000) print "ts=", ts1 db = MySQLdb.connect(host="localhost", user="xxxxxxx", passwd="xxxxxxx", db="iobroker", charset="utf8") cursor = db.cursor() sql = """insert iobroker.ts_number(id, ts, val, ack, _from, q) values (12,%(ts)s,%(val)s,0,2,0) """ %{"ts":ts1, "val":co2} print "sql=", sql cursor.execute(sql) db.commit() db.close()
вывод исполнения
0xff 0x86 0x1 0xca 0x57 0x40 0x28 0x58 0x98
crc calc=0x98 crc get=0x98
crc ok
co2= 458
ts= 1514450008318
sql= insert iobroker.ts_number(id, ts, val, ack, _from, q) values (12,1514450008318,458,0,2,0)