ModBus TCP communication using Ruby: failing to implement HelloWorld - ruby

I am able to communicate with a ventilation installation (Helios KWL EC 500 W which supports holding registers only, english description starts at 50% of the file) using the modpoll utility v3.4. But I failed to transfer the very first communication to Ruby and the rmodbus library v1.3.3.
With modpoll, I may request some temperature value with the command
./modpoll -m tcp -a 180 <ipaddr> 0x7630 0x3031 0x3034 0x0000
and then read the data using
./modpoll -m tcp -a 180 -t4:hex -c 8 -0 -1 <ipaddr>
Protocol configuration: MODBUS/TCP
Slave configuration...: address = 180, start reference = 1 (PDU), count = 8
Communication.........: x.x.x.x, port 502, t/o 2.00 s, poll rate 1000 ms
Data type.............: 16-bit register (hex), output (holding) register table
-- Polling slave...
[1]: 0x7630
which outputs 8 16bit registers as stated as example in the Helios modbus documentation. As very first step, I tried to move the read part to Ruby. However, my Ruby code times out:
require 'rmodbus'
ModBus::TCPClient.new(ipaddr, 502) do |client|
client.with_slave(1) do |slave|
slave.debug = true
puts slave.holding_registers[180..187]
end
end
and throws the exception
/var/lib/gems/2.3.0/gems/rmodbus-1.3.3/lib/rmodbus/slave.rb:241:in `rescue in query':
Timed out during read attempt (ModBus::Errors::ModBusTimeout)
from /var/lib/gems/2.3.0/gems/rmodbus-1.3.3/lib/rmodbus/slave.rb:232:in `query'
from /var/lib/gems/2.3.0/gems/rmodbus-1.3.3/lib/rmodbus/slave.rb:164:in `read_holding_registers'
What's wrong?
I am not sure if / how to use the parameters output by modpoll "address =180" and "start reference =1". Is "address" equivalent to "holding register #"?

Okay, this one was rather stupid. For the records (and others who might want to talk to their Helios using rmodbus):
slave.debug = 1
turns on the debugging which outputs the byte stream sent to the modbus slave. The first bytes sequence is supposed to be: transaction number (2 byte), protocol specifier (2 byte, always zero), size of the following message (2 byte), unit identifier (1 byte, always 180 for Helios KWL).
The slave needs to be initialized with its unit identifier 180, instead of 1:
client.with_slave(180) do |slave|

Related

how to capture all packet size using windows pktmon

I am trying to use pktmon(built-in windows packet analyzer). However from the documentation they mention that by default packet size is limited to 128 bytes but can be increase with the following command pktmon start --etw -p 0.
But running that command gives me this error Error: '0' is not a valid event provider Id. what could be wrong?
So far I've not seen anything helpful on the internet.
Most of the examples on the internet show
pktmon start --etw -p 0 -c 1
The -p doesn't seem to work and also the -c.
So what worked for me is
pktmon start --etw --pkt-size 0 --comp 1
From the utility help:
--pkt-size
Number of bytes to log from each packet. To always log the entire
packet set this to 0. Default is 128 bytes.

Error during go build/run execution

I've created a simple go script: https://gist.github.com/kbl/86ed3b2112eb80522949f0ce574a04e3
It's fetching some xml from the internet and then starts X goroutines. The X depends on file content. In my case it was 1700 goroutines.
My first execution finished with:
$ go run mathandel1.go
2018/01/27 14:19:37 Get https://www.boardgamegeek.com/xmlapi/boardgame/162152?pricehistory=1&stats=1: dial tcp 72.233.16.130:443: socket: too many open files
2018/01/27 14:19:37 Get https://www.boardgamegeek.com/xmlapi/boardgame/148517?pricehistory=1&stats=1: dial tcp 72.233.16.130:443: socket: too many open files
exit status 1
I've tried to increase ulimit to 2048.
Now I'm getting different error, script is the same thou:
$ go build mathandel1.go
# command-line-arguments
/usr/local/go/pkg/tool/linux_amd64/link: flushing $WORK/command-line-arguments/_obj/exe/a.out: write $WORK/command-line-arguments/_obj/exe/a.out: file too large
What is causing that error? How can I fix that?
You ran ulimit 2048 which changed the maximum file size.
From man bash(1), ulimit section:
If no option is given, then -f is assumed.
This means that you now set the maximum file size to 2048 bytes, that's probably not enough for.... anything.
I'm guessing you meant to change the limit for number of open file descriptors. For this, you want to run:
ulimit -n 2048
As for the original error (before changing the maximum file size), you're launching 1700 goroutines, each performing a http get. Each creates a connection, using a tcp socket. These are covered by the open file descriptor limit.
Instead, you should be limiting the number of concurrent downloads. This can be done with a simple worker pool pattern.

Commands not accepted by instrument over RS232 w/ ruby serialport script

MY ENVIRONMENT
I'm sending commands to a camera simulator device made by Vivid Engineering (Model CLS-211) over RS-232 from my laptop which is running CentOS 7.
ISSUE
I have installed two different serial monitors (minicom, gtkterm) and can successfully send successive commands over and over to the device. I can send a command to dump the memory contents as well. There are several configuration commands I have to send to the CLS-211 to set it up per a specific test. I want to automate this process and have written a ruby script to write a list of commands to the CLS-211 to make this process easier. However, it appears that I am not terminating each command correctly or the CLS-211 requires a specific terminator/signal that I am not giving to it in my ruby script. I'm confused why I can successfully accomplish this task with a serial monitor but not a ruby script. I've configured the serial port settings correctly per their manual so I know this is not the issue. You'll see those settings below defined in my scirpts. Their manual points out they use HyperTerminal which I can't use because I'm on a Linux system. Manufacture mentioned that other serial terminals should work just fine but they have only chosen to test one out being HyperTerminal. I've asked for their feedback on the issue and they simply say "We don't use Linux but it shouldn't be much different, good luck".
TROUBLESHOOTING
I have verified that my "send.rb" script is working to the best of my knowledge by writing a "read.rb" script to read back what I sent. I essentially connected pin 2 "rx" to pin 3 "tx" on the RS-232 cable for a loopback test. Below is my two scripts and the resulting output from running this test.
## Filename send.rb
require 'serialport'
ser = SerialPort.new("/dev/ttyS0", 9600, 8, 1, SerialPort::NONE)
ser.write "LVAL_LO 5\r\n"
ser.write "LVAL_HI 6\r\n"
ser.write "FVAL_LO 7\r\n"
ser.write "FVAL_HI 8\r\n"
ser.close
## Filename read.rb
require 'serialport'
ser = SerialPort.new("/dev/ttyS0", 9600, 8, 1, SerialPort::NONE)
while true do
printf("%c", ser.getc)
end
ser.close
Just found out that I cannot post more than 2 links since my reputation is so low. Anyways the output is just the following...
username#hostname $ ruby read.rb
LVAL_LO 5
LVAL_HI 6
FVAL_LO 7
FVAL_HI 8
I have hooked up the CLS-211 and dumped the memory contents by issuing the DUMP command using GtkTerm and this works fine. The following image shows the memory contents of the first four parameters being LVAL_LO, LVAL_HI, FVAL_LO, and FVAL_HI. I'm just choosing to show four values in the memory dump for the sake of keeping this thread short versus listing all of them. Since I cannot include more than 2 links because my reputation is low being a new guy I'm typing what the output looks like in GtkTerm instead...
CLS-211 initializing, please wait
............
ready
CLS211 Camera Link Simulator CLI
Vivid Engineering
Rev 3.0
DUMP
LVAL_LO = 0x0020 / 32
LVAL_HI = 0x0100 / 256
FVAL_LO = 0x0002 / 2
FVAL_HI = 0x0100 / 256
In the above image you can clearly see that the system boots as expected. After I typed in the command "DUMP" it printed out the memory contents successfully. You see that LVAL_LO = 32, LVAL_HI = 256, FVAL_LO = 2, and FVAL_HI = 256. As I mentioned before I can successfully type in a command to GtkTerm to change a specific parameter as well. The below images shows that after typing in the command LVAL_LO 5 to GtkTerm and then issuing a DUMP command the value 5 was read correctly and LVAL_LO was changed as expected. I can replicate this successful behavior with every command using GtkTerm.
Again, I can't post more than 2 links so I'm writing the output below...
LVAL_LO 5
DUMP
LVAL_LO = 0x0005 / 5
LVAL_HI = 0x0100 / 256
FVAL_LO = 0x0002 / 2
FVAL_HI = 0x0100 / 256
At this point I was like ok everything is working as expected. Lets see if I can execute my ruby script and replicate the same successfully. I then ran the script I typed up above titled "send.rb". Then I opened up GtkTerm and issued a DUMP command afterwards to see if those values were taken. Let it be known that before I ran "send.rb" the values that existed in memory on the CLS-211 were LVAL_LO = 32, LVAL_HI = 256, FVAL_LO = 2, and FVAL_HI = 256. You can see that after running "send.rb", opening GtkTerm back up and issuing the DUMP command the CLS-211 replied w/ "invalid entry". After issuing it again you'll see that it dumped the contents of memory and showed LVAL_LO was changed correctly but the other three values were not.
Almost Successful
At this point I assumed that the first value was being received and written to the memory contents of the CLS-211 correctly but the other commands were not being received correctly. I assumed this was most likely because of the lack of any delay. Therefore, I placed a 1 second delay between each ser.write command. I changed the script "send.rb" to the following.
## Filename send.rb
require 'serialport'
ser = SerialPort.new("/dev/ttyS0", 9600, 8, 1, SerialPort::NONE)
ser.write "LVAL_LO 9\r\n"
sleep(1)
ser.write "LVAL_HI 10\r\n"
sleep(1)
ser.write "FVAL_LO 11\r\n"
sleep(1)
ser.write "FVAL_HI 12\r\n"
sleep(1)
ser.close
The following is the result of running "send.rb" again with the above changes, opening up GtkTerm, and executing the DUMP command to verify memory.
Added sleep(1)
Nothing really changed. I was able to tell that the script took longer to execute and the first value did change but like before the last three values I sent did not get received and saved to memory on the CLS-211.
CONCLUSION
How can I continue troubleshooting this issue? What sort of terminations are happening to each command that I send through GtkTerm and is that different from what I have sent in my ruby script "send.rb" being "...\r\n". Totally lost and out of options on what I can do next.
[EDIT/UPDATE 10/09/17]
I'm so stupid. The one termination character I forgot to try out "by itself" was carriage return "\r". Using a carriage return by itself after each command fixed the issue. I'm curious what requirements drive a manufacturer to define how a serial packet should be constructed in terms of a termination character(s). I would think there would be a predefined standard to what termination character(s) should be used. For completeness I have included my code below to what it should be in the case of communicating correctly with the CLS-211 device. Basically, i took out the '\n' and kept the '\r' that was it.
## Filename send.rb
require 'serialport'
ser = SerialPort.new("/dev/ttyS0", 9600, 8, 1, SerialPort::NONE)
ser.write "LVAL_LO 9\r"
sleep(1)
ser.write "LVAL_HI 10\r"
sleep(1)
ser.write "FVAL_LO 11\r"
sleep(1)
ser.write "FVAL_HI 12\r"
sleep(1)
ser.close

Linpack sometimes starting, sometimes not, but nothing changed

I installed Linpack on a 2-Node cluster with Xeon processors. Sometimes if I start Linpack with this command:
mpiexec -np 28 -print-rank-map -f /root/machines.HOSTS ./xhpl_intel64
linpack starts and prints the output, sometimes I only see the mpi mappings printed and then nothing following. To me this seems like random behaviour because I don't change anything between the calls and as already mentioned, Linpack sometimes starts, sometimes not.
In top I can see that xhpl_intel64processes have been created and they are heavily using the CPU but when watching the traffic between the nodes, iftop is telling me that it nothing is sent.
I am using MPICH2 as MPI implementation. This is my HPL.dat:
# cat HPL.dat
HPLinpack benchmark input file
Innovative Computing Laboratory, University of Tennessee
HPL.out output file name (if any)
6 device out (6=stdout,7=stderr,file)
1 # of problems sizes (N)
10000 Ns
1 # of NBs
250 NBs
0 PMAP process mapping (0=Row-,1=Column-major)
1 # of process grids (P x Q)
2 Ps
14 Qs
16.0 threshold
1 # of panel fact
2 PFACTs (0=left, 1=Crout, 2=Right)
1 # of recursive stopping criterium
4 NBMINs (>= 1)
1 # of panels in recursion
2 NDIVs
1 # of recursive panel fact.
1 RFACTs (0=left, 1=Crout, 2=Right)
1 # of broadcast
1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM)
1 # of lookahead depth
1 DEPTHs (>=0)
2 SWAP (0=bin-exch,1=long,2=mix)
64 swapping threshold
0 L1 in (0=transposed,1=no-transposed) form
0 U in (0=transposed,1=no-transposed) form
1 Equilibration (0=no,1=yes)
8 memory alignment in double (> 0)
edit2:
I now just let the program run for a while and after 30min it tells me:
# mpiexec -np 32 -print-rank-map -f /root/machines.HOSTS ./xhpl_intel64
(node-0:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
(node-1:16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31)
Assertion failed in file ../../socksm.c at line 2577: (it_plfd->revents & 0x008) == 0
internal ABORT - process 0
APPLICATION TERMINATED WITH THE EXIT STRING: Hangup (signal 1)
Is this a mpi problem?
Do you know what type of problem this could be?
I figured out what the problem was: MPICH2 uses different random ports each time it starts and if these are blocked your application wont start up correctly.
The solution for MPICH2 is to set the environment variable MPICH_PORT_RANGE to START:END, like this:
export MPICH_PORT_RANGE=50000:51000
Best,
heinrich

Asynchronous Read/Writing with libraw1394

I'm trying to get two computers to communicate with each other over firewire. Both of the computers are running Ubuntu 9.10 and both have read/write access to the /dev/raw1394 node. I'm using firecontrol to quickly test sending read/write requests. If I can get it to work with firecontrol, I should be able to figure out how to do the same in my code.
On computer A, I do this:
computerA $ ./commander
Work Now
Copyright (C) 2002-2007 by Manfred Weihs
This software comes with absolutely no warranty.
No adapter specified!
successfully got handle
current generation number (driver): 1
1 card(s) found
nodes on bus: 2, card name: ohci1394
using adapter 0
found: 2 nodes on bus, local ID is 1, IRM is 1
current generation number (adapter): 7
entering command mode
Type 'help' for more information!
Command: w . 0 0 0xDE
insufficient arguments for operation!
Command: w . 0 0 2 0xDe
writing to node 0, bus 1023, offset 000000000000 2 bytes:
00 DE
write succeeded.
Ack code: complete
Since computer A is on node 1, I send to node 0. Then I go to computer B and read from node 0 and get this:
computerB $ ./commander
Copyright (C) 2002-2007 by Manfred Weihs
This software comes with absolutely no warranty.
No adapter specified!
successfully got handle
current generation number (driver): 1
1 card(s) found
nodes on bus: 2, card name: ohci1394
using adapter 0
found: 2 nodes on bus, local ID is 0, IRM is 1
current generation number (adapter): 9
entering command mode
Type 'help' for more information!
Command: r . 0 0 1
reading from node 0, bus 1023, offset 000000000000 1 bytes
read failed.
Ack code: pending; Response code: address error
I'm using the same offset for both of them. What am I doing wrong and how am I supposed to read/write from/to firewire nodes?
I have these same problems when I try and use raw1394 in my own code.

Resources