MODULE modbusTCP_slave
!author: Liao Chen, mousechen17@163.com
! Aug.21, 2023
!!!!!!! regiser start_address is 1!!!!
!!!!!!! coil start_add is 1!!!!!
!!!!!!! support holding register
!!!!!!! support holding coil
!!!!!!! support 0x03 0x06 0x10 0x01 0x05 0x0F function
!!!!!!! if robot receive wrong data, robot will not send feadback
VAR socketdev temp_socket;
VAR socketdev client_socket;
VAR string received_string;
VAR bool keep_listening:=TRUE;
VAR rawbytes recv_raw;
VAR rawbytes send_raw;
!!!!!! data need to be modified
PERS string rb_ip:="127.0.0.1";
PERS num holdingReg{100}:=[563,2567,868,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0];
PERS num coils{100}:=[1,1,1,1,0,1,1,1,1,0, 1,1,1,1,0,1,1,1,1,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0];
PROC main()
SocketClose temp_socket;
SocketClose client_socket;
SocketCreate temp_socket;
SocketBind temp_socket,rb_ip,502;
SocketListen temp_socket;
SocketAccept temp_socket,client_socket;
WHILE keep_listening DO
SocketReceive client_socket\RawData:=recv_raw\Time:=WAIT_MAX;
modbusHandle;
ENDWHILE
SocketClose temp_socket;
ERROR
IF ERRNO=ERR_SOCK_TIMEOUT THEN
TRYNEXT;
ELSEIF ERRNO=ERR_SOCK_CLOSED THEN
SocketClose temp_socket;
SocketClose client_socket;
SocketCreate temp_socket;
SocketBind temp_socket,rb_ip,502;
SocketListen temp_socket;
SocketAccept temp_socket,client_socket;
RETRY;
ELSE
TPWrite "ERRNO = "\Num:=ERRNO;
Stop;
ENDIF
ENDPROC
PROC modbusHandle()
VAR num pro_len;
VAR num data_len;
VAR num raw_len;
VAR num funNo;
VAR num regAdd;
ClearRawBytes send_raw;
raw_len:=RawBytesLen(recv_raw);
IF raw_len<=0 THEN
goto END;
ENDIF
UnPackRawBytes recv_raw\Network,5,pro_len\IntX:=UINT;
IF pro_len<>(raw_len-6) THEN
goto END;
ENDIF
UnPackRawBytes recv_raw\Network,9,regAdd\IntX:=UINT;
IF regAdd<=0 THEN
goto END;
ENDIF
UnPackRawBytes recv_raw\Network,8,funNo\IntX:=USINT;
! get FunNo
TEST funNo
CASE 3:
readMultiReg regAdd;
CASE 6:
writeSingReg regAdd;
CASE 16:
writeMultiReg regAdd;
CASE 1:
readMultiCoil regAdd;
CASE 5:
writeSingCoil regAdd;
CASE 15:
writeMultiCoil regAdd;
DEFAULT:
goto END;
ENDTEST
SocketSend client_socket\RawData:=send_raw;
END:
ENDPROC
PROC writeMultiCoil(num regAdd)
! 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_num byte_len byte1 byte2
! robot feedback: 0000 0000 0006 01 0F 0005 000A
! ttl data len slaveID funNo add coil_num
VAR num coilCount;
VAR num tmpValue;
VAR byte inValue;
VAR num byteCount:=1;
CopyRawBytes recv_raw,1,send_raw,1\NoOfBytes:=12;
UnPackRawBytes recv_raw\Network,11,coilCount\IntX:=UINT;
FOR i FROM 1 TO coilCount DO
IF (i mod 8)=1 THEN
UnPackRawBytes recv_raw\Network,13+byteCount,tmpValue\IntX:=USINT;
inValue:=tmpValue;
byteCount:=byteCount+1;
ENDIF
coils{regAdd+i-1}:=bitand(inValue,1); inValue:=BitRSh(inValue,1);
ENDFOR
PackRawBytes 6,send_raw\Network,5\IntX:=uint;
ENDPROC
PROC writeSingCoil(num regAdd)
! funNo: 0x05: write single coil
! device send: 0000 0000 0006 01 05 0002 FF00
! ttl data len slaveID funNo add data(FF00:ON, 0000:OFF)
! robot feedback: 0000 0000 0006 01 05 0002 FF00
! ttl data len slaveID funNo add data
VAR num value;
CopyRawBytes recv_raw,1,send_raw,1\NoOfBytes:=12;
UnPackRawBytes recv_raw\Network,11,value\IntX:=UsINT;
IF value=255 THEN
coils{regAdd}:=1; ELSE
coils{regAdd}:=0; ENDIF
ENDPROC
PROC readMultiCoil(num regAdd)
! 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
VAR num coilCount;
VAR num outValue{50}; VAR num byteCount:=1;
VAR num tmpValue;
ClearRawBytes send_raw;
CopyRawBytes recv_raw,1,send_raw,1\NoOfBytes:=8;
UnPackRawBytes recv_raw\Network,11,coilCount\IntX:=UINT;
FOR i FROM 1 TO coilCount DO
outValue{byteCount}:=outValue{byteCount}+coils{regAdd+i-1}*pow(2,(i-1) mod 8); IF (i mod 8)=0 THEN
byteCount:=byteCount+1;
ENDIF
ENDFOR
FOR i FROM 1 TO byteCount DO
tmpValue:=outValue{i}; PackRawBytes tmpValue,send_raw\Network,9+i\IntX:=1;
ENDFOR
PackRawBytes byteCount,send_raw\Network,9\IntX:=usint;
PackRawBytes byteCount+3,send_raw\Network,5\IntX:=uint;
ENDPROC
PROC readMultiReg(num regAdd)
! funNo: 0x03: read multi holding register
! device send: 0000 0000 0006 01 03 0001 0001
! ttl data len slaveID funNo add data_num
! robot feedback: 0000 0000 0005 01 03 02 0001
! ttl data len slaveID funNo rest_data_len data
VAR num regCount;
CopyRawBytes recv_raw,1,send_raw,1\NoOfBytes:=8;
UnPackRawBytes recv_raw\Network,11,regCount\IntX:=UINT;
FOR i FROM 1 TO regCount DO
PackRawBytes holdingReg{regAdd+i-1},send_raw\Network,9+(2*i-1)\IntX:=uint; ENDFOR
PackRawBytes regCount*2,send_raw\Network,9\IntX:=usint;
PackRawBytes regCount*2+3,send_raw\Network,5\IntX:=uint;
ENDPROC
PROC writeMultiReg(num regAdd)
! funNo: 0x10: write multi holding register
! device send: 0000 0000 000B FF 10 0002 0002 04 0021 002A
! ttl_data_len id funNo add data_num rest_data_len data1 data2
! robot feedback: 0000 0000 0006 FF 10 0002 00 02
! ttl_data_len id funNo add data_num
VAR num regCount;
VAR num value;
CopyRawBytes recv_raw,1,send_raw,1\NoOfBytes:=12;
UnPackRawBytes recv_raw\Network,11,regCount\IntX:=UINT;
FOR i FROM 1 TO regCount DO
unPackRawBytes recv_raw\Network,13+(2*i-1),value\IntX:=uint;
holdingReg{regAdd+i-1}:=value; ENDFOR
PackRawBytes 6,send_raw\Network,5\IntX:=uint;
ENDPROC
PROC writeSingReg(num regAdd)
! funNo: 0x06: write single holding register
! device send: 0000 0000 0006 01 06 0001 0001
! ttl data len slaveID funNo add data
! robot feedback: 0000 0000 0006 01 06 0001 0001
! ttl data len slaveID funNo add data
VAR num value;
CopyRawBytes recv_raw,1,send_raw,1\NoOfBytes:=12;
UnPackRawBytes recv_raw\Network,11,value\IntX:=UINT;
holdingReg{regAdd}:=value; ENDPROC
ENDMODULE