im目前正在使用python-snap7进行项目。 为了执行我的脚本,我使用WinPython64-3.6.7.0Qt5和python-snap7(0.10)软件包以及Windows 10。
# -*- coding: utf-8 -*-
"""
Created on Fri Nov 24 13:41:00 2017
@author: Nils
"""
import snap7
import snap7.client as c
import time
import Neural_Network
from snap7.util import *
from snap7.snap7types import *
from pathlib import Path
import struct
def ReadMemory_E(plc,byte,bit,datatype):
result = plc.read_area(areas['PE'],0,byte,datatype)
if datatype==S7WLBit:
return get_bool(result,0,1)
elif datatype==S7WLByte or datatype==S7WLWord:
return get_int(result,0)
elif datatype==S7WLReal:
return get_real(result,0)
elif datatype==S7WLDWord:
return get_dword(result,0)
else:
return None
def ReadMemory_A(plc,byte,bit,datatype):
result = plc.read_area(areas['PA'],0,byte,datatype)
if datatype==S7WLBit:
return get_bool(result,0,1)
elif datatype==S7WLByte or datatype==S7WLWord:
return get_int(result,0)
elif datatype==S7WLReal:
return get_real(result,0)
elif datatype==S7WLDWord:
return get_dword(result,0)
else:
return None
#Umwandlung der negativen Bitzahlen in positive Bitzahlen
def GetVar(EW):
count_Bit = 15
EW_Bin = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
if EW >= 0:
while count_Bit >= 0:
if EW/(2**count_Bit) >= 1:
EW_Bin[count_Bit] = 1
EW -= 2**count_Bit
count_Bit = count_Bit - 1
else:
EW_Bin[count_Bit] = 0
count_Bit -= 1
return EW_Bin
else:
EW = EW * (-1) -1
while count_Bit >= 0:
if EW/(2**count_Bit) >= 1:
EW_Bin[count_Bit] = 0
EW -= 2**count_Bit
count_Bit -= 1
else:
EW_Bin[count_Bit] = 1
count_Bit -= 1
return EW_Bin
#Zeitüberwachung, einzelne Phase > 30s -> Fehler, Zeitüberschreitung
def Overtime(t_0, EW):
#Zeit seit Start der Phase ermitteln
t_1 = time.time()
total = t_1-t_0
#Zeit > 30 Sekunden -> Zeitüberschreitung
if((total) > 30):
return EW + 20
else:
return EW
#PLC-Variablen auslesen bis gewünschtes Ereignis (Eingangswort, Bit, erwarteter Wert)
#eingetreten ist
def ReadPLC_Int(EW,Bit,Ex,output):
#Variable zur Überprüfung, ob das gewünschte Ereignis eingetreten ist
Trigger = 2
#Eingangswörter Initialisieren
E20_Word = ReadMemory_E(plc,20,0,S7WLByte)
E21_Word = ReadMemory_E(plc,21,0,S7WLByte)
E100_Word = ReadMemory_E(plc,100,0,S7WLByte)
E101_Word = ReadMemory_E(plc,101,0,S7WLByte)
#Eingangswörter werden als Bits in ein Array geschrieben
E20 = GetVar(E20_Word)
E21 = GetVar(E21_Word)
E100 = GetVar(E100_Word)
E101 = GetVar(E101_Word)
#Ausgabewörter Initialisieren
A21_Word = ReadMemory_A(plc,21,0,S7WLByte)
A21 = GetVar(A21_Word)
#@Phase 4: Merken des letzten passierten Platzes
if EW == 4:
curent_position = 0
#Timer Starten zur Zeitüberwachung
t_start = time.time()
#Werte überprüfen bis Trigger erreicht ist
while Trigger != Ex:
#Auto-Schalter einlesen
output[1] = E100[10]
output[2] = E21[10]
output[3] = E20[11]
#Stop-Schalter einlesen
output[19] = E100[8]
output[20] = E21[8]
output[21] = E20[12]
#Bei Aktivierung des zugehörigen Triggers wird die While-Schleife nach dem
#aktuellen Durchlauf beendet:
#Phase 1: Egal welcher Start-Taster gedrückt wurde.
if EW == 1:
if (E20[10]) | (E21[9]) | (E100[9]):
Trigger = 1
#Phase 2: Teil an Sensor
elif EW == 2:
Trigger = E100[11]
#Phase 3: Teil an Bandanfang
elif EW == 3:
Trigger = E20[9]
#Phase 4: Egal welcher Auswurfaktor ausgefahren ist
elif EW == 4:
if(A21[11] | A21[10] | A21[9]):
Trigger = 1
#Phase 5: Wenn alle Auswuraktor in Ausgangsposition
elif EW == 5:
if ((A21[11]) | (A21[10]) | (A21[9]) == 0):
Trigger = 1
#Fehlererkennung:
#Fehler wenn Auto-Schalter auf 0
elif (E100[10] & E21[10] & E20[11]) == 0:
EW = 20
#Fehler wenn Stop-Schalter auf 0
elif (E100[8] & E20[12] & E21[8]) == 0:
EW = 21
#Zeit überprüfen (außer bei Phase 1)
if EW != 1:
EW = Overtime(t_start, EW)
#Fehlerüberprüfung: Bei einem auftretendem Fehler wird die While-Schleife sofort
#unterbrochen
if ((EW == 20) | (EW == 21) | (EW == 22) | (EW == 23) | (EW == 24) | (EW == 25)):
break
#Delays in Phase 1 und in Phase 2
if Trigger == 1:
#@Phase 1: Kurze Pause wenn sich Magazin nicht in Position "hinten" befindet
if (EW == 1):
if (E101[10] != 1):
time.sleep(1.5)
#@Phase 2: Pause für Verzögerung des Induktiven-Sensors
if EW == 2:
time.sleep(1.0)
#@Phase 4: Letzter Standpunkt des Zylinders auf TB aktuallisieren
if EW == 4:
if E20[13]:
curent_position = 1
elif E20[14]:
curent_position = 2
elif E20[15]:
curent_position = 3
#Um Durchlaufzeit in Phase 4 zu minimieren werden nur die nötigen Daten
#eingelesen
if EW != 4:
#Eingangswörter werden von der Sps geladen
E21_Word = ReadMemory_E(plc,21,0,S7WLByte)
E100_Word = ReadMemory_E(plc,100,0,S7WLByte)
E101_Word = ReadMemory_E(plc,101,0,S7WLByte)
#Eingangswörter werden als Bits in ein Array geschrieben
E21 = GetVar(E21_Word)
E100 = GetVar(E100_Word)
E101 = GetVar(E101_Word)
#Wörter werden von der Sps geladen
E20_Word = ReadMemory_E(plc,20,0,S7WLByte)
A21_Word = ReadMemory_A(plc,21,0,S7WLByte)
#Wörter werden als Bits in ein Array geschrieben
E20 = GetVar(E20_Word)
A21 = GetVar(A21_Word)
#Ausgabe Phase 1: Magazin Stellung
if EW == 1:
output[0] = E101[10]
#Ausgabe Phase 2: Auto-Schalter überprüfen
elif EW == 2:
#Induktiv -> Silber
if E101[12] == 1:
output[4] = 0
output[6] = 1
output[8] = 0
#Nicht induktiv + Hell -> Weiß
elif E101[13] == 1:
output[4] = 0
output[6] = 0
output[8] = 1
#Nicht induktiv + Dunkel -> Schwarz
elif E101[13] == 0:
output[4] = 1
output[6] = 0
output[8] = 0
#Ausgabe Phase 3: Dreharm
elif EW == 3:
output[17] = E101[8] #MA Stoßer eingefahren
#Ausgabe Phase 4: Einsortierung
elif EW == 4:
if curent_position == 1:
output[5] = 0
output[7] = 0
output[9] = 1
elif curent_position == 2:
output[5] = 1
output[7] = 0
output[9] = 0
elif curent_position == 3:
output[5] = 0
output[7] = 1
output[9] = 0
#Ausgabe Phase 5: Endstellungen
elif EW == 5:
if A21[11] == 0:
output[10] = 1
else:
Ausgabe[10] = 0
if A21[10] == 0:
output[11] = 1
else:
output[11] = 0
if A21[9] == 0:
output[12] = 1
else:
output[12] = 0
if A21[14] == 0:
output[15] = 1
else:
output[15] = 0
if A21[13] == 0:
output[16] = 1
else:
output[16] = 0
output[13] = E21[12] #DA Oben
output[14] = E21[14] #DA Start Pos
#Ausgabe bei Fehlerfällen:
#Auto-Schalter
elif EW == 20:
output[1] = E100[10]
output[2] = E21[10]
output[3] = E20[11]
#Stop-Schalter
elif EW == 21:
output[19] = E100[8]
output[20] = E21[8]
output[21] = E20[12]
#Zeitüberschreitung MA
elif EW == 22:
output = [0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0]
#Zeitüberschreitung DA
elif EW == 23:
output = [0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0]
#Zeitüberschreitung TB
elif ((EW == 24) | (EW == 25)):
output = [0,0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0]
return output
#Fehlerüberprüfung zwischen den einzelnen Phasen
#def Fehler(output):
#Auto-Schalter Fehler
if (output[1] & output[2] & output[3]) != 1:
return 1
#Stop-Schalter Fehler
elif (output[19] & output[20] & output[21]) != 1:
return 1
#Zeitüberschreitung Fehler
elif ((output == [0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0]) | (output ==
[0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0]) | (output ==
[0,0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0])):
return 1
else:
return 0
#Entsprechend der Manuellen Eingabe zu Beginn des Programmes wird das ermittelte
#Output-Array unter dem entsprechenden Dateien-Pfad abgespeichert
def Output_Data_txt(output, function):
cout_data_ind = 0
count_Bit = 0
#Trainingsdaten
if function == 1:
#Ermittlung der nächst möglichen Bezeichnung
TD_file = Path("Trainingsdaten/TD_{0}.txt".format(cout_data_ind))
while TD_file.is_file() == 1:
cout_data_ind += 1
TD_file = Path("Trainingsdaten/TD_{0}.txt".format(cout_data_ind))
#Schreiben des Output-Arrays in entsprechende txt-Datei
fobj_out = open('Trainingsdaten/TD_{0}.txt'.format(cout_data_ind),"w")
while count_Bit < 22:
fobj_out.write('{}'.format(output[count_Bit]))
fobj_out.write(";")
count_Bit += 1
fobj_out.close()
#Automatisierter Professor
elif function == 2:
#Ermittlung der nächst möglichen Bezeichnung
TD_file = Path("Automatisierter_Professor/Uebergabedaten_{0}.txt".format(cout_data_ind))
while TD_file.is_file() == 1:
cout_data_ind += 1
TD_file = Path("Automatisierter_Professor/Uebergabedaten_{0}.txt".format(cout_data_ind))
#Schreiben des Output-Arrays in entsprechende txt-Datei
fobj_out = open("Automatisierter_Professor/Uebergabedaten_{0}.txt".format(cout_data_ind),"w")
while count_Bit < 22:
fobj_out.write('{}'.format(output[count_Bit]))
fobj_out.write(";")
count_Bit += 1
fobj_out.close()
#Funktionseingabe durch manueller Eingabe ermitteln
def select_function():
Input = input("Welche Funktion soll das Programm durchfuehren:\n\n1 -> Trainingsdaten\n2 -> Automatisierter Professor\n\nEingabe: ")
if Input == 1:
print ("\nGewählte Funktion: Trainingsdaten")
return Input
elif Input == 2:
print ("\nGewählte Funktion: Automatisierter Professor")
return Input
else:
print ("\nFalsche Eingabe\n")
select_function()
#Zylinderzahl durch manueller Eingabe ermitteln
def select_number_cylinder():
Input = input("\nAnzahl der Zylinder im Magazin? (1-12)\n\nEingabe: ")
print ("\nGewählte Anzahl: {0}".format(Input))
if (Input > 0) & (Input <= 12):
return Input
else:
print ("Falsche Eingabe\n")
select_number_cylinder()
if __name__=="__main__":
Output = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
#Verbindung mit Sps aufbauen
plc = c.Client()
plc.connect('192.168.1.1',0,1)
#Eingabe der gewünschten Funktion
function = select_function()
#Eingabe der Anzahl an Zylindern im Magazin
number_of_cylinders = select_number_cylinder()
count_cylinders = number_of_cylinders
while count_cylinders >= 1:
print (count_cylinders)
#Phase 1: Überprüfung der Startposition des Magazins, nur in erstem Durchlauf
#vorgegeben
if count_cylinders == number_of_cylinders:
Output = ReadPLC_Int(1,0,1,Output)
print ("Phase 1")
print (Output)
else:
Output[0] = 1
#Phase 2: Einlesen des Induktion- und Farb-Sensors
if Fehler(Output) == 0:
Output = ReadPLC_Int(2,0,1,Output)
print ("Phase 2")
print (Output)
#Phase3: Zeitüberprüfung Dreaharm
if Fehler(Output) == 0:
Output = ReadPLC_Int(3,0,1,Output)
print ("Phase 3")
print (Output)
#Phase 4: Einsortierung
if Fehler(Output) == 0:
Output = ReadPLC_Int(4,0,1,Output)
print ("Phase 4")
print (Output)
#Phase 5: Endstellungen überprüfen
if Fehler(Output) == 0:
Output = ReadPLC_Int(5,0,1,Output)
print ("Phase 5")
print (Output)
#Phase 6: Überprüfung der Endposition des Magazins
#Position nur in letztem Durchlauf vorgegeben
if ((Fehler(Output) == 0) & (count_cylinders == 1)):
Pos_MA = ReadMemory_E(plc,101,0,S7WLByte)
Pos_MA = GetVar(Pos_MA)
Output[18] = Pos_MA[11]
print ("Phase 6")
elif ((Fehler(Output) == 0) & (count_cylinders > 1)):
Output[18] = 1
print ("Phase 6")
print (Output)
#Ausgabe in txt-Format
Output_Data_txt(Output, function)
#Neuer Durchlauf, Hand- & Stopschalter auf 1
Output = [0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1]
count_cylinders -= 1
print ("\nEnde des Einleseprozesses\nNeuronales Netzt wird gestartet...\n")
Neural_Network.start_neural_Network(number_of_cylinders)
我收到以下错误:
OSError:异常:读取0x00000000214119D0的访问冲突TypeError:byref()参数必须是ctypes实例,而不是'NoneType'。
Traceback (most recent call last):
File "PLC.py", line 399, in <module>
plc = c.Client()
File "C:\Users\WAdmin\Documents\Projektarbeit_Grether_Schlindwein\WPy-3670\python-3.6.7.amd64\lib\site-packages\snap7\client.py", line 38, in __init__
self.create()
File "C:\Users\WAdmin\Documents\Projektarbeit_Grether_Schlindwein\WPy-3670\python-3.6.7.amd64\lib\site-packages\snap7\client.py", line 49, in create
self.pointer = S7Object(self.library.Cli_Create())
OSError: exception: access violation reading 0x00000000214119D0
Exception ignored in: <bound method Client.__del__ of <snap7.client.Client object at 0x000001C024C89080>>
Traceback (most recent call last):
File "C:\Users\WAdmin\Documents\Projektarbeit_Grether_Schlindwein\WPy-3670\python-3.6.7.amd64\lib\site-packages\snap7\client.py", line 41, in __del__
self.destroy()
File "C:\Users\WAdmin\Documents\Projektarbeit_Grether_Schlindwein\WPy-3670\python-3.6.7.amd64\lib\site-packages\snap7\client.py", line 57, in destroy
return self.library.Cli_Destroy(byref(self.pointer))
TypeError: byref() argument must be a ctypes instance, not 'NoneType'