PLC is a mechanical device used to operate a large machine such as a factory. This equipment is mainly manufactured by KEYENCE and Mitsubishi. When programming, it is expressed in a graphical diagram such as an electric circuit diagram instead of the English-speaking language used on a PC.
Created at work when asked "Can a computer program communicate with a PLC?" I checked PLC from 1 because I am a person in the IT field who is not familiar with PLC.
It seems that communication is possible, but since there are few sample codes made with python, I understand the mechanism from other languages. -Soket communication is used to send the value. -It is necessary to encode to ascii code when communicating. -The value to be entered when sending is converted from hexadecimal to decimal. You need to convert the ascii code to decimal. I had a hard time because I was not familiar with mathematics.
It is an environment where communication is performed via a switching hub. PC-Switching Hub-PLC It's like that.
ip = '10.50.100.32' #IP address on the PLC side.
port = 8501 #Port number used for upper link communication set on the PLC side
#The device name is EM9000 etc.
#The number of devices is used when the number of devices is continuously and in order.
#EM9000,Used when arranging devices such as EM9001.
#The value / message to be entered is
#Decimal numbers can be used as they are.
#Hexagonal numbers can be sent in multiples of 4 characters. 4 characters, 8 characters,12 characters
#Therefore, the number of devices also increases to 1 to 3.
#Ascii can only have 2 characters per device.
#The number of devices will increase accordingly.
to_EM9000 = Send_to_PLC(ip,port,"EM9000","3","ABCDEF")
to_EM9002 = Send_to_PLC(ip,port,"EM9002","2","00200616")
to_EM9004 = Send_to_PLC(ip,port,"EM9004","1","1")
to_EM9000.send_ascii_message() #Send ASCII code to PLC in decimal number
to_EM9002.send_16decimal_message() #Send to PLC from hexadecimal number to decimal number
to_EM9004.send_10decimal_message() #Send decimal numbers to PLC as they are
Send_to_PLC
import socket
#Class that can change the value of PLC device
class Send_to_PLC(object):
def __init__(self,ip_address,port_num,device_name,data_length,message):
self.ip_address =ip_address
self.port_num = int(port_num)
self.device_name = device_name
self.data_length = data_length
self.message = message
#Convert ASCII code to decimal
def ascii_to_10decimal(self):
#If the number of characters in message is smaller than the specified data length
read_device_length = int(self.data_length)
message_length = len(self.message)
if read_device_length >= message_length:
data_lng_int = message_length
else:
data_lng_int = read_device_length
#Put the message in a 2-byte list.
separate_msg_list =[]
for i in range(data_lng_int):
if i == 0:
separate_msg = self.message[0:2]
separate_msg_list.append(separate_msg)
else:
separate_msg = self.message[2*i:2*(i+1)]
separate_msg_list.append(separate_msg)
#If the number of characters is odd, the last character is left-justified.
if len(separate_msg_list[-1]) == 1:
separate_msg_list[-1] = separate_msg_list[-1]+ " "
#Convert ascii code to decimal.(ascii → binary hexadecimal number → decimal number)
digit_mesage_list = []
for msg in separate_msg_list:
ascii_data = msg.encode(encoding="ascii")
hex_bina_data = binascii.hexlify(ascii_data)
digi10_int = int(hex_bina_data,16)
digi10_str = str(digi10_int)
digit_mesage_list.append(digi10_str)
trans_message = " ".join(digit_mesage_list)
return trans_message
#Convert hexadecimal numbers to decimal numbers
def digit16_to_degit10(self):
read_device_length = int(self.data_length)
message_length = len(self.message)
if read_device_length >= message_length:
data_lng_int = message_length
else:
data_lng_int = read_device_length
#Divide the message into 4 bytes and put it in the list.
#Convert hexadecimal number to decimal number after entering
separate_msg_list =[]
for i in range(data_lng_int):
if i == 0:
separate_msg = self.message[0:4]
digi10_int = int(separate_msg,16)
digi10_str = str(digi10_int)
separate_msg_list.append(digi10_str)
else:
separate_msg = self.message[4*i:4*(i+1)]
digi10_int = int(separate_msg,16)
digi10_str = str(digi10_int)
separate_msg_list.append(digi10_str)
trans_message = " ".join(separate_msg_list)
return trans_message
#Send to PLC
def send_message(self,command_list):
command_sentence = "".join(command_list)
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((self.ip_address,self.port_num))
s.send(command_sentence.encode('ascii'))
#After converting ASCII code to decimal number,Send to PLC
#message is a multiple of 4 characters.
def send_ascii_message(self):
tranformed_digi_message = self.ascii_to_10decimal()
command_list = ['WRS ',self.device_name,".S ",self.data_length," ",tranformed_digi_message,'\r']
self.send_message(command_list)
#After converting hexadecimal numbers to decimal numbers,Send to PLC
def send_16decimal_message(self):
tranformed_digi_message = self.digit16_to_degit10()
command_list = ['WRS ',self.device_name,".S ",self.data_length," ",tranformed_digi_message,'\r']
self.send_message(command_list)
#After converting hexadecimal numbers to decimal numbers,Send to PLC
#Supports only one device
def send_10decimal_message(self):
command_list = ['WR ',self.device_name,".S ",self.message,'\r']
self.send_message(command_list)
if __name__ == '__main__':
ip = '10.50.100.32'
port = 8501
#IP address when instantiating,port number,First device name, number of devices,Enter the value / message to be entered.
to_EM9000 = Send_to_PLC(ip,port,"EM9000","3","ABCDEF")
to_EM9002 = Send_to_PLC(ip,port,"EM9002","2","00200616")
to_EM9004 = Send_to_PLC(ip,port,"EM9004","1","1")
to_EM9000.send_ascii_message() #Send ASCII code to PLC in decimal number
to_EM9002.send_16decimal_message() #Send to PLC from hexadecimal number to decimal number
to_EM9004.send_10decimal_message() #Send decimal numbers to PLC as they are
I feel that the explanation is not good, but I will release it for the time being.
Recommended Posts