Writing a Driver for Modbus/TCP

X

Thread Starter

xPCSIM

hey guys!

i've got a new task. its about writing a modbus driver which is working in xpc for a hardware (its a board which can speak modbus, profinet etc etc).

so far i got following steps made.

i made xpc run on my target IPC.
i know how to get my matlab modell on the target pc.
i know how to write sfunctions in matlab.

so the task is about writing an sfunction which is my driver to get a connection from my laptop (windows) to the IPC with xPC.

so far i made some studys about modbus all at all - and jeah it was confusing in the beginning but i now got a clue about

modbus basics like function codes, eceptions etc.
i had some looks at wireshark for a modbus connection i created between two windows pc´s with freeware (trial)

can you guys give me a little coach how to make that project now in the next steps. don't get me wrong i don't want u to tell me how to do stuff i want to find out for myself.

i just want to know how u would go on like milestones not the process description :)

ok wish u a nice day!

cya
jonas
 
Don't know if this helps....
This is a serial driver using tcl....
To use tcp/ip, try opening a socket to device, basically just another channel to tcl
e.g. <pre>
set fh [socket 192.168.3.241 502]
fconfigure $fh -blocking 0 -buffering none -translation binary</pre>
Either this can be "translated" to matlab, or just call this as an external prog from
matlab<pre>
#Get a tclkit interpreter for Win, Linux etc. from
#code.google.com/p/tclkit/
#package name modbus.tcl
#Detailed at wiki.tcl.tk/21150
#
# Abstract: serial modbus rtu plc driver
#
# Author: Steve Redler IV 06-1-2008
#
#
# Cable wiring to AutomationDirect DL05 PLC
# DB9 female 6P6C 6-pin phone plug - Port 2 on plc
# 2 rxd ------------- 4 txd /--///--/|
# 3 txd ------------- 3 rxd /__[#]__//
# 5 gnd ------------- 1 gnd |123456|/
# --------
# 7 rts --\ jumper
# 8 cts --/
#get crc16 package from
#tcllib.sourceforge.net/doc/crc16.html
source crc16.tcl
package require crc16

proc modbussendmsg {message responsesize device timeoutms} {
#change below if using socket
set fh [open $device "RDWR"]
fconfigure $fh -translation binary -mode 9600,e,8,1 -buffering none -blocking 0
flush $fh; set junk [read $fh]; # clear buffer
puts -nonewline $fh $message
flush $fh
set timeoutctr 0
set reply ""
while {[string bytelength $reply] < $responsesize && $timeoutms >= $timeoutctr } {
binary scan [read $fh] H* asciihex
if {$asciihex != ""} {
append reply $asciihex
}
after 5
incr timeoutctr 5
}
if {$timeoutms < $timeoutctr} {set reply "timeout"}
close $fh
return $reply
}

proc modbuscommand {args} {
if {[llength $args] == 7} {
foreach {slaveaddr function startreg pointcount databytes device timeoutms} $args {}
} else {
foreach {slaveaddr function startreg pointcount device timeoutms} $args {}
}

switch $pointcount {
on {set pointcount 65280}
off {set pointcount 0}
}

append message [binary format c $slaveaddr]
append message [binary format c $function]
if {$startreg != {}} {append message [binary format S $startreg]}

switch $function {
12 {if {$pointcount != {}} {append message [binary format S $pointcount]}
}
6 {append message [binary format H* $pointcount]}
15 -
16 {append message [binary format S $pointcount]
append message [binary format c [expr [string length $databytes] /2]]
append message [binary format H* $databytes]
}
22 {#not available in DL05/06
append message [binary format H* $pointcount]
append message [binary format H* $databytes]
}
default {if {$pointcount != {}} {append message [binary format S $pointcount]}
}
}

set checksum [::crc::crc16 -seed 0xFFFF $message]
set checksum [binary format s $checksum]
append message $checksum
#binary scan $message H* msg ; puts "msg=$msg"
switch $function {
1 -
2 {set responsesize [expr $pointcount / 4 +5 *2]}
3 {set responsesize [expr $pointcount * 4 +5 *2]}
4 {set responsesize [expr $pointcount * 4 +5 *2]}
default {set responsesize 12}
}
set result [modbussendmsg $message $responsesize $device $timeoutms]
if {$result == "timeout"} {return $result}
if {[string index $result 2] <= 7} {
if {$function <= 4} {
set result [string range $result 6 end-4]
} else {
set result "ok"
}
} else {
set result "error"
}

return $result
}

#############################################################
# test examples #
#############################################################

set port /dev/ttyUSB0
set timeout 1000

#read discrete outputs 0x ref (returns 1 byte per 8 output bits)
puts [modbuscommand 5 1 2048 8 $port $timeout]

#read disrcete input status 1x ref (returns 1 byte per 8 input bits)
puts [modbuscommand 5 2 2048 8 $port $timeout]

#read holding registers 4x ref (returns 2 bytes per 1 16bit register)
puts [modbuscommand 5 3 2100 8 $port $timeout]

#read input register 3x ref (returns 2 bytes per 1 16bit register)
puts [modbuscommand 5 4 2048 8 $port $timeout]

#force single output coil on
puts [modbuscommand 5 5 2049 on $port $timeout]

#preset a single register 4x ref
puts [modbuscommand 5 6 1 4444 $port $timeout]
puts [modbuscommand 5 3 1 1 $port $timeout]

#force multiple output coils on 8
puts [modbuscommand 5 15 2049 8 ff00 $port $timeout]

#force multiple output coils off 8
puts [modbuscommand 5 15 2049 8 0000 $port $timeout]

#preset multiple registers addr 2048 count 2 datavalues ff00aa33
puts [modbuscommand 5 16 2048 2 ff00aa33 $port $timeout]
puts [modbuscommand 5 16 2100 4 1234567812345678 $port $timeout]

########################
Output of test commands:
00
08
12345678123456780000000000000000
ff00aa33000000000000000000000000
ok
ok
4444
ok
ok
ok
ok</pre>
regards,
nick
 
V

vikrantmakwana

You can look at NModbus .net library and create a master console app and call this from Matlab.

I can offer my help to write the .net side of interface.

If you could call C functions in Matlab, you would want to look at libmodbus.
 
Top