Modus RTU Codes senden?

Hallo zusammen,
ich habe Probleme dabei bestimmte Modbus RTU Codes über IP-Symcon zu senden.
Ich habe Relaisplatinen die sich per Modbus steuern lassen. Diese beinhalten 4 Inputs und 4 Relais die man schalten kann, davon möchte ich in insgesamt 4 Platinen in IP-Symcon einbinden. Ich habe die Funktion mit Modbus Poll geprüft, bekomme mit Symcon aber nicht die korrekten Codes über die Einstellmöglichkeiten in den Instanzen eingestellt.

Beispiel: Ich möchte Relais 1 schalten und Input 1 lesen. Die Adresse der Platine habe ich bereits auf 1 gesetzt. Die richtigen Befehle wären:

Relais 1 ein: 01 05 00 01 01 00 + CRC
Relais 1 aus: 01 05 00 01 00 00 + CRC
Input 1 lesen: 01 02 00 01 00 00 + CRC - Rückantwort Input 1 aus: 01 02 01 00 , Input 1 ein: 01 02 01 01

Wie bekomme ich das mit Symcon hin, was muss ich dazu einstellen? Wenn ich Read Discrete Inputs [Funktion 02] auswähle sendet Symcon: 01 02 00 00 00 01 B9 CA , also setzt die Software ein anderes Bit auf 1. Ebenso beim Relais schalten, da schaltet es mit „01 05 00 00 FF 00 8C 3A“ das Relais ein und mit „01 05 00 00 00 00 CD CA“ das Relais aus.
Das ist natürlich für die Platine nicht korrekt, mir würde es ja reichen, wenn ich einfach die genauen Codes einzelnd eintippen kann und diese dann gesendet werden. Besteht dazu die Möglichkeit, oder kann ich die Platinen mit Symcon garnicht nutzen?
Und gehe ich ansonsten richtig der Annahme, dass ich für jeden einzelnen Befehl eine Instanz erstellen und einstellen muss, weil pro Instanz immer genau 1 Befehl bearbeitet wird, oder kann ich auch mehrere Befehle in Folge senden und diese in Variablen speichern damit ich z.B. alle Inputs einer Platine auf einmal abfragen kann? (Danach ändert sich ja sogar die Adresse, dafür müsste ich dann ja ein extra „Modbus Gateway“ hinzufügen.

Gruß

Finde den Edit-Button nicht und wollte noch die Versionsinfo hinzufügen:

Plattform: Raspberry Pi 3 mit Raspbian
IPS: Version 4.3
Schnittstelle: /dev/ttyUSB0 , USB-Stick direkt im Pi (genügend Stromversorgung, da es mit Modbus Poll immer 1a geht)

Editieren wäre gut gewesen, kannst Du aber erst, wenn Du einiges an Beiträgen geschrieben hast.

Grundsätzlich mußt Du eine Modbusinstanze erstellen, Instanze -> Modbusdevice und dann darfst Du genauer werden :wink:
Ob Coil, Integer, Real … ob nur lesen oder auch schreiben.

Die übergeordnete Instanze ist ein Splitter (Modbus RTU) dessen Übergeordnete die serielle Schnittstelle.
Hast Du diese Instanzen nicht mußt Du sie, am Besten vorher, noch erstellen.

Gibt viele Beispiele hier, lohnt sich also die Suchfunktion zu testen.
Gruß Helmut

Das habe ich ja bereits getan. Ich habe eine Schnittstelle, einen Splitter (übergeordnete Instanz) und die eigentliche Instanz in der die „Funktion“ lesen/schreiben eingestellt werden kann. Problem ist aber wie gesagt, dass diese Funktion andere Codes sendet als ich benötige und ich trotz Adressänderung etc. nicht den korrekten Befehl rausbekomme.

Gibt es verschiedene „Modbus-Versionen“ in IPS, wo sich die Codes vielleicht leicht unterscheiden auf die man wechseln kann? Grundsätzlich stimmt die Adresse und der Funktionsaufruf ja, aber es setzt eben andere Bits als ich benötige. Wundert mich etwas, da ich mit „Modbus Poll“ quasi die genau gleichen Daten eintippe und ein anderer RTU Code hinten rauskommt. (siehe 1. Beitrag wo sich die Codes unterscheiden und welche ich benötige)

Gruß
JumpY

Screenshots wären gut.
Weil es gibt ja nicht nur die Gerät ID im Gateway, auch die Adresse des Registers in der Modus Instanz muss eingetragen werden.
Und die sieht aus, als wenn dort 0 bei dir steht.
Michael

Wenn Du Funktionscode 05 nutzen willst ist discrete Input falsch, dann mußt Du write single coil nehmen, siehe Beschreibung und hier.

Und ja, Michael liest Adresse 0 bei Dir, Du müßtest Adresse 1 eintragen, Modbus ADR 0 gibt es, zählt mit.

Edit: Verstehe erst jetzt wo das Problem scheinbar ist, Deine Relaisplatte nimmt einen anderen „Ein/AUS“ Befehl…
Bist Du Dir da sicher?
Modbus Poll Fu-Code 5, nimmt auch die Ein/Aus-Befehle wie IP-Symcon.
Teste mal mit ADR 1

Gruß Helmut

Okay ich versuche das ganze nochmal etwas strukurierter darzustellen. (Die Relaisschaltung hat sich quasi erledigt, aber ist hier nochmal aufgelistet. Wichtiger wäre das lesen der Inputs weiter unten, wie bekomme ich jeden Input in eine bestimmte Variable gesetzt, damit ich das als Status nehmen kann? Das sind Endschalter und Schalter z.B., ich möchte mit diesen Inputs etwas überwachen oder bei Betätigung eine Aktion ausführen)

Meine Testplatine hier hat die Modbus ID 1. Wenn ich mit Modbus Poll auf die Platine gehe, benötige ich folgende Befehle um die 4 Relais auf der Platine zu schalten: (Befehl: Write Single Coil, Funktion 05)

Relais1 ein: 01 05 00 00 01 00
Relais2 aus: 01 05 00 00 00 00

Relais2 ein: 01 05 00 01 01 00
Relais2 aus: 01 05 00 01 00 00

Relais3 ein: 01 05 00 02 01 00
Relais3 aus: 01 05 00 02 00 00

Relais4 ein: 01 05 00 03 01 00
Relais4 aus: 01 05 00 03 00 00

Also gliedert sich mein Befehl wie folgt auf:

Slave ID Function Adresse Daten Ein/Aus (0100 / 0000)
Relais1 Ein: 01 05 0000 0100
Relais1 Aus: 01 05 0000 0000
Relais1 Ein: (Mögl. 2) 01 05 0000 FF00

Möglichkeit 2 habe ich gerade erst festgestellt, das Modbus Poll das über das „Einstellfenster“ mit Dropdownmenu so sendet, ich hatte vorher den normalen „Relais1 Ein“-Befehl gesendet, so wie er in meiner Dokumentation stand. (Habe bei Modbus Poll im Testcenter einfach die RTU-Codes einzelnd gesendet zum testen)
Die Schreibbefehle funktionieren jetzt also auch so in IPS, IPS nutzt ebenfalls die Schreibweise der Möglichkeit 2, also Aus = 0000, Ein = FF00.

Nun zum lesen. Meine Dokumentation sagt mir folgendes:

Sendebefehl Rückantwort „Aus“ Rückantwort „Ein“
Input 1 lesen: 01 02 00 00 00 00 01 02 00 00 01 02 00 01
Input 2 lesen: 01 02 00 01 00 00 01 02 01 00 01 02 01 01
Input 3 lesen: 01 02 00 02 00 00 01 02 02 00 01 02 02 01
Input 4 lesen: 01 02 00 03 00 00 01 02 03 00 01 02 03 01

Damit bekomme ich aber in Modbus-Poll auch nicht die richtigen Werte.
Ich sende bei Modbus-Poll folgendes: (Slave 1, Adresse 0, Funktion 02, Quantity 4)

01 02 00 00 00 04

Dann bekomme ich direkt in der Tabelle die 4 Inputs angezeigt, mit den entsprechenden Werten. Die Rückantwort ist dann:

Input 1 beschaltet: 01 02 01 01
Input 1 und 2 beschaltet: 01 02 01 03
Input 1 und 3 beschaltet: 01 02 01 05
Input 1 und 4 beschaltet: 01 02 01 09
Input 1 und 2 und 3 beschaltet: 01 02 01 07

Das bekomme ich mit IPS jetzt garnichtmehr abgebildet, was soll ich dazu einstellen bzw. wie soll ich die Variablen da rausfiltern, oder muss ich für jede Variable einen einzelnen Befehl rausfinden, dann müsste ich mich da nochmal drangeben das rauszufinden. Es ist aber ja klar zu sehen, dass das in „Bit-Zählung“ funktioniert, also „0-15“ im Prinzip. Habs jetzt nicht durchgetestet auf die Schnelle, aber so müsste ja bei allen 4 beschaltet z.B. der Wert 15 sein. (Also 4bits auf 1)

Ich hoffe das ist jetzt irgendwie verständlich erklärt, was mein Problem darstellt. Wie bekomme ich genau so etwas wie hier gezeigt (Inputs) in IPS abgebildet.

Gruß
JumpY

Nee, dann müßte IP-Symcon Funktion 15 können, dann würdest Du auch noch die Rückantwort dekodieren müssen.
Edit ; Quatsch, 15 ist zum Schreiben, ich habe irgendwo gelesen ein zukünftige Version von IP-Symcon soll das können was Du willst.

Du mußt einzeln abfragen, jeden Eingang einzeln mit einer Instanz. zB so
Gruß Helmut

02.jpg

Das wäre natürlich sehr schlecht, dann könnte ich die Software dafür nicht nutzen. Ich denke das Problem ist nun verständlich beschrieben, nun wieder meine Tests dazu. (Problem: Die „China“-Platine hat eine unzureichende Dokumentation und die Befehle die laut Beschreibung der Platine funktionieren sollten, funktionieren nicht. Ich bekomme bei „Einzelabfrage“ immer die gleiche Rückantwort, bringt mir also nichts. Der Code zur „Mehrfachauslesung“ von allen 4 Zuständen auf einmal ist der einzige der bei mir überhaupt etwas liefert mit Modbus Poll, deswegen ist das der einzige Weg den ich nutzen könnte…)

Wenn ich nach deiner Einstellung auf dem Screenshot sende (vorher schon versucht), sendet IPS folgendes:

01 02 00 00 00 01

Daraufhin bekomme ich den Rückwert: „01 02 01 01 60 48“. Den gleichen Rückwert bekomme ich aber auch wenn ich am Ende eine 0 sende, eine 2, oder ähnliches und egal wie der Zustand ist. Ebenfalls bekomme ich die Rückmeldung, wenn ich die Leseadresse in IPS auf 1,2,3,4 setze. Das ist quasi eine Art „Fehlermeldung“ des Moduls, damit kann ich die Inputs nicht abfragen. Gleiches Bild auch in Modbus Poll.

Zusätzlich fällt mir auf, dass die debug Anzeige der Schnittstelle in IPS ständig etwas als Received anzeigt, auch wenn IPS garnichts sendet. Wenn ich den Traffic in Modbus Poll mitlese, bekomme ich nie eine Nachricht angezeigt wenn ich nichts sende. Wie kommt IPS daran dass zu empfangen, wenn ich nichts sende? Da ich im Terminal etc. nichts sehe, gehe ich nicht davon aus, dass die Platine diesen Befehl von sich aus sendet. (Siehe Screenshot…)

Ich habe auch relativ häufig Verbindungsabbrüche der Schnittstelle, die sich dann neuverbinden muss, das habe ich mit Modbus Poll z.B. noch nie gehabt, das wundert mich irgendwie…

Aber daran liegt es alles nicht, ich muss es irgendwie hinbekommen den Befehl: " 01 02 00 00 00 04" zu senden und den Rückgabewert zu „selektieren“. Ist es auf keinem Wege möglich die „Auswahl“ über die Instanz zu umgehen und den Code selber zu senden, oder komme ich irgendwie an das „Modbus-Modul“ in IPS dran, um in dem Quellcode davon die „Sendung“ zu verändern. Wenn das irgendwie offener Code wäre, würde ich mich da auch mal reinlesen eine solche Funktion zu implementieren. (Vielleicht für die Zukunft ja interessant, auch wenn ich irgendwo hier gelesen habe, dass die Möglichkeit RTU Codes direkt in HEX zu definieren, eigentlich mal eingebaut werden sollte).

Ansonsten: Muss ich den Weg jetzt echt irgendwie über ein Pythonscript gehen, welches im Modbus schreibt, mir vermutlich die Schnittstelle blockiert, die Inputs ließt, irgendwo Variablen ablegt, die ich dann mit IPS wiederrum auf dem Pi auslese? Das wäre ein sehr steiniger Weg, den ich gerne umgehen würde…

Gruß
JumpY

Wieso kannst Du entscheiden was Du sendest?
Wenn Du das Lesen machst wie gepostet, dann steht in der Boolvariable der Zustand, stimmt er denn?
Und wenn Du den Lesezyklus kleiner stellst hast Du auch keine Abbrüche mehr, schätze ich.
Gruß Helmut

Wie gesagt, wenn ich die Codes zum Auslesen, die im Datenblatt stehen sende, bekomme ich immer den identischen Rückwert. Egal ob geschaltet oder nicht, also ist die Variable auch dadurch falsch gesetzt.
Die Dokumentation von der China-Platine ist halt auch schlecht, veraltet und unvollständig. Der Befehl mit allen 4 war der einzige der bislang funktioniert hat und den kann ich mit IPS ja nicht einstellen…

Also, meine Einzelbefehle sind falsch:
Ich sende: 01 02 00 00 00 00 bekomme zurück: 01 02 01 01 60 48
Ich sende: 01 02 00 01 00 00 bekomme zurück: 01 02 01 01 60 48

Ich bekomme also immer die gleiche Antwort, egal bei welcher Einzelabfrage. Ich bekomme auch die gleiche Antwort, wenn der Eingang beschaltet ist, funktioniert also so nicht.

Ich müsste es irgendwie hinbekommen, die letzte „Ziffer“ zu ändern. Also damit ich den Befehl genau so senden kann, das ist der einzige der funktioniert:
01 02 00 00 00 04

Außer es hat vielleicht noch einer ne Idee, was für ein Befehl sonst funktionieren könnte, aber das bezweifel ich, habe eigentlich schon alles durch… Ist halt warscheinlich nicht das „Standartprotokoll“…

Hast Du mal Lust mir das Teil per Post zu schicken? Link vorab?
Gruß Helmut

Das ist leider aktuell das einzige der Teile die ich Verfügbar habe, hätte ich mehrere gerne. Ich habe aber mit Modbus Poll schon etliche Durchläuft mit etlichen Registern gemacht, ich kam wirklich nur auf dem einen Weg an die Daten. Ansonsten muss ich es halt wirklich über ein zusätzliches Script machen…

Ist nicht zufällig ASCII Code oder das Modul lässt ASCII Code oder AT-Befehle zu? Damit könntest Du dann ja auch was werden, allerdings mit Scripten
Gruß Helmut

Puh, da bin ich überfragt, habe ich aber bislang noch nirgends einen Hinweis zu gelesen. Ich werde morgen vielleicht nochmal mehrere Codes durchfahren, aber ich erwarte nicht all zu viel.

Das ist quasi alles was ich zu der Platine habe, die Codes die ich hier gepostet habe sind aus einem anderen Forum (FHEM), wo jemand mit viel Kleinarbeit die Codes rausgefunden hat. Die Codes in der Ebayauktion funktionieren fast alle nicht & wie ich ja festgestellt habe, funktionieren die Codes aus dem anderen Forum bei mir auch nicht alle. Schade, mit Modbus-Poll funktioniert es so schön und wenn ich irgendwo in einer Libary oder sonstwo eine Änderung machen könnte um den richtigen Befehl zu setzen, wäre alles so einfach gelöst…

Es geht um die Platine hier…

Ich muss nochmal nachhaken:
Ist es mit dem PHP-Code oder ähnlichem nicht möglich, den Rückwert einer Modbuskommunikation genau zu bekommen? Beispiel: Ich sende „01 02 00 00 00 01 B9 CA“ und erhalte z.B. „01 02 01 01 60 48“, oder „01 02 01 03 E1 89“. Davon möchte ich das letzte Datenpaket auswerten, welche Zahl ich da bekomme.

00 - Alle Eingänge Aus
01 - Eingang 1 AN, Rest Aus
02 - Eingang 2 AN, Rest Aus
03 - Eingang 1+2 AN, Rest Aus
… usw.

Kann ich das nicht irgendwie selektieren mit IP-Symcon?

Zusätzlich habe ich wirklich immer weiter das Problem, dass die Schnittstelle „abstürzt“. Ich kann den Fehler nicht finden, mit Modbus Poll auf Windows funktioniert alles 1a, bei IPS und dem Pi3 verliere ich die Verbindung alle paar Sekunden. Ich weiß noch nicht ob es mit dem Stick zusammenhängt, IPS, oder was genau. Kennt jemand Probleme mit dem CH431-Chipsatz Sticks die bei Ebay und Co gängig sind?

Das versuche ich noch in den Griff zu bekommen, aber wenn IPS die Werte eh nicht auswerten kann ist das alles Mist. Ich versuche in PHP auch Readbefehle zu machen, bekomme ich nicht hin, weil die auch garnicht dokumentiert sind. Kann ich mit dem PHP-Code nicht einen Coil o.ä. auslesen, nur über dieses Einstellfenster? Schreiben kann ich ja ganz einfach über die PHP Befehle… (Ich dachte an etwas wie $variable = ModBus_ReadInputCoil($id, $coil) z.B…)

Gruß
JumpY

Die Edit-Funktion habe ich leider noch immer nicht freigeschaltet, kurzer Nachtrag:

Ich habe jetzt sämliche Register, Coils, whatever mit Modbus-Poll durchtestet und finde nirgends anders den Wert hinterlegt. Somit bleibt mir wirklich nur die Möglichkeit mit „ReadInputCoils“ (Funktion 02), die digitalen Inputs auf meiner Platine auszulesen. Ich habe in IPS nun alles mögliche durchgeklickt und habe es nicht hinbekommen das so zu lesen wie ich es mir vorgestellt habe.

Ich würde ja auch den Weg darüber gehen, dass ich die „Antwort“ auf eine Leseanfrage in HEX oder ähnlichem bekomme (genau der Befehl der im Debug-Fenster angezeigt wird). Wenn ich die in mein PHP-Script in IPS bekommen würde, könnte ich mir daraus meinen Status der Inputs „errechnen“. Gibt es da einfach garnichts? Hat sonst jemand eine Idee, wie ich es irgendwie lösen könnte, wenn dann eben auch nicht sonderlich elegant.

Mein Angebot steht
Gruß Helmut

Hallo Helmut,
nochmal Danke für dein Angebot und deine tolle Hilfe bis hier hin. Ich habe gestern Abend mit Spoosie im IRC gesprochen und er hat mir eine Lösung dazu gezeigt und für mich eingestellt.
Du hattest soweit Recht, das lässt sich nicht über das ModBus Modul als solches bedienen, da gab es keine Möglichkeit. Mein jetziges Script (welches auch funktioniert), sendet die Nachricht selber auf den Datenbus, erhält die Antwort in einer RegisterVariable und diese wird dann in einem PHP-Script ausgewertet.

Falls mal jemand auf dieses Thema stößt und damit etwas anfangen kann, hier ein kurzes Codebeispiel dazu:

<?
	$scriptName = "Readinputs";
	
	// Variablen definieren: $varID + Platinennummer + Inputnummer
	
	/*   [Platine 1 - Tor 1+2]   */
	$varID1_1 = 57410 /*[Platine 1 - Tor 1+2\Input 1 - Tor 1 geschlossen]*/;
	$varID1_2 = 29667 /*[Platine 1 - Tor 1+2\Input 2 - Tor 2 geschlossen]*/;
	$varID1_3 = 44347 /*[Platine 1 - Tor 1+2\Input 3 - unbelegt]*/;
	$varID1_4 = 17780 /*[Platine 1 - Tor 1+2\Input 4 - unbelegt]*/;
		
	// Serialport definieren
	$portID = 34368 /*[Serial Port (ModBus Gateway #15656)]*/;
	
	// Auslöser selektieren:
	// TimerEvent = Zyklustimer 
	// RegisterVariable = Empfangener Datenstream auf dem Bus
	if ($_IPS["SENDER"] == "TimerEvent")
	{
		// Auslesen Platine 1
		SPRT_SendText($portID,"\x01\x02\x00\x00\x00\x01\xB9\xCA"); //01 02 00 00 00 01 B9 CA		
	}
	else if ($_IPS["SENDER"] == "RegisterVariable")
	{	
		// Adresse & Wert umwandeln
		$address = hexdec(bin2hex(substr($_IPS["VALUE"],0,1)));
		$value = hexdec(bin2hex(substr($_IPS["VALUE"],3,1)));
		// Lognachricht mit selektierter Adresse und Wert
		IPS_LogMessage($scriptName,"Antwort=".bin2hex($_IPS["VALUE"])."   Address = ".$address." ; Value = ".$value);
	}	
?>

So hat man dann in der Variable $address die Adresse der Platine gespeichert (nur notwendig wenn man mehrere dieser Platinen abfragen möchte und danach selektieren), und in $value den Wert 01, 02, 03, etc. den ich benötige. So kann man einfach die ganze Rückantwort abfangen und damit arbeiten wie man möchte. Finde ich eine Klasse Lösung und ich bin froh, IPS für meine Aufgabe einsetzen zu können.

Zeigt sich mal wieder, es gibt hier immer eine Lösung :wink:
Gruß Helmut