Motor control PLC in Python
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.