GPIOs von einem RaspberryPi auf RevolutionPi

Mit den RevPiNet* Klassen, können wir über das Netzwerk auf das Prozessabbild zugreifen. Diese Funktion nutzen wir nun, um den Wert eines GPIO-Pins des Raspberry Pis in unserem Prozessabbild zu verwenden.

piCtory Konfiguration am Revolution Pi

Auf dem Revolution Pi legen wir ein virtuelles Device mit dem Namen virtrpi an, über das der Raspberry Pi mit dem Revolution Pi Daten austauscht. Den ersten Input nennen wir inputbyte1

Virtuelles Device virtrpi mit Positionsnummer 64
Erster INP auf virtrpi mit dem Namen inputbyte1.

Über das virtuelle Device können alle Programme, die das Prozessabbild verwenden, auf die Daten zugreifen. Ob es sich dabei um ein Steuerungsprogramm in Python3 mit RevPiModIO oder logi.CAD handelt, spielt keine Rolle! Auch Visualisierungslösungen, welche das Prozessabbild verwenden, erhalten Zugriff auf die Daten.

RevPiPyLoad auf dem Revolution Pi

Damit ein System mit RevPiNetIO über das Netzwerk auf das Prozessabbild zugreifen kann, muss RevPiPyLoad (ab Version 0.6.5) auf dem Revolution Pi installiert sein! [Installationsanleitung]

Nach der Installation muss die RevPiPyLoad-Konfiguration angepasst werden. Besonders wichtig ist ein Wert der Konfigurationsdatei /etc/revpipyload/revpipyload.conf, welche wir über SSH oder direkt am Revolution Pi bearbeiten.

pi@RevPi ~/ $ sudo nano /etc/revpipyload/revpipyload.conf
[DEFAULT]
(...)

[PLCLSAVE]
plcslave = 0
(...)

Für die Aktivierung des Netzwerkzugriffs auf das Prozessabbild muss der Parameter plcslave auf 1 gesetzt werden!

Sehr wichtig ist auch die Datei /etc/revpipyload/aclplcslave.conf, über die die Zugriffsberechtigung auf das Prozessabbild gesteuert wird.
Jede Zeile der Datei hat folgende Syntax: IPADRESSE,RECHT
(mehrere dieser Berechtigungen werden durch eine Leerstelle getrennt)

  • IPADRESSE
    Einzelne IP-Adresse oder mit Platzhalter definierte Gruppen:
    192.168.178.10 -> Nur der eine Rechner
    192.168.178.* -> Alle Rechner, bei denen die IP mit 192.168.178. beginnt
  • RECHT
    0 = Nur lesen
    1 = Lesen und schreiben

Beispiel:

# PLC-SLAVE Access Control List (acl)
# One entry per Line IPADRESS,LEVEL
#
192.168.178.*,0
192.168.178.10,1

Alle Rechner im Netz 192.168.178.xxx haben lesenden Zugriff, der Rechner mit IP 192.168.178.10 hat lesenden und schreibenden Zugriff.

Nach der Änderung muss die Datei gespeichert und der Dienst neu gestartet werden:

pi@RevPi ~/ $ sudo systemctl restart revpipyload

Alle weiteren Parameter sind HIER aufgeführt.

Raspberry Pi vorbereiten

Als erstes müssen wir das RevPiModIO2 Modul auf dem Raspberry Pi installieren. Dies können wir wie hier beschrieben oder über pip3 erledigen.

pi@raspberrypi:~ $ sudo pip3 install revpimodio2

Den ersten Test können wir nun vom Raspberry Pi vornehmen. Zu beachten ist, dass kein anderes Steuerungsprogramm auf dem Revolution Pi läuft, da wir den exklusiven Modus verwenden!
Hinweis: Die IP-Adresse muss natürlich auf euren Revolution Pi angepasst werden!!!

