Samstag, 8. April 2023

  Copyright ©  Dipl.-Ing. Johannes Hofer 2022                                           

 

Ki2Plc

Die Möglichkeiten einer  SPS-Programmierung, um diese am Geschehen der künstlichen Intelligenz zu beteiligen



Beispiel Bit-Operator im Vergleich Simatic-Pyton

Bis jetzt zeigt das Ergbenis der Fragen, dass das Interesse an diesem Thema mehr aus dem Bereich der Python-Programmiere kommt. Besser fast nur 😀


SPS-Programmierer aus der IEC 61131-3 dagegen, stellen oft die Frage ob Python eine sichere Programmiersprache für eine Anwendung als SPS ist. Ich kann mir dazu keine Meinung bilden, aber wenn RUST als sicher eingestuft wird, dann ist es aus meiner Sicht auch Python. Außerdem macht das keinen Sinn in Python zu arbeiten, wenn man davon nicht überzeugt ist.

Ich denke eher das Gerät und dessen Betriebssystem auf dem die Software läuft, ist wesentlich an der Sicherheit beteiligt. Zudem soll ja die KiPlc in der Python-Version enthalten sein. Und dass ist in IEC-61131-3 bis jetzt nicht nachvollziehbar.

Nun zur Bitte des Bit-Operator-Vergleich. Hier das Beuspiel in FUP:




SPS-Programmierer kommen mit diesem Beispiel gut zurecht. Allerdings ist das hier nach meiner Meinung schon schwierig, da sich hier ein Set- und ein Assignment-Block befindet. Nun wir wollen ja nicht kneifen. Bei den noch folgenden Timer (nächster Blog-Beitrag), sieht das noch viel komplizierter aus. Zumindest auf der Python-Ebene 😌😎

Als Lösung habe ich folgendes Video ohne Ton vorbereitet (nicht in meinemYouTube-Kanal):



Im nächsten Blogbeitrag zeige ich den Einsatz der Timer wieder abgeleitet von der Simatic nach Python 🙋







Dienstag, 4. April 2023

 Copyright ©  Dipl.-Ing. Johannes Hofer 2022                                           

 

Ki2Plc

Die Möglichkeiten einer  SPS-Programmierung, um diese am Geschehen der künstlichen Intelligenz zu beteiligen



Wie soll der Anwender sein Programm organisieren?

Ich habe nun den Pfad Project hinzugefügt, welches die Anwendungen beinhalten soll, also das main.py und project.py mit den FCs und FBs ( in PyCharm)

Die Zykluszeit der PLC wird hier auf 5 ms = MIN_CYCLE festgelegt. Diese Zeit darf nicht überschritten werden, sonst findet kein logging und auch keine info statt, falls diese mit True durch die Instanzierung der Klasse plc = c_pyPlc angelegt worden waren.

plc = c_pyPlc(info=True, logging=False, optimize=False, cycle=MIN_CYCLE)
Wird der Parameter weggelassen, dann beträgt diese Zeit den default von MIN_CYCLE == 5ms und dass ist schon recht knapp bemessen. So könnte man diesen Parameter auch mit weniger oder mehr Zeit versehen. 

Der grundsätzliche Aufbau zur Bibliothek ist in main.py zu sehen und das SPS-Programm in project.py. Beide befinden sich im Pfad Project.

Somit haben wir schon einmal eine sauber Trennung der Bibliothek und der Anwendung gefunden 👍.

Project/main.py
from pyPlc import *
from project import fc_tor_sued

if __name__ == '__main__':
plc = c_pyPlc(info=True, logging=False, optimize=False, cycle=MIN_CYCLE)
plc.create_fc(fc_tor_sued)
plc.run()
#
while plc.is_running():
time.sleep(0.1)
pass

print("plc exit")

Project/project.py
from info import *
import time


def fc_tor_sued(self):
res = self.fct.UND('M0.0', self.neg_bit('M0.1'), 'M0.2')
c_info.print_info(self, "result in fc_tor_sued: " + str(res))
time.sleep(0.001)

