Seite 1 von 1

Einfache SPS mit rp2040 oder esp32

Verfasst: 19 Okt 2025, 17:07
von asp
Nachdem ich eine Klasse für die IO-Erweiterung viewtopic.php?t=85&sid=d4c22dfd39b10f28ec98e34a6c978538 erstellt und auf dem rp2040 abgespeichert habe, kann ich nun 32 Ein-/Ausgänge einfach beschreiben und es steht nichts mehr im Weg, eine einfache SPS zu programmieren:
RP2040-USB.png
RP2040-USB.png (237.02 KiB) 4920 mal betrachtet
Ein SPS-Programm schreiben Das SPS-Programm sps.py soll ein Programm programm.txt parsen und die im Programm aufgelisteten Befehle ausführen.

Code: Alles auswählen

# ----------------------------------------------
# dieses Programm wird von "sps.py" geparst
#
# Gültige Befehle
# ---------------
# s : einen Ausgang setzen
# r : einen Ausgang zurücksetzen
# p : einen Text ausgeben
# w : w 3 = 3 Sekunden warten
# ----------------------------------------------
p Benötigt das iopiplus-Board an i2c-Bus
p Testprogramm start:
s do17
p Heizen gestartet
w 5
r do17
p Heizen beendet
s do18
p Rühren gestartet
w 3
r do18
p Rühren beendet
p Programm beendet
oben ist das Programm und unten das SPS-Programm:

Code: Alles auswählen

from iopi_plus import IOPiPlus
import time

class SPSParser:
    def __init__(self):
        self.io = IOPiPlus()
        self.digital_outputs = {}  # Speichert DO Zustände

    def parse_program(self, filename):
        """Liest und führt ein SPS-Programm aus"""
        try:
            with open(filename, 'r') as file:
                lines = file.readlines()

            line_number = 0
            for line in lines:
                line_number += 1
                line = line.strip()

                # Leerzeilen und Kommentare überspringen
                if not line or line.startswith('#'):
                    continue

                # Befehl parsen und ausführen
                success = self._execute_command(line, line_number)
                if not success:
                    print(f"Fehler in Zeile {line_number}: {line}")
                    break

        except Exception as e:
            print(f"Fehler beim Lesen der Datei: {e}")

    def _execute_command(self, command, line_number):
        """Führt einen einzelnen Befehl aus"""
        parts = command.split(' ', 1)  # Ersten Teil (Befehl) abtrennen
        cmd = parts[0].lower()
        param = parts[1] if len(parts) > 1 else ""

        try:
            if cmd == 'p':  # Print
                print(f"PRINT: {param}")
                return True

            elif cmd == 's':  # Set Digital Output
                return self._set_digital_output(param, 1, line_number)

            elif cmd == 'r':  # Reset Digital Output  
                return self._set_digital_output(param, 0, line_number)

            elif cmd == 'w':  # Wait
                return self._wait(param, line_number)

            else:
                print(f"Unbekannter Befehl: {cmd} in Zeile {line_number}")
                return False

        except Exception as e:
            print(f"Fehler in Befehl '{command}': {e}")
            return False

    def _set_digital_output(self, do_param, value, line_number):
        """Setzt/Rücksetzt einen digitalen Ausgang"""
        if not do_param.startswith('do'):
            print(f"Ungültiger DO-Parameter: {do_param} in Zeile {line_number}")
            return False

        try:
            pin_number = int(do_param[2:])  # Zahl nach "do" extrahieren

            # Sicherheitsprüfung
            if pin_number < 1 or pin_number > 32:
                print(f"Pin {pin_number} außerhalb des gültigen Bereichs 1-32")
                return False

            # Pin konfigurieren und setzen
            self.io.set_pin_direction(pin_number, 0)  # Output
            self.io.write_pin(pin_number, value)
            self.digital_outputs[pin_number] = value

            status = "AN" if value == 1 else "AUS"
            print(f"DO {pin_number} {status}")
            return True

        except ValueError:
            print(f"Ungültige Pin-Nummer: {do_param} in Zeile {line_number}")
            return False

    def _wait(self, param, line_number):
        """Wartet für angegebene Sekunden"""
        try:
            seconds = float(param)
            print(f"Warte {seconds} Sekunden...")
            time.sleep(seconds)
            return True
        except ValueError:
            print(f"Ungültige Wartezeit: {param} in Zeile {line_number}")
            return False

    def get_output_status(self):
        """Gibt Status aller Ausgänge zurück"""
        return self.digital_outputs

# Beispiel für die Verwendung
if __name__ == "__main__":
    sps = SPSParser()
    print("SPS-Parser bereit")

    # Programm ausführen
    sps.parse_program("programm.txt")
Jetzt kann man das SPS-Programm programm.txt und das SPS-Ausführungsprogramm sps.py auf rp2040 laden und sps.py ausführen.