pi@raspberrypi:~ $ python3
Python 3.5.3 (default, Jan 19 2017, 14:11:04)                                                                                                                                                                                                                                  
[GCC 6.3.0 20170124] on linux                                                                                                                                                                                                                                                  
Type "help", "copyright", "credits" or "license" for more information.                                                                                                                                                                                                         
>>> import revpimodio2                                                                                                                                                                                                                              
>>> rpi = revpimodio2.RevPiNetIO("192.168.50.36", autorefresh=True)                                                                                                                                                                                                
>>> rpi.core.temperature
49                                                                                                                                                                                                                                                                             
>>> rpi.io.inputbyte1.value
0                                                                                                                                                                                                                                                                              
>>> rpi.disconnect()                                                                                                                                                                                                                                                           
>>> exit()

Sollte die Ausgabe so aussehen, ist der Test erfolgreich!

Raspberry Pi programmieren

Mit dem Raspberry Pi wollen wir nun Daten in die INPUTS des virtuellen Devices schreiben. Damit dies möglich ist (in Inputs schreiben) verwenden wir RevPiNetIODriver(...).

# -*- coding: utf-8 -*-
"""Dieses Programm sendet den Status der GPIO Pins an den Revolution Pi."""
import revpimodio2
from RPi import GPIO


def cyclefunc(ct):
    """Zuklusfunktion, welche vom cycleloop() zyklisch aufgerufen wird."""
    # Den Wert vom GPIO Pin 13 in den IO pin13 schreiben
    rpi.io.pin13.value = GPIO.input(13)


def endfunc():
    """Setzt alle Werte des virtuellen Device auf 0/False bei Programmende."""
    rpi.setdefaultvalues()


# Setup GPIO on RaspberryPi
GPIO.setmode(GPIO.BCM)
GPIO.setup(13, GPIO.IN)

# Setup RevPiModIODriver() für virtuelles Device 'virtrpi'
rpi = revpimodio2.RevPiNetIODriver(
    "192.168.50.36", "virtrpi", autorefresh=True
)

# Auf das Bit 0 des "inputbyte1" von unserem virtuellen Device registrieren wir
# einen "Eingang" mit dem namen "pin13".
# Da wir ein Treiber sind (RevPiNetIODriver) können wir in Eingänge schreiben!
rpi.io.inputbyte1.replace_io("pin13", "?", bit=0)

# Programm sauber beenden, wenn SIGINT oder SIGTERM gesendet wird
rpi.handlesignalend(endfunc)

# Bei einem Kommunikationsfehler das virtuelle Device auf 0 setzen!
rpi.net_setdefaultvalues()

# Zyklische Verarbeitung starten
print("Starte cycleloop()")
rpi.cycleloop(cyclefunc)

# Nach Beenden des cycleloop vom Revolution Pi trennen
rpi.disconnect()

# GPIO aufräumen
GPIO.cleanup()

Dieses Programm erzeugt eine Instanz von RevPiNetIODriver(...). Als Übergabeparameter geben wir die IP-Adresse des Revolution Pi und den Namen des virtuellen Devices an, welches unsere Treiberinstanz verwenden soll.

Da wir die GPIO Werte als BITs speichern wollen, können wir auf unserem inputbyte1 bis zu 8 BIT-IOs registrieren. Über rpi.io.inputbyte1.replace_io("pin13", "?", bit=0) registrieren wir einen neuen BIT-IO mit dem Namen pin13, welchen wir dann direkt über rpi.io.pin13 ansprechen können.

Da wir ein Treiber sind, können wir in Inputs schreiben und Outputs nur lesen!

WICHTIG: Mit rpi.net_setdefaultvalues() weisen wir den Revolution Pi an, alle Eingänge das virtuellen Device auf Standardwerte (normalerweise 0) zu setzen, sollte die Verbindung unterbrochen werden! Dies ist sehr wichtig, da im Falle eines Verbindungsabbruch sonst die gesetzten Eingänge ihren Status beibehalten würden!