Der time.sleep(0.001) == 1ms hat hier nichts zu suchen, soll aber vorerst zur Erklärung angewendet werden. Der c_info.print_info(...) ist nur für Testzwecke gedacht und soll den SPS-Entwickler unterstützen. Mit der Instanzbildung kann der dann abgeschaltet werden oder wird automatisch verdrängt, wenn die vereinbarte Zykluszeit (hier 5ms) überschritten werden. Ist das mal der Fall, dann wird dieser print gespeichert und später, falls es die Zykluszeit erlaubt, ausgegeben.

Was sich da noch an Reserven (auf meinem PC) bilden könnten und wie sich der print in unserem kleinen Beispiel fc_tor_sued verhält, schauen wir uns im Video an:


Wir erkennen, dass die Zykluszeit im Projekt eine wichtige Rolle spielt. Deswegen hat in der SPS ein time.sleep(...)  nichts zu suchen. Der SPS-Programmierer kennt das auch nicht, es sei denn, es handelt sich um einen Timer der SPS (später mehr)

In der Hauptanwendung dagegen, kann ein time.sleep(..) angewendet werden. Der wirkt sich  auf unseren Thread nicht sooo wesendlich aus. Hier können wir  in Ruhe noch  weitere  Dinge tun, also  z. B. den Server, Visualisierung oder anderes. 

Wer mit VS-Code arbeitet, bringt das main.py im Hauptprojekt unter, falls das so nicht geht.

Vorerst mal abwarten, welche Fragen noch kommen. Ich melde mich dann wieder mit einem neuen Blog-Beitrag 🙋



Montag, 3. April 2023

  Copyright ©  Dipl.-Ing. Johannes Hofer 2022                                           

 

Ki2Plc

Die Möglichkeiten einer  SPS-Programmierung, um diese am Geschehen der künstlichen Intelligenz zu beteiligen

 




Vorab einige Antworten zu den Fragen

Im oben gezeigten Video wird der grundsätzliche Ablauf für Start, Stop und Programm-Ende gezeigt. Zusätzlich die Anwendung über einen FC und FB. Damit wir ordentliche Strukturen erhalten, sollten FCs und FBs als Programmbausteine in einer Anwendung verwendet werden. 

Natürlich reicht es auch aus, einfach drauf los zu legen. Dann allerdings wirde es mühsehlig, denn Funktionen sind teilweise "private" bzw. "protected" und das bedeutet, dass die so ohne weiteres nicht angewendet werden können, da der  Python-Übersetzter das nicht akzeptiert und meldet, dass er das eine oder andere nicht kennt. Zudem muss die bestehende Struktur angepasst werden, falls man das nicht möchte und bedeutet auch eine Menge Arbeit, welche sich nicht lohnt. 

Zudem werden FCs und FBs überwacht und kontrolliert im PLC-Thread angewendet. Das gibt Sicherheit und bei einer Plc (SPS) und sollte das auch so sein 😁

Sollte in der eigenen Anwendung eine Exception entstehen, dann kann diese unter Umständen nicht bemerkt werden und die PLC läuft weiter ohne in die Anwendung zurück zu kommen. Das heisst:

Der Anwender sollte in jedem Falle seine eigene Exception abfangen, wenn er selbst erstellten Code anwendet.

Hier ein Beispiel (nicht in You-Tube):
from pyPlc import *

plc = c_pyPlc(info=True, logging=False, optimize=False)


def fc_tor_sued():
res = plc.fct.UND('M0.0', plc.neg_bit('M0.1'), 'M0.2')
print("res in fc_tor_sued: ", res)


plc.create_fc(fc_tor_sued)
plc.run()
time.sleep(0.1)
erg = plc.fct.UND('M0.0', plc.neg_bit('M0.1'), 'M0.2')
print("\ngeht auch: ", erg)
plc.prog_exit()!

