#%TITLE% WAGO.MAC
#%NAME%
# Macro functions to access WAGO I/O modules.
#
#%DESCRIPTION%
# This macro set implements communication with modules of the
# WAGO-I/O-SYSTEM 750 through field bus couplers for MODBUS over serial
# lines or MODBUS/TCP over Ethernet TCP/IP.%BR%
#
#%EXAMPLE%
#
# %B%wagosetup%B% %BR%
# %B%print wago_read("temp", 2, "IW")%B% %BR%
# This prints the value of the 3rd input register associated to the function
# name "temp".%BR%
# %B%wago_write("myout", 0, 1, "OB")%B% %BR%
# This macro sets the first output bit of "myout" to 1.%BR%
#
#%UU%
#%MDESC%
# .%BR%
#
def wagosetup '_wagosetup(0)'
#%UU%
#%MDESC%
# .%BR%
#
def wagoshow '_wagosetup(1)'
#%IU%
#%MDESC%
# .%BR%
#
def _wagosetup(show) '{
global WAGO[]
global WAGOCONFIG[]
global WAGOFUNCT[]
global WAGO_ERR
global MODB_ERR
local configf setupf editor
if (whatis("BLISSADM") & 0x04000000) {
configf = BLISSADM "/spec/macros/wago.config"
setupf = BLISSADM "/local/spec/userconf/" SPECBL "config.wago"
} else {
configf = SPECD "/../jmacros/wago.config"
setupf = sprintf("%s/../local/userconf/%sconfig.wago", SPECD, SPECBL)
}
if (!SETUP && !show) {
if (SEDITOR == "") {
print "Cannot open file editor. No editor configured"
} else {
if (GUI_RUN)
editor = sprintf("xterm -tn vt100 -e %s", SEDITOR)
else
editor = SEDITOR
unix(sprintf("%s %s", editor, setupf))
}
}
if (wago__conf(configf) > 0) {
wago__nodes(setupf, show)
}
setup_tail("wago")
}'
#%IU%
#%MDESC%
# .%BR%
#
def wagounsetup '{
unglobal WAGO
unglobal WAGOCONFIG
unglobal WAGOFUNCT
unglobal WAGO_ERR
}'
#%IU% (<config_file>])
#%MDESC%
# .%BR%
#
def wago__conf(cfile) '{
local line
local ref ib ob iw ow desc
if (!file_info(cfile)) {
print " WAGO: Can not access configuration file ", cfile
return (-1)
}
if (SETUP && WAGO["conftime"] == file_info(cfile, "mtime")) {
return(WAGO["nconf"])
}
getline(cfile, "close")
if (getline(cfile, "open") == -1) {
print " WAGO: Can not open configuration file ", cfile
return(-1)
}
for (line in WAGOCONFIG) delete WAGOCONFIG[line]
WAGO["nconf"] = 0
printf("Reading file \"%s\"\n", cfile)
while((line = getline(cfile)) != -1) {
c = substr(line, 1, 1)
if (asc(c) < 32 || c == "#")
continue
if (sscanf(line, " %[^,], %g, %g, %g, %g, %[^\n\r]", \
ref, ib, ob, iw, ow, desc) != 6) {
printf(" Bad line in \"%s\": %s\n", cfile, line)
continue
}
WAGOCONFIG[ref] = WAGO["nconf"]++
WAGOCONFIG[ref]["ib"] = ib
WAGOCONFIG[ref]["ob"] = ob
WAGOCONFIG[ref]["iw"] = iw
WAGOCONFIG[ref]["ow"] = ow
WAGOCONFIG[ref]["desc"] = desc
}
WAGO["conftime"] = file_info(cfile, "mtime")
getline(cfile, "close")
return(WAGO["nconf"])
}'
#%IU% (<setup_file>])
#%MDESC%
# .%BR%
#
def wago__nodes(nfile, show) '{
local line node nodename
local type device addr nmod
local nametable[]
short array modtable[64][4]
if (!file_info(nfile, "-r")) {
print " WAGO: Can not access setup file ", nfile
return (-1)
}
getline(nfile, "close")
for (line in WAGOFUNCT) delete WAGOFUNCT[line]
printf("Reading file \"%s\"\n", nfile)
WAGO["nfunc"] = 0
node = 0
while ((line = getline(nfile)) != -1) {
c = substr(line, 1, 1)
if (asc(c) < 32 || c == "#")
continue
if (!node) {
addr = -1
device = other = ""
if (sscanf(line, " node %s %s %d %s %s", \
type, nodename, addr, device, other) >= 2 && \
(type == "tcp" || (type == "serial" && addr >= 0 && device != ""))) {
if (type == "tcp") {
device = nodename
if (addr < 0) addr = 0xFF
}
if (show) {
printf("\nI/O station: %s ", nodename)
if (type == "tcp")
printf("(tcp)\n")
else
printf("(%s ## %s)\n", device, addr)
}
} else {
printf(" Bad line in \"%s\": %s\n", nfile, line)
return(-1)
}
node = 1
nmod = 0
} else {
name = ""
sscanf(line, " %s %s", ref, name)
if (ref == "node") {
printf(" Bad line in \"%s\": %s\n", nfile, line)
print " Node terminator is probably missing."
return(-1)
}
if (!(ref in WAGOCONFIG)) {
printf(" WAGO reference `%s\' not known.\n", ref)
return(-1)
} else if (show) {
printf(" %2d - %s - %s\n", nmod, ref, WAGOCONFIG[ref]["desc"])
}
nametable[nmod] = name
modtable[nmod][0] = WAGOCONFIG[ref]["ib"]
modtable[nmod][1] = WAGOCONFIG[ref]["ob"]
modtable[nmod][2] = WAGOCONFIG[ref]["iw"]
modtable[nmod][3] = WAGOCONFIG[ref]["ow"]
if (modtable[nmod][0] == -1) {
wago__addnode(nodename, device, addr, nametable, modtable, nmod)
node = 0
} else if(array_op("sum", modtable[nmod]) > 0) {
nmod++
}
}
}
if (node) {
print " Node terminator is probably missing."
return(-1)
}
getline(nfile, "close")
}'
#%IU% (<name>, <device>, <addr>, <nametab>, <dtable>, <nmod>)
#%MDESC%
# .%BR%
#
def wago__addnode(nodename, device, addr, nametab, table, n) '{
short array bas[4] len[4] oth[4]
local modbnode idx hostn
if ((idx = index(device, ":")) != 0){
unix("hostname", hostn="")
sscanf(hostn, "%s", hostn)
if (substr(device, 1, idx - 1) != hostn) {
if (!SETUP)
printf(" Not the right host for node %s (%s).\n", nodename, device)
return
}
device = substr(device, idx + 1)
}
if (substr(device, 1, 5) == "/dev/") {
# Check for device
if (1 && !SETUP) {
printf(" Device %s (node %s) not configured as serial interface.\n",\
device, nodename)
return
}
device = 99
}
MODB_ERR = -1
modbnode = modb_addnode(device, addr, nodename)
if (MODB_ERR == 1001) {
printf(" Interface error (%s) with node \'%s\'\n", device, nodename)
return
} else if (MODB_ERR == 1002) {
printf(" Bad address (%d) for node \'%s\'\n", addr, nodename)
return
} else if (MODB_ERR) {
printf(" Node \'%s\' does not respond (%s, %d)\n", nodename, device, addr)
return
} else {
# Add i/o bits/words and check with real device before
len[0] = array_op("sum", table[][0])
len[1] = array_op("sum", table[][1])
len[2] = array_op("sum", table[][2])
len[3] = array_op("sum", table[][3])
#p len
# modb_read_multregs(modbnode, 0x1022, 4, oth)
#p oth
# if (array_op("sum", oth != len) != 0) {
# printf(" Node \'%s\' does not match settings.\n", nodename)
# return
# }
}
funct = 0
bas = 0
for (i = 0; i < n; i++) {
name = nametab[i]
if (name == "") {
bas += table[i]
continue
}
if (name in WAGOFUNCT) {
printf(" Invalid function name %s in node %s\n", name, nodename)
bas += table[i]
continue
}
len = table[i]
oth = 0
for (j = i + 1; j < n; j++) {
if (name == nametab[j]) {
nametab[j] = ""
len += table[j]
if (array_op("sum", len * oth) > 0) {
print " Non consecutive modules/addresses for function", name
return(-1)
}
} else {
oth += table[j]
}
}
WAGOFUNCT[name] = WAGO["nfunc"]++
WAGOFUNCT[name]["node"] = modbnode
WAGOFUNCT[name]["b_IB"] = bas[0]
WAGOFUNCT[name]["b_OB"] = bas[1]
WAGOFUNCT[name]["b_IW"] = bas[2]
WAGOFUNCT[name]["b_OW"] = bas[3]
WAGOFUNCT[name]["n_IB"] = len[0]
WAGOFUNCT[name]["n_OB"] = len[1]
WAGOFUNCT[name]["n_IW"] = len[2]
WAGOFUNCT[name]["n_OW"] = len[3]
funct++
bas += table[i]
}
return(funct)
}'
#%IU% (<modname>, <addr>, <dtype>, <nval>)
#%MDESC%
# .%BR%
#
def wago__check(name, addr, dtype, nval) '{
local base len
if (!(name in WAGOFUNCT)) {
if (WAGO_ERR != -1)
printf("Not a valid wago name: %s\n", name)
return(-1)
}
base = WAGOFUNCT[name]["b_" dtype]
len = WAGOFUNCT[name]["n_" dtype]
if (addr < 0 || (addr + nval) > len) {
if (WAGO_ERR != -1) {
printf("Not valid \'%s\' address range (%d-%d) for wago name: %s\n", \
dtype, addr, addr + nval - 1, name)
}
WAGO_ERR = 101
return(-1)
}
WAGO["currnode"] = WAGOFUNCT[name]["node"]
WAGO["curraddr"] = base + addr
WAGO_ERR = 0
return(0)
}'
#%UU% (<fname>, <faddr> [, <dtype>])
#%MDESC%
# .%BR%
#
def wago_read(name, addr, dtype) '{
local data[]
if (whatis("dtype") & 0x08000000)
dtype = "IW"
if (wago_mread(name, addr, 1, data, dtype) > 0)
return(data[0])
else
return(-1)
}'
#%UU% (<fname>, <faddr>, <nval>, <data> [, <dtype>])
#%MDESC%
# .%BR%
#
def wago_mread(name, addr, nval, data, dtype) '{
local node eaddr
if (whatis("dtype") & 0x08000000)
dtype = "IW"
if (wago__check(name, addr, dtype, nval) < 0)
return(-1)
node = WAGO["currnode"]
eaddr = WAGO["curraddr"]
if (dtype == "IW") {
return(modb_read_inpregs(node, eaddr, nval, data))
} else if (dtype == "OW") {
eaddr += 0x0200
return(modb_read_inpregs(node, eaddr, nval, data))
} else if (dtype == "IB") {
return(modb_read_coils(node, eaddr, nval, data))
} else if (dtype == "OB") {
eaddr += 0x0200
return(modb_read_coils(node, eaddr, nval, data))
} else
return(-1)
}'
#%UU% (<fname>, <faddr>, <value> [, <dtype>])
#%MDESC%
# .%BR%
#
def wago_write(name, addr, value, dtype) '{
local node eaddr
if (whatis("dtype") & 0x08000000)
dtype = "OW"
if (wago__check(name, addr, dtype, 1) < 0)
return(-1)
node = WAGO["currnode"]
eaddr = WAGO["curraddr"]
if (dtype == "OW") {
return(modb_write_reg(node, eaddr, value))
} else if (dtype == "OB") {
return(modb_write_coil(node, eaddr, value))
} else {
if (WAGO_ERR != -1) {
printf("Not output wago data type: %s\n", dtype)
}
WAGO_ERR = 110
return(-1)
}
}'
#%UU% (<fname>, <faddr>, <nval>, <data> [, <dtype>])
#%MDESC%
# .%BR%
#
def wago_mwrite(name, addr, nval, data, dtype) '{
local node eaddr
if (whatis("dtype") & 0x08000000)
dtype = "OW"
if (wago__check(name, addr, dtype, nval) < 0)
return(-1)
node = WAGO["currnode"]
eaddr = WAGO["curraddr"]
if (dtype == "OW") {
return(modb_write_regs(node, eaddr, nval, data))
} else if (dtype == "OB") {
return(modb_force_coils(node, eaddr, nval, data))
} else {
if (WAGO_ERR != -1) {
printf("Not output wago data type: %s", dtype)
}
WAGO_ERR = 110
return(-1)
}
}'
def multim_init_wago '
global WAGO_MULTIM[]
if (whatis("WAGOFUNCT") == 0) {
printf("wagosetup must be run before multimsetup type=wago\n")
return 1
}
if ("group" in MULTIM[cntr]) {
local group channel
group = MULTIM[cntr]["group"]
if ("channel" in MULTIM[cntr])
channel = MULTIM[cntr]["channel"]
else {
channel = counter_par(cntr, "channel")
MULTIM[cntr]["channel"] = channel
}
if (channel < 0) {
printf("Invalid WAGO channel %d in counter %s\n", channel, \
cnt_mne(cntr))
return 1
}
else if (channel >= WAGOFUNCT[group]["n_IW"]) {
local msg
msg = "WAGO Channel %d greater than nr. of configured channels " \
"in group \"%s\" (=%d)\n"
printf(msg, channel, group, WAGOFUNCT[group]["n_IW"])
return 1
}
# if (!("offset" in MULTIM[cntr]))
# MULTIM[cntr]["offset"] = 0
# else
# MULTIM[cntr]["offset"] /= MULTIM[cntr]["scale"]
}
else {
printf("No \"group\" parameter in multimsetup for WAGO counter %s\n", \
cnt_mne(cntr))
return 1
}
'
#def multim_read_wago '
#
# if ("group" in MULTIM[cntr]) {
# local group channel
# group = MULTIM[cntr]["group"]
# if (WAGO_MULTIM[group]["t0"] != MULTIM["t0"]) {
# wago_multim_read_all(group)
# WAGO_MULTIM[group]["t0"] = MULTIM["t0"]
# }
#
# channel = MULTIM[cntr]["channel"]
# if (WAGO_MULTIM[group]["nrchan"] > channel) {
# value = WAGO_MULTIM[group][channel] + MULTIM[cntr]["offset"]
# ok = 1
# }
# }
#'
def multim_read_wago '
if ("group" in MULTIM[cntr]) {
local group channel
group = MULTIM[cntr]["group"]
if (MULTIM["loop_n"] > WAGO_MULTIM[group]["last_n"]) {
wago_multim_read_all(group)
WAGO_MULTIM[group]["last_n"] = MULTIM["loop_n"]
}
channel = MULTIM[cntr]["channel"]
if (WAGO_MULTIM[group]["nrchan"] > channel) {
value = WAGO_MULTIM[group][channel] + MULTIM[cntr]["offset"]
ok = 1
}
}
'
def wago_multim_read_all(group) '{
local nrchan indx
nrchan = WAGOFUNCT[group]["n_IW"]
local short array arr[nrchan]
nrchan = wago_mread(group, 0, nrchan, arr)
WAGO_MULTIM[group]["nrchan"] = nrchan
for (indx = 0; indx < nrchan; indx++)
WAGO_MULTIM[group][indx] = arr[indx]
}'
#%MACROS%
#%DEPENDENCIES%
# This macro set needs modbus.mac to access MODBUS devices.
#
#%INTERNALS%
# ???.
#
#%AUTHOR% P. Fajardo, (Original 5/01).
# $Revision: 1.1 $ / $Date: 2003/03/31 11:17:54 $
#%TOC%
|