Danach rufen wir rpi.cycleloop(cyclefunc) auf und das RevPiModIO führt zyklisch (Standard alle 50 Millisekunden) die Funktion cyclefunc(ct) aus. Diese Funktion ließt den aktuellen Status True / False des GPIO Pin 13 aus und schreibt den Wert in unseren Input pin13.

Auf dem Revolution Pi ist dieser Wert nun verfügbar!

Optional: Steuerungsprogramm auf dem Revolution Pi

Auf dem Revolution Pi führen wir folgendes Programm aus.

# -*- coding: utf-8 -*-
"""Beispielprogramm um auf Daten des Raspberry Pi zuzugreifen."""
import revpimodio2


def evt_raspberry(ioname, iovalue):
    """Eventfunktion fuer Datenaenderung des Raspberry Pi."""
    # Eine Zeile mit aktuellem Wert ausgeben
    print("Input: {} - Value: {}".format(ioname, iovalue))


# RevPiModIO Instanz erzeugen
rpi = revpimodio2.RevPiModIO(autorefresh=True)

# Auf das Bit 0 des "inputbyte1" von unserem virtuellen Device registrieren wir
# einen "Eingang" mit dem namen "pin13".
rpi.io.inputbyte1.replace_io("pin13", "?", bit=0)

# Für den neuen Eingang registrieren wir ein Event.
rpi.io.pin13.reg_event(evt_raspberry)

# Programm sauber beenden, wenn SIGINT oder SIGTERM gesendet wird
rpi.handlesignalend()

# Eventüberwachung starten und auf Events reagieren
print("mainloop()")
rpi.mainloop()

Wir erstellen auch hier einen neuen Eingang pin13 auf dem Bit 0 des Eingangs inputbyte1.

Im Anschluss registrieren wir mit rpi.io.pin13.reg_event(evt_raspberry) ein Event, welches bei Wertänderung die Funktion evt_raspberry(ioname, iovalue) ausführt. Die Funktion schreibt dann einfach den IO Namen und aktuellen Wert in die Ausgabe.

mainloop()
Input: pin13 - Value: True
Input: pin13 - Value: False
Input: pin13 - Value: True

