Open PAIDI-RAMESH opened 4 years ago
Thank you for the issue.
a. what error do you get ? b. can you run with debug on ? c. how often do you get the error ?
can you send a pull request fixing it ?
I'm running this on a oscilloscope and can see that the modbus-serial code is transmitting 16 bit numbers for every register address and data field over the wire. I can't tell what the module expects with the oscilloscope.
This would obviously mess up the CRCs if the device was using 8 bit registers.
(Un?)fortunately, I am definitely not a javascript programmer and have no business fixing this for others. An FYI, the module definitely doesn't strictly enforce uint8_t in all the things.
@exitrip : I'm a software developer and I'm facing the same thing on my project. Do you think you can help me with the debugging sessions? I'm not that good at electronics but did some studies previously. I'm only interested how did you've figure it out and to to debug actually. I am looking forward to fix this and add a PR to the repo, @yaacov .
@alexszilagyi I ended up implementing everything using https://github.com/serialport/node-serialport directly and grabbing CRC javascript off a few websites. Unfortunately can't share the whole working source, as it's for a client, but I'll paste some boilerplate and open snippets:
const SerialPort = require('serialport')
const InterByteTimeout = require('@serialport/parser-inter-byte-timeout')
const portPath = '/dev/ttyUSB1';
var port = new SerialPort(portPath, {
baudRate: 9600,
dataBits: 8,
parity: 'none',
stopBits: 1,
flowControl: false
})
/*
* The recieve thread
*/
parser.on('data', function (data) {
//format the data buffer as a hex string and calc the crc
for (let hex of hexFormatValues(data)) {
rx_packet += hex;
}
rx_crc = calculateCRCString(rx_packet);
//because of the magic of CRCs, if we calculate a '0' crc
// we have recieved a valid packet (or all 0's)
// we also reset the read if we somehow got any nulls
// (these things happen)
if(parseInt(rx_crc, 16) === 0 || !rx_crc ||
!rx_packet || parseInt(rx_packet, 16) === 0) {
// TODO process rx packet and then zero it out
if (parseInt(rx_crc, 16) === 0) {
//TODO this is where you have a valid response
console.log('RX: ', rx_packet);
}
rx_packet = '';
console.log('-')
}
})
/*
* Stock/boilerplate serialport code
*/
// Open errors will be emitted as an error event
port.on('error', function(err) {
console.log('Error: ', err.message)
})
/*
* Functions of convenience I scraped off the internet and modified
*/
function calculateCRCString ( input ) {
var crc = 0xFFFF;
//no input verification TODO
var str = hexStringToString(input);
for (var pos = 0; pos < str.length; pos++) {
crc ^= str.charCodeAt(pos);
for (var i = 8; i !== 0; i--) {
if ((crc & 0x0001) !== 0) {
crc >>= 1;
crc ^= 0xA001;
} else
crc >>= 1;
}
}
//crc is a number,
// we need to build a string with swapped bytes for modbus
// Modbus is LSB first!!! Do this to every 16 bit number
crc = ((crc & 0x00ff) << 8) + ((crc & 0xff00) >> 8);
return crc.toString(16);
}
function hexStringToString (inputstr) {
var hex = inputstr.toString(); //force conversion
var str = '';
for (var i = 0; i < hex.length; i += 2)
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
return str;
}
function* hexFormatValues(buffer) {
for (let x of buffer) {
const hex = x.toString(16)
yield hex.padStart(2, '0')
}
}