Open goranach opened 11 years ago
Hey!
I've added a few examples to the example/ directory. Check out the verbose-init-tcp-ip.js especially, as it also has some comments.
The automated tests are not finished, so there may be bugs. Some features (like functions for handling of repeatable transactions) are not yet present.
As I was writing the code, I've tested it against Modbus PLC Simulator (can be used to quickly run the examples), some Delta PLC (Serial+ASCII, Serial+RTU, TCP+IP), Array APB PLC and Delta+Moxa NPort (TCP+ASCII -> Serial+ASCII, UDP+ASCII -> Serial+ASCII...).
The proper readme and documentation will be done after 100% test code coverage, which in turn may be done if I'll have to do another application that requires MODBUS.
Until then, feel free to ask any questions here ;)
Do you have any examples using Serial RTU? The project looks pretty solid however I am struggling with reading and writing holding registers over serial RTU. Any small example using your project would be wonderful.
You'll need node-serialport:
npm install serialport
Then, create the master like so:
var SerialPort = require('serialport').SerialPort;
var modbus = require('h5.modbus');
var serialPort = new SerialPort('/dev/ttyUSB0', {
baudRate: 9600,
dataBits: 8,
stopBits: 2,
paritry: 'none'
});
var master = modbus.createMaster({
transport: {
type: 'rtu',
eofTimeout: 10, // End of frame timeout
connection: {
type: 'serial',
serialPort: serialPort
}
}
});
// ...
Thanks for the quick reply. I will fiddle about and let you know how everything goes.
Thanks again for the help. One more question (then I think I am good to get this rolling on my own).
I am attempting to connect to my device and just read a single holding register, however immediately after running master.readHoldingRegisters(1,1,opts)
i'm receiving a timeout error (no delay is waited) - shortly after the retries and stuff happen.
events.js:72
throw er; // Unhandled 'error' event
^
ResponseTimeoutError: No response was received from the slave in the specified time.
at Transaction.handleTimeout (/home/rlemon/dryermaster/modbus/lib/Transaction.js:452:20)
at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
Have you ever seen this while working with the library? What was the general cause of it to not want to communicate? I have tested that the device does communicate properly on windows with other software via modbus RTU.
I appreciate your time.
Thanks, rlemon.
You have to listen for the error
events on the transaction object returned by the readHoldingRegisters()
or set the master's supressTransactionErrors
to true
(master and transaction objects are node.js EventEmitters and they throw an exception if an error
event was emitted, buy there is no listeners):
// ...
var master = modbus.createMaster({
suppressTransactionErrors: true, // automatically adds a listener for the `error` events to every transaction
transport: {
// ...
}
});
var req = master.readHoldingRegisters(1, 1, opts);
req.on('error', function(err)
{
console.error(err.message);
});
If you have a lot of timeout errors, then try to increase the timeout options until they are gone (master's defaultTimeout
option or transaction's timeout
option).
Sorry to continue to bother you. We're having some real issues - I presumed to change the slaveID I would change the unit in the Transaction Options.. but reading the stream on the other end I'm seeing the slave as 00
?? How do I set the slave ID?
master.readHoldingRegisters(0, 1, {unit: 1})
What Connection and Transport are you using? Serial RTU?
Sorry false alarm. I have another gentleman working on this with me and he hard coded the unit in the Transaction file to 13 (and tera term makes D and 0 look incredibly alike) - So we were actually seeing 0D (13) - reverted the file and it works as expected. Sorry for jumping the gun.
Sorry, to bother you. I'm working along side rlemon on this code. Unfortunately, as it stands the modbus library defaults to START_LOW_COIL = 1, but we want it to start at 0. Here's my calling procedure:
var transactionOptions = {
timeout: 10000,
unit: 1
};
var req = master.readHoldingRegisters( 1 , 1 , transactionOptions);
Is there a default variable, analogous to 'timeout' or 'unit' in the code sample above, that we can specify to force it to start at 0?
The frame data it currently outputs is: "01 03 00 01 00 01 D5 CA".
Thanks
Why don't you pass 0
as the first argument?
// readHoldingRegisters(address, quantity, options)
master.readHoldingRegisters(1, 1, {unit: 1})
// results in frame
// 01 - unit
// 03 - function code
// 00 01 - address
// 00 01 - quantity
// D5 CA - checksum
master.readHoldingRegisters(0, 1, {unit: 1})
// should result in frame
// 01 - unit
// 03 - function code
// 00 00 - address
// 00 01 - quantity
// xx xx - checksum
Awesome!!! It works!!! Thanks a bunch.
I have a terminal monitoring packets sent and received and I am finally getting a response packet from the slave of: 01 03 02 00 00 B8 44 which looks perfect and the CRC checks out, but the modbus code doesn't receive anything. It just times out with the message: 'ERR [ { name: 'ResponseTimeoutError', message: 'No response was received from the slave in the specified time.' }, undefined, undefined ] ' Again the code is,
var SerialPort = require('serialport').SerialPort,
modbus = require('./lib');
var portOptions = {
baudRate: 19200,
dataBits: 8,
stopBits: 1,
parity: 'none',
flowControl: false
};
var serialPort = new SerialPort('/dev/ttyO2', portOptions, true, startScan);
function startScan() {
var master = modbus.createMaster({
suppressTransactionErrors: true,
transport: {
type: 'rtu',
eofTimeout: 100000,
connection: {
type: 'serial',
serialPort: serialPort
}
}
});
var transactionOptions = {
timeout: 10000,
unit: 1
};
var req = master.readHoldingRegisters( 0 , 5 , transactionOptions);
req.on('response', function(a,b,c) {
console.log('RESP', [a,b,c]);
}).on('complete', function(a,b,c) {
console.log('COMPL', [a,b,c]);
}).on('error', function(a,b,c) {
console.log('ERR', [a,b,c]);
});
}
Is there anyway that I can dump or check if data is received? Thanks in advance.
Modbus RTU separates frames by not sending anything for a specific amount of time ("at least 3 1⁄2 character times of silence between frames", see Wikipedia). I don't think you can wait 3 1/2 character times in Node.js so I've introduced the eofTimeout
option. After the data is received, the RTU transport waits eofTimeout
milliseconds, and if no more data is received, then an end of frame is assumed. If more data arrives before the eofTimeout
ms, then the end of frame timer is restarted.
You have set the eofTimeout
to 100 seconds, so the RTU transport will parse the frame after 100s.
BUT
You have also set the timeout
to 10 seconds, which is less than eofTimeout
and finishes first. There's your ResponseTimeoutError
.
Try setting the timeout
option to 200
and the eofTimeout
to 20
.
If you'll receive a lot of ResponseTimeoutError
s, then slowly increase the timeout
option.
If you'll receive a lot of IncompleteResponseFrameError
s or InvalidChecksumError
s, then slowly increase the eofTimeout
option.
That did it!!! Thanks again.
Hey, do you have any examples of using ascii?
I have been successfully using your rtu example but switching over to ascii I keep getting a "ResponseTimeoutError". I connected a network analyzer and my device is getting everything correct, I just can't figure out how to tell the listener that there is a response waiting.
Hey! Try increasing the master's defaultTimeout
option or transaction's timeout
option.
See https://gist.github.com/morkai/f7b11f971682fc8e5598
Thanks for the quick response! Did a complete wipe of my source and that fixed it. I must have tried modifying something in the h5.modbus source. Responses are coming through in ~50 ms now so the defaultTimeout wasn't the issue (I was...).
Should 'eofTimeout' be a function of the baud rate?...
It should, but it won't work in node.js. For baud rates >= 19200 it should be 1.75 ms, for 9600 - 3.65 ms. Node isn't reliable with such small timers, so you should just test what is the smallest value that works for you.
Hey, I try to make scada app in node.js ,i need modbus-tcp but i haven't find any example that explain modbus with node.js , i have installed modbus-tcp module but i don't find an example and modbus simulator ?? Please i need your help
Look into the example/ directory or check out any project of mine that is using this library.
I am interested in this project. but the node version is too high. is V0.10.X will be possible?
The one from the master branch won't work (unless you transpile it using something like Babel).
The old version will work: https://github.com/morkai/h5.modbus/tree/v0
I am very interested in your project, as it only meets my requirements. Could you write a small documentation for me. Thanks in advance.