5 Antworten auf „GPIOs von einem RaspberryPi auf RevolutionPi“

  1. Hallo und vielen Dank für den super Artikel!
    Ich habe genau nach so etwas gesucht, weil ich mit einem RevPi und logiCAD3 eine Steuerung realisiere und jetzt einen RasPi für die Darstellung von Zustandswerten auf einem 10″Display verwenden will (mit python und Tkinter). Dafür muss ich die Zustandswerte vom RevPi auf den RasPi bekommen, irgendwie. Und die obige Lösung sieht deutlich einfacher aus als bspw. über RS485 mit Modbus RTU oder ähnlichem.

    Zu der Umsetzung der Kommunikation noch vier Fragen (ich bin neu und unbewandert auf dem ganzen serielle-Kommunikations- und Prozessabbild-Gebiet ;-)) :

    1. Kann ich sicher sein, dass ich durch das Schreiben auf das virtuelle Device meine Steuerung nicht gefährde? Also wenn ich z.B. statt einem BYTE einen STRING an einen Input schicke, hätte ich die Befürchtung, dass dadurch meine Steuerung, die einen Motor-FU und andere Geräte anspricht und stabil laufen muss, evtl. instabil wird. Reicht hier dann eine Fehlerabfrage in meinem Steuerungsprogramm in logiCAD?

    2. Wenn ich RevPi und RasPi mit einem Netzwerkkabel verbinde, fehlt mir dann ja eine debug-Möglichkeit, um die Variablen auf dem RevPi in logiCAD zu beobachten. Die RJ45-Buchse am RevPi ist dann ja belegt. Gibt es hier eine Möglichkeit, trotzdem noch die Variablen in logiCAD von meinem Laptop aus anzusehen?

    3. Kann ich auf alle logiCAD-Variablen vom RasPi aus zugreifen mit rpi.core.varX? Wobei varX meine Variable ist und in logiCAD erstellt wurde. Oder gehts das nur mit EXTERNAL-Variablen oder ähnlichem?

    4. Kann ich vom RasPi aus an die Inputs des virtuellen Devices auch längere Datentypen wie INTs oder sogar STRINGs schicken? Wie ginge das?

    Entschuldige, wenn die Fragen so einfach sind, dass ich die Antworten darauf auch woanders finden könnte (ich hab gesucht, nur fand ich nichts…).

    1. Hi Frido!

      1) Das RevPiModIO, bzw. RevPiNetIO hält sich direkt an die piCtory Konfiguration. Daher kannst du über RevPiModIO keinen String in eine Bool Variable schreiben. Python würde dir eine Fehlermeldung ausgeben. Auch wenn du über .replace_io(„1024s“) 1024 Bytes versuchen würdest auf einem Device zu registrieren, gäbe dir RevPiModIO einen Fehler, da die Länge nicht passt. Wir haben an der Stelle diverse Prüfungen eingebaut.

      2) Du könntest einen Switch benutzen, um Laptop, RevPi und Raspi in ein Netz aufzunehmen. Dann könntest du am Laptop logiCAD debuggen und am RevPi dein Python-Programm.

      3) NEIN 🙁 Leide kannst du nicht auf interne Variablen von logiCAD zugreifen. Diese müsstest du auf ein virtuelles Device spiegeln und dann dieses virtuelle Device im Raspi mit RevPiNetIO abfragen. Mit .replace_io(…) kannst du die Bytes in diverse Datentypen umwandeln.
      Siehe: https://revpimodio.org/revolutionsumbau-freestyle-panelpc/

      4) Du konfigurierst in logiCAD deine Datentypen über die Bytes des virtuellen Devices. Danach kannst du per .replace_io(…) diese Bytes im Pythonprogramm wieder in deine Datentypen umwandeln. (Dieses Beispiel funktioniert andersherum, aber zeigt wie es geht) https://revpimodio.org/startseite/ueber-revpimodiodriver/

  2. Hallo und vielen Dank für diesen Artikel, das ist genau das, wonach ich gesucht habe! Ich will mit einem RevPi Core eine Steuerung realisieren und mit einem RasPi und einem Display einige Zustandsgrößen der Steuerung anzeigen lassen.

    Ich habe alle Schritte wie oben befolgt, bekomme aber leider eine Fehlermeldung auf dem RasPi, wenn ich mit python3 „>>> rpi = revpimodio2.RevPiNetIO(„192.168.50.36″, autorefresh=True)“ eingebe (die IP-Adresse habe ich angepasst):
    „FileNotFoundError: can not connect to revpi slave“

    Ich kann den RevPi, der eine statische IP hat, vom RasPi aus erfolgreich anpingen. Auch andersrum vom RevPi aus kann ich den RasPi anpingen.

    Ich habe einen RevPi Core 3 (Jessie) und einen Raspberry 3B+ (Stretch), auf dem ich ebenfalls eine statische IP-Adresse eingerichtet habe. Auf dem RevPi Core habe ich in einem weiteren Versuch über das Web-Interface „Enable/Disable Modbus Slave“ auf „enabled“ gesetzt, aber ohne Erfolg.

    Was könnte hier der Fehler sein? Warum kann ich nicht vom RasPi auf die Prozessdaten des RevPis zugreifen? Ich bin für Tipps sehr dankbar!

    Grüße

    1. An dieser Stelle muss ich mich entschuldigen, da dieser Blogeintrag noch eine alte Konfiguration der ACL (Zugriffskontrolle) zeigt! Bitte hier im Punkt „Parameter in PLCSLAVE Sektion“ schauen: https://revpimodio.org/revpipyplc/revpipyload/

      Oder unser grafisches Tool verwenden, wobei dort aus Sicherheitsgründen natürlich auch eine ACL angelegt werden muss: https://revpimodio.org/revpipyplc/revpipycontrol/

      Unbedingt die Logdatei „/var/log/revpipyload“ auswerten, da dort abgelehnte Verbindungen protokolliert werden und auch der Grund!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.