Die Funktion fc_tor_sued wird als FC mit plc.create_fc(fc_tor_sued) integriert und somit kontrolliert angewendet. Dann wird später das UND noch einmal, ohne in den FC einzubinden, angewendet. Macht in diesem Fall nichts, da kein Laufzeitfehler entsteht. Ist natürlich nicht logisch aber was soll's.

Hinweis: Das UND wird es in Zukunft nicht mehr geben. Alle Tokens in Englisch, also AND 😏

Hat allerdings die Zeile print("\n.. einen Fehler, wie z. B. wird nicht erg verwendet, sondern versehentlich res, was hier in der Zeile nicht bekannt ist, dann wird der error von der PLC ausgeschlossen und das Programm, also die PLC läuft ewig weiter und kommt nicht zum Ende. Hier im folgenden Film ohne Ton gezeigt und wie man das verhindert, indem man seine eigenen Zeilen (Anwenderprogramm) mit einem eigenen try-Blog versieht.:




Besser ist natürlich die Anwendung der Funktionen aus dem Projekt über FCs oder FBs 😏 



Fortsetzung folgt im nächsten Blog 🙋





Montag, 27. März 2023

 Copyright ©  Dipl.-Ing. Johannes Hofer 2022                                           

 

Ki2Plc

Die Möglichkeiten einer  SPS-Programmierung, um diese am Geschehen der künstlichen Intelligenz zu beteiligen



Die pyPlc

Nachdem nun doch einige nachgefragt haben, wie es nun mit der KI2Plc weitergeht, habe ich mich entschlossen zunächst eine pyPlc in Python zu programmieren. Damit wird die Grundlage gebildet, mit einer SPS nach Industriestandard vorerst seine eigenen Projekte unter Windows und Python zu testen, um diese danach in ein Gerät zu laden. Hier wird in der ersten Phase folgendes Ziel zur Umsetzung geplant:

  • pyPlc komplett in Python-Code auf PyCarm
  • Funktionen entsprechend nach IEC 61131-3 - allerdings in Python 
  • Operanden nach internationaler Darstellung (englisch)
  • Merker (M, MW, MDW)
  • Input (I, IW)
  • Output (Q, QW)
  • Datenbaustein (DB)
  • Timer (TON, TONR, TOF, TP)
  • Zähler(CTU, CTD, CTUD)
  • Scale
  • Unscale
  • Funktionsbausteine (FB)
  • Functionen (FC)
  • plc_Server
  • und vieles mehr, wie z.B.: Taktkette, py2SCL, Zweipunkt-Regler, PID ...

Das ganze basiert auf Basis mit meinem YouTube-Kanal, allerdings nur in Kurzform als jeweilige Einleitung zum Thema. Die Videos fürs Mitmachen allerdings auf meinem Blog oder einer neuen Webseite (mal sehen). Da kann dann jeder beliebig oft die Videos studieren ohne mit einer scheiss Werbung belästigt zu werden.

pyPlc lernt Machine-Learning 😂

In Python kann die Idee KI2Plc sehr gut angewendet werden. Dieser Prozess kann ebenfalls in einem Gerät, wie z. B. die Simatic in SCL übersetzt zur Anwendung kommen. Der Übersetzer Python2SCL ist bereits in Arbeit. 

Das bedeutet, dass in der Plc ein Lernprozess stattfindet, der beständig ist und nie endet.

Die Umsetzung ist relativ einfach, wenn man von dem Wissen der KI ableitet. Zur Bewertung bzw. Klassifizierung werden die Daten in der PLC innerhalb des Programmes erzeugt und kommen so zur Auswertung. Das sind in erster Linie :
  • Prozesszeit
  • Gewichtung der Prozesse
Diese bestimmen dann den weiteren Ablauf und erklärt auch, dass die Prozesse in FCs und FBs aufgeteilt sein sollten. Es gibt in der pyPlc also keine eigenständigen Funktionen (def), zumindest wird das nicht empfohlen. Dazu dienen die Methoden.

Natürlich kann jeder PLC-Programmierer in Python machen was er will, bedeutet aber, dass sein Algorithnus in diesem Fall nicht bewertet werden kann und somit auch nicht sooo lernfähig ist.

Die gelante Software-Struktur

Wir überlassen nichts dem Zufall und planen unser Vorhaben wie bereits der jetzige Stand zeigen kann:

Die Klasse c_pyPlc ist unsere Ausgangsklasse, welche von der Klasse c_plc_init abgeleitet wird. Diese wiederum ist von c_plc_helper abgeleitet und letztendliche diese von c_info. Damit können wir die Methoden aus allen Ableitungen in der Klasse c_pyPlc nutzen (nicht die private). Zudem hat die Klasse c_pyPlc zusätzlich die Komposition mit der Klasse c_plc_fct, welche eine Vielzahl der SPS-Funktionen anbietet.

Und damit es nicht langweilig wird, besitzt die Klasse c_plc_init noch die Klassen socket und c_plc_database, denn schliesslich brauchen wir Merker, Fbs, Fcs, Eingänge, Ausgänge und noch vieles mehr.

 
..... Fortsetzung folgt im nächsten Blog-Beitrag 🙋



Zum Thema auf meinem Blog:
Natürlich wie immer hier kostenfrei und mit entsprechender Interesse zu diesem Thema,  kann ich das umgsetzen. Also meldet euch! 









Mittwoch, 22. März 2023

   Copyright ©  Dipl.-Ing. Johannes Hofer 2022                                           

 

Ki2Plc

Die Möglichkeiten einer Programmierung im TIA-Portal, um diese am Geschehen der künstlichen Intelligenz zu beteiligen



Simatic S7-1200 und Snap7 - Teil 2 (matrix)


Die Grundposition ist der Ausgangspunkt aller Dinge. Wie auch in Python wird hier zuerst die Grundposition überprüft und erst danach ist eine weitere Verarbeitung möglich.  Deswegen auch diese etwas verwirrenden Zeilen zum folgenden Bild:


Zunächst wird in Zeile 41 der IPL in ein char gewandelt um danach weiterhin verwendet zu werden. In unserem DB sind die Zustände als char gespeichert, deswegen die Anweisung von INT_TO_CHAR.

Solange also die Grundposition (gp) nicht erreicht wurde, wird der Baustein mit Zeile 46 verlassen. Ist die Grundposition erreicht, wird in Zeile 49 der Merker gesetzt und ein eventuell aufgetretener Fehler in Zeile 50 gelöscht. Nun wird solange das RETURN ausgeführt (Zeile 51), bis die Grundposition verlassen wird. In unserem Fall durch drücken des Eingangs V1 für den Zyl. auszufahren. So schlägt keine IF-Anweisung mehr (Zeilen 42 und 48) zu und das Programm kann ab Zeile 55 beginnen.


Nun kommt zuerst die Fehlerauswertung. Sollte der IPL den Zustand des error-Sektor besitzen, hier sind das zwei, dann wird der error_status gesetzt (Zeile 62), die Grundposition gelöscht (Zeile 61) und der Baustein verlassen. Da wir zu Beginn in Zeile 5 den Ausgang immer löschen (#matrix_out := False, in Teil-1 zu sehen) ist dieser automatisch False solange keine Zuweisung auf  True erfolgt. Der error_status ist als Ausgang Output in der Bausteinschnittstelle deklariert deklariert (letztes Bild).


Der Zustand no action entsteht immer dann, wenn der V1 nicht gesetzt ist. Ist also der IPL mit den zwei Zuständen (Zeilen 68 und 70) erfüllt, wird der Ausgang und die Grundstellung gelöscht. Hier könnte Zeile 74 entfallen 😌 , da das ja beim Eintritt des FBs immer geschieht.


Der Zustand action entsteht immer wenn der Eingang V1 gesetzt ist. Ist also der IPL mit den Zeilen 80 bis 84 erfüllt, dann wird der Ausgang in Zeile 87 gesetzt. In Zeile 91 wird die Grundstellung gelöscht und entspricht im Python der Exception. Eines der drei Zustände error, no action oder action muss vorhanden sein. Wenn nicht wird diese Zeile 91 erreicht und es muss wieder eine Grundstellung erreicht werden, damit das Spiel von vorne beginnt.

Das wäre eine getippte Lösung zur Matrix. Natürlich sollte die Matrix so interpretiert werden, dass jede beliebige Matrix übersetzt werden kann. Dabei ist auch zu überlegen, ob man nicht einen anderen Weg einschlägt, denn diese Matrix wird umfangreich, wenn grössere Projekte anstehen und auch SPS-spezifische Dinge hinzukommen.

Das könnten also Analogwerte sein, oder die noch nicht erklärten warnings, welche den Zeitfaktor berücksichtigen oder die in den Videos genannten Synapsen, welche zusätzliche Atrribute erhalten können.

Fazit: ? 
Man könnte eine Python-Sequenz an die SPS senden (write_DB), welche interpretiert wird. Also sowas wie IEC61131-3_Python? oder plc_python? oder sowas 😁, schließlich gibt es ja auch micropython!



🙋













Dienstag, 21. März 2023

  Copyright ©  Dipl.-Ing. Johannes Hofer 2022                                           

 

Ki2Plc

Die Möglichkeiten einer Programmierung im TIA-Portal, um diese am Geschehen der künstlichen Intelligenz zu beteiligen



Simatic S7-1200 und Snap7 - Teil 1

Die uns bereits bekannte Kommunikation mit den Bausteinen TRCV_C und TSENDE_C aus dem TIA-Portal (Open user communication) habe ich zur allgemeinen Information im Projekt belassen, nutze diese hier aber nicht mehr

Wir verwenden jetzt python-snap7 um die Kommunikation nun unabhängig der angebotenen Bausteine aus der Open user communication umzusetzen und schaffen so eine kleine Grundlage für ein mögliches Ziel 😁

IEC-61131-3-Python oder Plc-Python zu schaffen

Bevor wir uns damit in der Zukunft beschäftigen können, müssen wir die Grundlage erarbeiten, diese Aufgabe richtig zu verstehen. Erst dann ist eine Lösung bzw. mehrere Teil-Lösungen machbar.




Wir benötigen python-snap7, wie im Link gezeigt und können nun gezielt in einem DB Informationen ablegen, welche in SCL direkt übersetzt werden und eine quasi hardcodierte Lösung anbietet.

Darüber muss man unbedingt nachdenken, denn jetzt kann eine quasi Hardcodierung aufgrund der Daten aus KI2Plc erfolgen, welche bei jedem Training eine neue Datei und somit einen neuen Ablauf ermöglicht.

Ich kannte snap7 noch aus meiner C/C++-Tätigkeit und freue mich sehr über diese neue integrierte Lösung in python-snap7, welche ausserordentlich gut funktioniert, wenn man diese richtig anwendet und dazu die Dinge in der SPS folgerichtig versteht 😎.


Der neue Baustein Cylinder_FB (Main[OB1]) beinhaltet nun alle Dinge welche notwendig sind unsere Matrix aus KI2Plc umzusetzen. Also IPL lesen, Matrix interpretieren und OPL setzen. Sozusagen wie ein Rezept in einem Kochbuch - all in one 😀

Diese Lösung funktioniert, wie im noch ausstehendem Video zu sehen und soll keine komplette Lösung darstellen, sondern den neuen Weg erklären. Schritt für Schritt kommen wir so dem grossen Ziel näher.


Zunächst werden wir einen kleinen Check vornehmen und die gelieferten Daten überprüfen und dann den Input-Layer (IPL) lesen. Danach überprüfen wir die Grundposition und schliesslich den Rest aus der Matrix mit error, no action und action. So entsteht der Ausgangs-Layer (OPL).

Wir verwenden dazu den uns bereits bekannten DB SendReceiveData und davon den Receive-Abschnitt. Dort schreibt unser python-snap7 die Daten der Matrix hin.



In Zeile 3 und 4 sehen wir z. B. die Anzahl der Bytes (84) welche die Matrix umfasst. Dann folgen die Matrix-Daten, welche nun hardcodiert übersetzt werden können. 

Das heisst: Die Indizes, wie beim Check zu sehen (Bild unten), werden jeweils speziell in einem DB abgelegt. Hier nicht, hier habe ich diese zur Vereinfachung der Erklärung in den DB unter Constant abgetippt - damit keine Mißverständnissse entstehen -. 

So lässt sich das am einfachsten erklären.


Eine Datenprüfung im Sinne einer Checksum ist das nicht und soll es auch nicht sein. Wir sind damit zufrieden und gehen davon aus, wenn Zeile 15 erreicht wird, dass wir im Baustein weiter verfahren können um den IPL einzulesen.


Auch hier kommen wir mit einer einfachen Auswertung zurecht und haben nun einen Wert in #ipl, welcher uns zum Vergleich in der Matrix dient. Wichtig ist, dass die Reihenfolge der Daten der Reihenfolge in KI2Plc entspricht. Also wie hier ist der erste Eingang der V1 für Zyl.-Vor-Zur.
Beginnen wir im nächsten Teil mit der Grundposition  🙋













 

Montag, 20. März 2023

   Copyright ©  Dipl.-Ing. Johannes Hofer 2022                                           

 

Ki2Plc

Die Möglichkeiten einer Programmierung im TIA-Portal, um diese am Geschehen der künstlichen Intelligenz zu beteiligen



 

Pico-EVB als mini-plc Teil-3

Nun zur Matrix selbst. Ich denke dass auf einem Pico kein Programm im Sinne einer SPS zur Anwendung kommt. Projekte mit geringem Umfang sind sicherlich interessant und auch umsetzbar. Ich habe hier nun von der Matrix die action, no_action und den error aus der Matrix von KI2Plc verarbeitet. Die Grundposition fehlt hier im Beispielund macht wohl wenig Sinn, da der Zylinder ohnehin nur simuliert wird.


Hier wird _matrix() vom _thread aufgerufen und sollte ohne Unterbrechung über while True laufen. Diese Funktion ruft __matrix auf, wenn run eingeschaltet ist (True). Dazu wird auch die LED.on() verwendet, damit wir auch etwas sehen können. Der Ausgang V1_Od wird ebenfalls auf True gesetzt. Ist run False oder die Funktion __matrix() liefert False, dann schalten wir die LED ab und setzen den Ausgang zurück.



In der Funktion __matrix() erfolgt die Auswertung der Liste matrix_lst mit der Reihenfolge error (Zeile 135), no action (Zeile 140) und action (Zeile 144). 

Wie auch immer ist hier diese Funktion nur dann anwendbar, wenn die Daten aus KI2Plc vorhanden sind. Der status wird ja in Zeile 130 gelesen und mit den Werten aus der Liste verglichen. Fehlt also diese Liste, gibt es keine gültige Auswertung. Da wir hier im Pico lediglich ein Beispiel erklären, fehlt die Speicherung der Daten im Pico. Das wäre ohne Probleme möglich, müsste aber dann auch wieder gelesen werden. Dieser Aufwand ist nicht lohnenswert, da ohnehin keiner den Pico als Zylindersteuerung verwendet 😀

Im nächsten Bild sei noch einmal der Python-Abschnitt gezeigt, welcher in KI2Plc verwendet wird. Hier ist auch die Grundstellung berücksichtigt (Zeile 300).


Im nächsten Teil werde ich die Anwendung des Zylinders in einer Simatic S7-1200 mit Python und Snap7 zeigen 🙋