Motor control PLC in Python
Project description
We have different types of devices like sov, motor, analog, digital, control valves etc. Each type of device has 100 items.
Now our software continuously monitors with the PLC to read some property of each type according to which we need to write some property.
As an example, if motor on command is high then we need to write on feedback at PLC end high. At the moment, I face the problem that it takes too much time to update.
Now I describe my software architecture:
-
I make individual class for each types of device. As an example for motor:
class Fn_Motor1D: def __init__(self,com,df,idxNo): self._idxNo =idxNo self.gen = com self.df = df self.setup() self.initilizedigitalinput() def setup(self): try: for tag,col in self.readalltags(): if col==3: self.cmd = str(tag) if col == 4: self.runingFB = str(tag) if col == 5: self.remoteFB = str(tag) if col == 6: self.healthyFB = str(tag) if col == 7: self.readyFB = str(tag) if col == 8: self.mccbonFeedBack = str(tag) if col == 9: self.overloadFeedBack = str(tag) if col == 10: self.faultFB =str(tag) if col == 11: self.delaytime = tag except Exception as e: print("exception raise",e.args) log_exception(e) def initilizedigitalinput(self): try: if len(self.healthyFB) > 3: self.gen.writegeneral.writenodevalue(self.healthyFB, 1) else: pass if len(self.remoteFB) > 3: self.gen.writegeneral.writenodevalue(self.remoteFB, 1) else: pass if len(self.readyFB) > 3: self.gen.writegeneral.writenodevalue(self.readyFB, 1) else: pass if len(self.mccbonFeedBack) > 3: self.gen.writegeneral.writenodevalue(self.mccbonFeedBack, 1) else: pass if len(self.overloadFeedBack) > 3: self.gen.writegeneral.writenodevalue(self.overloadFeedBack, 0) else: pass if len(self.faultFB) > 3: self.gen.writegeneral.writenodevalue(self.faultFB, 0) else: pass except Exception as e : log_exception(e) def process(self): try: oncommandvalue = self.gen.readgeneral.readtagvalue(self.cmd) if oncommandvalue: sleep(self.delaytime) self.gen.writegeneral.writenodevalue(self.runingFB, 1) else: self.gen.writegeneral.writenodevalue(self.runingFB, 0) except Exception as e: log_exception(e) def readalltags(self): n = 3 row, col = self.df.shape print(col) while n < col: data = self.df.iloc[self._idxNo, n] yield data,n n = n + 1
-
Call all motor devices at one class and make
listofallmotor1d
devices.class Cal_AllMotor1D: def __init__(self,df,com): self.df = df self.com = com self.listofmotor1D = [] self.setup() def setup(self): try: n =0 self.listofmotor1D.clear() while n< len(self.df.index): self.df.iloc[n, 0] = Fn_Motor1D(self.com, self.df, n) self.listofmotor1D.append(self.df.iloc[n,0]) n = n + 1 except Exception as e : print(e.args) log_exception(e) def process(self): n = 0 while n < len(self.listofmotor1Dir): self.listofmotor1Dir[n].process() n = n + 1 @property def listofmotor1Dir(self): if len(self.listofmotor1D) > 0: return self.listofmotor1D
-
Now I make
AllDevices
class where I call the all device and write monitoring process:import callallmotor1D import callallmotor2D_V1 import callallsov1S_V1 import callallsov2S_V1 import calallanalog_V1 import calallcontrolvalves_V1 import callallvibrofeeder_V1 import callallconveyor_V1 import pandas as pd class AllDevices: def __init__(self,comobject): self._comobject = comobject dfM1D = pd.read_excel(r'D:\OPCUA\Working_VF1.xls', sheet_name='Motor1D') dfM2D = pd.read_excel(r'D:\OPCUA\Working_VF1.xls', sheet_name='Motor2D') dfsov1S = pd.read_excel(r'D:\OPCUA\Working_VF1.xls', sheet_name='Valve1S') dfsov2S = pd.read_excel(r'D:\OPCUA\Working_VF1.xls', sheet_name='Valve2S') dfanalog = pd.read_excel(r'D:\OPCUA\Working_VF1.xls', sheet_name='AnalogTx') dfcontrolvalve = pd.read_excel(r'D:\OPCUA\Working_VF1.xls', sheet_name='ControlValves') dfvibrofeeder = pd.read_excel(r'D:\OPCUA\Working_VF1.xls', sheet_name='VibroFeeder') dfconveyor = pd.read_excel(r'D:\OPCUA\Working_VF1.xls', sheet_name='Conveyor') self.allmotor1dobjects = callallmotor1D.Cal_AllMotor1D(dfM1D, comobject) self.allmotor2dobjects = callallmotor2D_V1.Cal_AllMotor2D(dfM2D,comobject) self.allsov1sobjects = callallsov1S_V1.Cal_AllSov1S(dfsov1S,comobject) self.allsov2sobjects = callallsov2S_V1.Cal_AllSov2S(dfsov2S, comobject) self.allanalogobjects = calallanalog_V1.Cal_AllAnalogInputs(dfanalog,comobject) self.allcontrolvalveobjects = calallcontrolvalves_V1.Cal_AllControlValve(dfcontrolvalve,comobject) self.allvibrofeederobjects = callallvibrofeeder_V1.Cal_AllVibroFeeder(dfvibrofeeder,comobject) self.allconveyorobjects = callallconveyor_V1.Cal_AllConveyor1D(dfconveyor,comobject) def allmotor1dprocessing(self): self.allmotor1dobjects.process() self.allmotor1dobjects.process() def allmotor2dprocessing(self): self.allmotor2dobjects.process() def allsov1sprocessing(self): self.allsov1sobjects.process() def allanalogsprocessing(self): self.allanalogobjects.process() def allcontrolvaleprocessing(self): self.allcontrolvalveobjects.process() def allvibrofeederprocessing(self): self.allvibrofeederobjects.process() def allconveyorprocessing(self): self.allconveyorobjects.process()
-
At the end I all devices class in my main UI and run seperate thread each device type:-
def allmotor1dprocess(): while True : self.callalldevices.allmotor1dprocessing() def allmotor2dprocess(): while True: self.callalldevices.allmotor2dprocessing() def allsov1sprocess(): while True: self.callalldevices.allsov1sprocessing() def allananlogprocess(): while True: self.callalldevices.allanalogsprocessing() def allcontrolvalveprocess(): while True: self.callalldevices.allcontrolvaleprocessing() def allconveyorprocess(): while True: self.callalldevices.allconveyorprocessing() self.writeallmotor1dthread = threading.Thread(target=allmotor1dprocess) self.writeallmotor2dthread =threading.Thread(target=allmotor2dprocess) self.writeallsov1sthread1 = threading.Thread(target=allsov1sprocess) self.writeallsov1sthread2 = threading.Thread(target=allsov1sprocess2) self.writeallsov2sthread = threading.Thread(target=allsov2sprocess) self.writeallanalogthread = threading.Thread(target=allananlogprocess) self.writeallcontrolvalvethread = threading.Thread(target=allcontrolvalveprocess) self.writeallconveyorthread = threading.Thread(target=allconveyorprocess) self.writeallmotor1dthread.start() self.writeallmotor2dthread.start() self.writeallsov1sthread1.start() self.writeallsov1sthread2.start() self.writeallsov2sthread.start() self.writeallanalogthread.start() self.writeallcontrolvalvethread.start() self.writeallconveyorthread.start()
In this software architecture I really face problem to update the plc data.
As an example, let's suppose that I give on command for a motor. This will take time to update its run feedback. So, I need your expert view on this.
Please let me know how I can improve my coding to get process faster.