-
MCPROTOCOL을 이용한 미쓰비시 PLC 통신PYTHON(파이썬)/파이썬 활용 2024. 11. 1. 03:44728x90반응형
미쓰비시 PLC 통신을 위해 Python 프로그램으로 제작되었으며, PLC에서 데이터를 읽어와 파일에 저장하고 로그인을 관리하는 역할을 수행합니다. 주요 pymcprotocol기능을 사용하여 PLC와 통신을 구현하고 있으며, 이 프로그램의 주요 기능은 다음과 같습니다.
주요 기능 문장:
- 출력 및 파일 생성 :
- makedir(directory)함수는 외부에서 생성됩니다.
- makefile(file, sHead)함수는 파일이 작성되는 경우 헤더 정보를 추가합니다.
- 서버 메시지 출력 :
- displaymsg(msg, imode)함수는 로그인 메시지를 콘솔에 출력하고 파일을 기록할 수 있습니다. imode값이 1이면 파일을 기록하는 데 사용됩니다.
- PLC연결 :
- PLCCon(sIP, iport)PLC와 연결을 시도합니다. 연결에 실패하면 업무 시간을 응답하고 재시도합니다. 연결이 성공하면 PLC 연결 OK메시지를 출력합니다.
- 파일 및 데이터 이동 :
- 프로그램 실행 시점의 날짜 정보를 바탕으로, 데이터 저장과 파일을 생성합니다.
- PLC 헤더 및 초기 값 plcadrm.txt파일에서 시작되는 데이터입니다. 이 파일은 데이터에 대한 정보를 포함하는 것으로 보입니다.
- PLC와의 메인 루프 :
- PLC와 연결 후 루프로 데이터를 처리하고 메인 루프를 실행합니다. 이 루프에서는 다음과 같은 작업을 수행합니다:
- PLC에서 D11490위치부터 33개의 명령 데이터를 읽었습니다.
- 읽은 데이터를 파일로 기록하고 로그를 남깁니다.
- 특정 데이터에 따라 조건을 추가로 처리하여 생성합니다.
- 주소로 D11579주소 1를 써서 PLC에 신호를 보냅니다.
- PLC와 연결 후 루프로 데이터를 처리하고 메인 루프를 실행합니다. 이 루프에서는 다음과 같은 작업을 수행합니다:
코드 흐름 분석:
- 생성 :
- 출력 및 파일을 준비하고 파일인을 설정 plcadrm.txt하고 PLC 데이터의 헤더와 값을 설정합니다.
- PLC에 연결을 시도하여 성공하면 메인 루프로 존재합니다.
- 메인 루프 :
- 메인 루프에서는 PLC에서 데이터를 입력하고, 로그인 파일과 CSV 파일로 저장합니다.
- 데이터를 기반으로 하는 D11579작업을 수행합니다.
- 데이터 읽기에 실패할 경우 재연결을 시도하며 일정 시간이 파일과 작성을 생성합니다.
주요 변수 및 의미:
- sIP, iport : PLC의 IP 주소와 포트 번호입니다. 이 정보를 바탕으로 PLC에 연결을 시도합니다.
- w_values : PLC에서 가져온 데이터의 목록입니다.
- sHead, sValue : plcadrm.txt파일에서 태그온 헤더 정보와 초기 값입니다. 데이터 구조를 정의하는 역할을 합니다.
- iErr : PLC 통신을 하면 카운트됩니다. 180번 이상 발생하면 재연결을 시도합니다.
- pymc3e : pymcprotocol.Type3E클래스의 참여로, PLC 통신을 담당합니다.
########################################################### 미쓰비시 PLC I/F# DATE: 2023.04.21 BY: EPLUS##########################################################import pymcprotocolimport sysimport timeimport osfrom datetime import datetimeimport keyboard
def makedir(directory):try:if not os.path.exists(directory):os.makedirs(directory)except OSError:print("Error: Failed to create the directory.")
def makefile(file, sHead):try:if not os.path.exists(file):file = open(file, 'w')for r in sHead:file.write(r + ',')file.write('\n')file.close()except OSError:print("Error: Failed to create the file.")def displaymsg(msg, imode):now = datetime.now()sDate = now.date()sMsg = str(now) + ' : ' + msgprint(sMsg)if imode == 1:file = open("c:/tong/Plog/" + str(sDate) + ".txt","a")file.write(sMsg + '\n')file.close
def PLCCon(sIP, iport):# PLC연결 후 접속 오류 시 종료에서 계속 확인 ------------pymc3e = pymcprotocol.Type3E()pymc3e.setaccessopt(commtype="binary")isCon = Truewhile isCon:try:pymc3e.connect(sIP, iport)sMsg = '## PLC 연결 OK!!! ## _IP: ' + sIPdisplaymsg(sMsg, 1)isCon = Falseexcept:sMsg = '## PLC 연결 오류!!! ## _IP: ' + sIPdisplaymsg(sMsg, 0)#프로그램종료 -> 계속 진행##quit()time.sleep(5)isCon = True# c:\tong\년월 디렉토리 생성sMsg = "## 년월 디렉토리 확인 및 생성 ##"displaymsg(sMsg, 1)
now = datetime.now()sDate = now.date()sdate = now.strftime('%Y%m%d')sYYmm = now.strftime('%Y%m')makedir("c:/tong/" + sYYmm)
# PLC Head 및 소숫점 Read ( 11, 12 : OK, NG 99:Spare, 88: 생성일시, 0~9 : 소숫점 )file = open("c:/work/plcadrm.txt","r")sTemp = file.readlines()i = 0for sline in sTemp:i += 1sMsg = "## plcadrm Read ## : " + slinedisplaymsg(sMsg, 1)sL= sline.replace('\n','')if i == 1:sHead = sL.split(';')elif i == 2:sValue = sL.split(';')file.close()
# 일자별 파일 생성makefile("c:/tong/" + sYYmm + '/' + str(sDate) + '.csv', sHead)#################################################### plc 연결###################################################sIP = "192.168.40.165"iport = 1025sMsg = '## PLC 연결 ##_IP: ' + sIP + '_PORT: ' + str(iport)displaymsg(sMsg, 1)
#################################################### PLC연결 후 접속###################################################pymc3e = pymcprotocol.Type3E()pymc3e.setaccessopt(commtype="binary")isCon = Truewhile isCon:try:pymc3e.connect(sIP, iport)sMsg = '## PLC 연결 OK!!! ## _IP: ' + sIPdisplaymsg(sMsg, 1)isCon = Falseexcept:sMsg = '## PLC 연결 오류!!! ## _IP: ' + sIPdisplaymsg(sMsg, 0)#프로그램종료 -> 계속 진행##quit()time.sleep(5)isCon = True
#pymc3e.connect("192.168.205.1", 5001)#################################################### Main Loop - Get Value From PLC - Start###################################################i = 0iErr = 0sJ = ""while True:sMsg = str(i) + '_## PLC Read...##'displaymsg(sMsg, 9)try:#################################################### PLC 값 읽기 1###################################################w_values = pymc3e.batchread_wordunits(headdevice="D11490", readsize=33)iErr = 0except:w_values = []sMsg ='## MC Protocol Error ##_Err_Cnt: ' + str(iErr)displaymsg(sMsg, 1)#프로그램종료-> 3분후 재접속 시도 --------------------------------#quit()time.sleep(1)iErr = iErr + 1if iErr > 180:makedir("c:/tong/" + sYYmm)makefile("c:/tong/" + sYYmm + '/' + str(sDate) + '.csv', sHead)##pymc3e = pymcprotocol.Type3E()pymc3e.setaccessopt(commtype="binary")isCon = Truewhile isCon:try:pymc3e.connect(sIP, iport)sMsg = '## PLC 연결 OK!!! ## _IP: ' + sIPdisplaymsg(sMsg, 1)isCon = Falseexcept:sMsg = '## PLC 연결 오류!!! ## _IP: ' + sIPdisplaymsg(sMsg, 0)#프로그램종료 -> 계속 진행##quit()time.sleep(5)isCon = True##iErr = 0now = datetime.now()sDate = now.date()sdate = now.strftime('%Y%m%d')sYYmm = now.strftime('%Y%m')print(str(now), w_values)if len(w_values) == 0:sMsg = '## 값이 없습니다 ##'displaymsg(sMsg, 1)# 값이 없으면 - 오류로 0 전달if iErr == 0:pymc3e.batchwrite_wordunits(headdevice="D11579", values=[0])else:file = open("c:/tong/Plog/" + str(sDate) + ".txt","a")for r in w_values:file.write('['+str(r)+']')w_values2 = pymc3e.batchread_wordunits(headdevice="D11575", readsize=5)file.write(str(w_values2[0])+',')file.write(str(w_values2[3])+',')file.write('\n')file.close()#################################################### PLC 값 저장###################################################iCnt = 0if sJ != str(w_values[0]):file = open("c:/tong/" + sYYmm + '/' + str(sDate) + '.csv',"a")for r in w_values:iV = int(sValue[iCnt])if iV == 0 or iV == 99:file.write(str(r)+',')elif iV == 11:if str(r) == '0':file.write(str(r)+'(OK),')else:file.write(str(r)+'(NG),')elif iV == 12:if str(r) == '1':file.write(str(r)+'(OK),')elif str(r) == '2':file.write(str(r)+'(NG),')else:file.write(str(r)+'( ),')elif iV >= 1 and iV <= 9: # 소숫점 처리file.write(str(float(r) / 10 **iV) + ',')else: # 88 생성일시file.write(str(now))iCnt = iCnt + 1w_values2 = pymc3e.batchread_wordunits(headdevice="D11575", readsize=5)r2 = str(w_values2[0])if str(r2) == '0':file.write(r2+'(OK),')else:file.write(r2+'(NG),')r2 = str(w_values2[3])file.write(r2+',')file.write(str(now))file.write('\n')file.close()#sJ = str(w_values[0])# 2 초 단위로 1 전송if divmod(i, 2)[1] == 0 and iErr == 0:pymc3e.batchwrite_wordunits(headdevice="D11579", values=[1])sMsg = '## D11579에 1 전송 ##'displaymsg(sMsg, 1)#i = i + 1if i > 3000:i = 0makedir("c:/tong/" + sYYmm)makefile("c:/tong/" + sYYmm + '/' + str(sDate) + '.csv', sHead)# 1초 대기time.sleep(1)#################################################### Main Loop - Get Value From PLC - END###################################################이 프로그램은 주로 제조 환경에서 PLC 데이터를 로드하고 CSV 파일로 기록하고 장비의 상태를 모니터링하기 위해 사용됩니다.
현재 LG전자 협력사에 적용중인 프로그램으로 초기 버젼입니다. 참조하여 미쓰비시 PLC I/F에 충분히 활용 가능합니다.
C#으로 변환한 소스입니다.
using System;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Collections.Generic;
using McProtocolLib; // Add MC Protocol library
class MitsubishiPLCInterface
{
static void Main(string[] args)
{
string directory = $"c:/tong/{DateTime.Now.ToString("yyyyMM")}";
MakeDirectory(directory);
string sIP = "192.168.40.165";
int iport = 1025;
DisplayMessage("## PLC 연결 ##_IP: " + sIP + "_PORT: " + iport, true);
McProtocolTcp mcProtocol = new McProtocolTcp(sIP, iport); // Instantiate MC Protocol client
while (true)
{
if (ConnectToPLC(mcProtocol))
{
DisplayMessage("## PLC 연결 OK!!! ## _IP: " + sIP, true);
break;
}
else
{
DisplayMessage("## PLC 연결 오류!!! ## _IP: " + sIP, false);
Thread.Sleep(5000);
}
}
int i = 0;
while (true)
{
DisplayMessage($"{i}_## PLC Read...##", false);
try
{
// PLC 값 읽기
List<int> w_values = BatchReadWordUnits(mcProtocol, "D11490", 33);
if (w_values.Count == 0)
{
DisplayMessage("## 값이 없습니다 ##", true);
BatchWriteWordUnits(mcProtocol, "D11579", new List<int> { 0 });
}
else
{
// 데이터를 파일에 기록
string logPath = $"c:/tong/Plog/{DateTime.Now.ToString("yyyy-MM-dd")}.txt";
using (StreamWriter file = new StreamWriter(logPath, true))
{
foreach (var value in w_values)
{
file.Write("[" + value + "]");
}
file.WriteLine();
}
}
if (i % 2 == 0)
{
BatchWriteWordUnits(mcProtocol, "D11579", new List<int> { 1 });
DisplayMessage("## D11579에 1 전송 ##", true);
}
}
catch (Exception ex)
{
DisplayMessage($"## MC Protocol Error ##: {ex.Message}", true);
}
i++;
if (i > 3000)
{
i = 0;
MakeDirectory(directory);
}
Thread.Sleep(1000);
}
}
static void MakeDirectory(string directory)
{
try
{
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: Failed to create the directory - {ex.Message}");
}
}
static void DisplayMessage(string msg, bool writeToLog)
{
string sMsg = DateTime.Now.ToString() + " : " + msg;
Console.WriteLine(sMsg);
if (writeToLog)
{
string logPath = $"c:/tong/Plog/{DateTime.Now.ToString("yyyy-MM-dd")}.txt";
using (StreamWriter file = new StreamWriter(logPath, true))
{
file.WriteLine(sMsg);
}
}
}
static bool ConnectToPLC(McProtocolTcp mcProtocol)
{
try
{
mcProtocol.Open();
return true;
}
catch (Exception)
{
return false;
}
}
static List<int> BatchReadWordUnits(McProtocolTcp mcProtocol, string headDevice, int readSize)
{
try
{
int[] readValues = mcProtocol.GetDevice(blockType: "D", headDeviceNo: int.Parse(headDevice.Substring(1)), points: readSize);
return new List<int>(readValues);
}
catch (Exception)
{
return new List<int>();
}
}
static void BatchWriteWordUnits(McProtocolTcp mcProtocol, string headDevice, List<int> values)
{
try
{
mcProtocol.SetDevice(blockType: "D", headDeviceNo: int.Parse(headDevice.Substring(1)), values.ToArray());
}
catch (Exception ex)
{
DisplayMessage($"## PLC Write Error ##: {ex.Message}", true);
}
}
}728x90'PYTHON(파이썬) > 파이썬 활용' 카테고리의 다른 글
첨부파일을 포함한 e-mail 보내기 (17) 2024.11.14 python으로 간단하게 e-mail 보내기 (2) 2024.11.13 네이버에서 PYTHON으로 삼성전자 주가 가져오기 (5) 2024.11.01 파이썬으로 작성한 SERIAL 통신 프로그램 (0) 2024.10.31 PC에 연결된 SERIAL PORT 찾기 (파이썬 그리고 C#) (1) 2024.10.31 - 출력 및 파일 생성 :