机器人通过0x02功能码读取远程I/O的离散输入
机器人通过0x0F功能码写入远程I/O的输出
1.现场使用Modbus/TCP的模块越来越多。例如机器人可以读写基于ModbusTCP的远程I/O模块。此处举例艾莫迅ETH-MODBUS-16IOR模块。相关手册参阅:
http://www.amsamotion.com/product_571.html
该模块有16个DI和16个DO。
DI采用0x02功能码读取输入线圈,DO可以采用0x05(写入单个线圈) 0x0F(写入多个线圈)等功能码写入
2. 为方便使用,建议机器人加入多任务功能,即将modbus的读写放入后台。对于RW6系统,还需要PC Interface选项(RW7不需要选项就可以使用socket通讯)
3. 相关代码如下:
MODULEmodbusTCP_Master! author: Liao Chen, mousechen17@163.com!!!!!!! support discrete input coil!!!!!!! support holding coil!!!!!!! support 0x01 0x02 0x05 0x0F function
VARsocketdev sock_mod;VARrawbytes recv_raw;VAR rawbytes send_raw;
PERSnum write_coils{16}:=[1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0];persnum read_coils{16}:=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];!!!!!! data need to be modified
PERSstring slave_ip:="127.0.0.1";PERSnum slave_ID:=1;PERS num regAdd:=0;
PROCmain()WHILEtrue DOreadMultiCoil\Input,regAdd,16,read_coils; ! 读取16个输入并存入read_coils数组setDI116; ! 将modbus信号存入vdo信号,并通过crossconnection关联到对应DI ! 此处假设DI信号均为di1,di2.。。di16的命名
writeCoils16; ! 将do1.。。do16真实信号的值存入write_coils数组writeMultiCoilregAdd,16,write_coils; ! 写入modbus远程waittime0.05; ENDWHILEENDPROC
PROCwriteCoils(num count) ! 假设do信号名为do1...do16VARsignaldo sig;VARstring name;FORi FROM 1 TO count DOname:="do"+valtostr(i);AliasIOname,sig;write_coils{i}:=doutput(sig);ENDFORENDPROC
PROCsetDI1(num count)FORi FROM 1 TO count DOsetDO_int"vdo"+ValToStr(i),read_coils{i};ENDFORENDPROC
PROCsetDO_int(string name,num value)VARsignaldo sig;aliasIOname,sig;setdosig,value;ENDPROC
PROCwriteMultiCoil(num regAdd,num coilCount,num coils{*}) ! funNo: 0x0F: write multi Coil ! device send: 00 01 00 00 00 09 01 0F 0005 000A 02 CD 01 ! ttl data len slaveID funNo add coil_count byte_len byte1 byte2 ! robot feedback: 0000 0000 0006 01 0F 0005 000A ! ttl data len slaveID funNo add coil_numVARbyte outByte{50};VARnum byteCount:=1; VAR num b{100};b{1}:=0x00;b{2}:=0x00;b{3}:=0x00;b{4}:=0x00; ! b{5}:=0x00; ! b{6}:=0x06;b{7}:=slave_ID;b{8}:=0x0F;
ClearRawBytessend_raw;FORi FROM 1 TO 8 DOPackRawBytesb{i},send_raw,i\IntX:=1;ENDFORPackRawBytesregAdd,send_raw\Network,9\IntX:=2;PackRawBytescoilCount,send_raw\Network,11\IntX:=2;
FORi FROM 1 TO coilCount DOoutByte{byteCount}:=outByte{byteCount}+coils{i}*pow(2,(i-1) mod 8);IF(i mod 8)=0 THENbyteCount:=byteCount+1;ENDIFENDFOR
DecrbyteCount;FORi FROM 1 TO byteCount DOPackRawBytesoutByte{i},send_raw\Network,13+i\Hex1;ENDFORPackRawBytesbyteCount,send_raw\Network,13\IntX:=1;PackRawBytes7+byteCount,send_raw\Network,5\IntX:=2;sendAndReceive;ENDPROC
PROCreadMultiCoil(\switch Input,num regAdd,num coilCount,inout num coils{*}) ! funNo: 0x01: read multi Coil ! device send: 00 00 00 00 00 06 01 01 0002 0002 ! ttl data len slaveID funNo add coil_num ! robot feedback: 0000 0000 0004 01 01 01 01 ! ttl data len slaveID funNo rest_data_len data
! funNo: 0x02: read input multi Coil ! device send: 00 00 00 00 00 06 01 02 0002 0002 ! ttl data len slaveID funNo add coil_num ! robot feedback: 0000 0000 0004 01 02 01 01 ! ttl data len slaveID funNo rest_data_len data VAR byte inValue;VARnum byteCount:=1;VARnum tmpValue; VAR num b{100};b{1}:=0x00;b{2}:=0x00;b{3}:=0x00;b{4}:=0x00;b{5}:=0x00;b{6}:=0x06;b{7}:=slave_ID;IFPresent(input) THENb{8}:=0x02;ELSEb{8}:=0x01;endif ClearRawBytes send_raw;FORi FROM 1 TO 8 DOPackRawBytesb{i},send_raw,i\IntX:=1;ENDFORPackRawBytesregAdd,send_raw\Network,9\IntX:=2;PackRawBytescoilCount,send_raw\Network,11\IntX:=2;sendAndReceive;FORi FROM 1 TO coilCount DOIF(i mod 8)=1 THENUnPackRawBytesrecv_raw\Network,9+byteCount,tmpValue\IntX:=USINT;inValue:=tmpValue;byteCount:=byteCount+1;ENDIFcoils{i}:=bitand(inValue,1);inValue:=BitRSh(inValue,1);ENDFORENDPROC
PROCcheckSocket()ifSocketGetStatus(sock_mod)<>SOCKET_CONNECTED THENSocketClosesock_mod;SocketCreatesock_mod;SocketConnectsock_mod,slave_ip,502\Time:=10;endifENDPROC
PROCsendAndReceive()checkSocket;SocketSendsock_mod\RawData:=send_raw;SocketReceivesock_mod\RawData:=recv_raw;ENDPROCENDMODULE
IO配置如下:
EIO:CFG_1.0:6:1::#EIO_CROSS: -Name "c1" -Res "di1" -Act1 "vdo1" -Name "c2" -Res "di2" -Act1 "vdo2" -Name "c3" -Res "di3" -Act1 "vdo3" -Name "c4" -Res "di4" -Act1 "vdo4" -Name "c5" -Res "di5" -Act1 "vdo5" -Name "c6" -Res "di6" -Act1 "vdo6" -Name "c7" -Res "di7" -Act1 "vdo7" -Name "c8" -Res "di8" -Act1 "vdo8" -Name "c9" -Res "di9" -Act1 "vdo9" -Name "c10" -Res "di10" -Act1 "vdo10" -Name "c11" -Res "di11" -Act1 "vdo11" -Name "c12" -Res "di12" -Act1 "vdo12" -Name "c13" -Res "di13" -Act1 "vdo13" -Name "c14" -Res "di14" -Act1 "vdo14" -Name "c15" -Res "di15" -Act1 "vdo15" -Name "c16" -Res "di16" -Act1 "vdo16"#EIO_SIGNAL: -Name "di1" -SignalType "DI" -Name "di2" -SignalType "DI" -Name "di3" -SignalType "DI" -Name "di4" -SignalType "DI" -Name "di5" -SignalType "DI" -Name "di6" -SignalType "DI" -Name "di7" -SignalType "DI" -Name "di8" -SignalType "DI" -Name "di9" -SignalType "DI" -Name "di10" -SignalType "DI" -Name "di11" -SignalType "DI" -Name "di12" -SignalType "DI" -Name "di13" -SignalType "DI" -Name "di14" -SignalType "DI" -Name "di15" -SignalType "DI" -Name "di16" -SignalType "DI" -Name "do1" -SignalType "DO" -Name "do2" -SignalType "DO" -Name "do3" -SignalType "DO" -Name "do4" -SignalType "DO" -Name "do5" -SignalType "DO" -Name "do6" -SignalType "DO" -Name "do7" -SignalType "DO" -Name "do8" -SignalType "DO" -Name "do9" -SignalType "DO" -Name "do10" -SignalType "DO" -Name "do11" -SignalType "DO" -Name "do12" -SignalType "DO" -Name "do13" -SignalType "DO" -Name "do14" -SignalType "DO" -Name "do15" -SignalType "DO" -Name "do16" -SignalType "DO" -Name "vdo1" -SignalType "DO" -Name "vdo2" -SignalType "DO" -Name "vdo3" -SignalType "DO" -Name "vdo4" -SignalType "DO" -Name "vdo5" -SignalType "DO" -Name "vdo6" -SignalType "DO" -Name "vdo7" -SignalType "DO" -Name "vdo8" -SignalType "DO" -Name "vdo9" -SignalType "DO" -Name "vdo10" -SignalType "DO" -Name "vdo11" -SignalType "DO" -Name "vdo12" -SignalType "DO" -Name "vdo13" -SignalType "DO" -Name "vdo14" -SignalType "DO" -Name "vdo15" -SignalType "DO" -Name "vdo16" -SignalType "DO"
********************************
|