Hallo Zusammen,
das es mich selbst einiges an Nerven und Zeit gekostet hat zu verstehen, warum IPS bei mir keine Schreibbefehle schickt, es aber angeblich funktioniert, hier nochmal zusammen gefasst die Ursache der Problematik und die Lösung, welche bei mir läuft:
Problematik:
Die Modbus-RTU Instanz sended in der aktuellen IPS 3.4 (und auch 4.x) auf Funktionscode 10! (steht auch so in der Anleitung)
Früher wurde im Funktionscode 06 gesendet. Roberto zB verwendet noch diese ältere Version.
Die Modbus-Bridge von Zimmermann nimmt nur Befehle im 06 Format an.
Lösung die bei mir Läuft:
Grundlage für die Sende und Empfangscodes ist die Excel-Tabelle, welche man von Zimmermann erhählt.
Spalte B enthält dort die Dezimalen Modbus-Codes (zB 4x0100 --> 100 in der Instanz).
Ich habe mich entschieden, hier nur kurz die Vorgehensweise zu beschreiben, da meine gesamte Umsetzung sehr detailiert ist und den Rahmen hier sprengt. (Automatisierungsskripte, wechselnde Variablendarstellungen, etc pp).
Ich hänge ein ZIP File an, in dem befinden sich folgende Dateien:
- Modbus_CRC16.ips.php --> Diese Datei muss immer eingebunden sein, da sie den passenden CRC16 Code erzeugt.
- PTC_schreiben.ips.php --> Beispiel wie ich die PTCs bei mir setze (7 PTCs und für je 1 PTC ist eine Boolean Variable unter der Modbus Instanz vorhanden)
- Wert_schreiben.ips.php --> Diese Datei verwende ich zum Schreiben von Soll-Temperaturen, Luftautomatik und Intensiv-Lüftung. Ausgelöst wird dieses Skript bei Änderung der Bezugsvariable (Solltemperatur, etc pp)
- Schalten.ips.php --> Standard Skript um Variablen in der Webfront Schaltbar zu machen
- AbfrageIntervallSetzen.ips.php --> Verwende ich zum AbfrageIntervalle auf „0“ zu setzen und dann mit modifikation zur zyklischen Abfrage aller Modbus Module
Modbus.zip (2.69 KB)
Betriebsarten und Lüfterstufen schalte ich mit eigenen Skripten und Programmen, da ich dort auch berücksichtige, welche Modi zur Verfügung stehen und welche nicht.
Aber jetzt mal im Detail erklärt, wie geschrieben wird:
-
Unter jeder Modbus-Schreibe Instanz habe ich eine passende neue Variable hinzugefügt. zB Solltemperatur als Integer für die Solltemperaturen
1a) WriteAddress in der Schreibe Instanz hinterlegen
-
Die Solltemp Variable zB hat dann ein VariablenProfil wie im Bild zu sehen erhalten und die Eigene Aktion geht auf das Schalten Skript.
Wichtig hierbei ist, dass die Variable den Wert Übergibt, der benötigt wird!
-
Wird die Variable geändert, löst sie folgendes Skript aus:
<?
include_once("\Proxon\Modbus_CRC16.ips.php");
IPS_SemaphoreEnter("Critical_ModBus", 4000); //Dauer sollte größer als die Laufzeit des Abfrage Skriptes sein!
if ($_IPS['SENDER'] == "Variable") {
$myInstanceID = IPS_GetParent($_IPS['VARIABLE']);
$BusID = "10"; // ModBus ID 10
$WriteCode = "06"; // Funktionscode
$TargetID = IPS_GetProperty($myInstanceID , "WriteAddress"); // Zieladresse
$myValue = $_IPS['VALUE']; // Zu schreibender Wert!
$myMessage = sprintf( "%02s", dechex( $BusID )).$WriteCode.sprintf( "%04s", dechex( $TargetID )).sprintf( "%04s", dechex( $myValue ));
$mySendCode = $myMessage .modbus_crc($myMessage); // Nachricht + CRC = SendCode
SPRT_SendText(15732, pack('H*',$mySendCode)); // wird an den Modbus Serial Port geschickt
IPS_SemaphoreLeave("Critical_ModBus");
};
?>
Die Grundlage des Schreibens habe ich dann auch für die Spezielleren Schreib-Routinen wie zB PTC verwendet. Dort wird der Wert aber noch Berechnet.
- Damit sich das Schreiben nicht mit dem Lesen „beisst“ habe ich bei allen Modbus-Modulen das AbfrageIntervall auf „0“ gesetzt und frage statt dessen zyklisch per Skript ab (alle 15 Sekunden zur Zeit). Das ganze noch mit Semaphore umhüllt und es gibt keine Probleme:
Zum setzen aller Intervalle auf 0, einfach die auskommentierten IPS_ Befehle einkommentieren und den Modbus_RequestRead auskommentieren.
<?
$mytime = 0; // in ms
$myArray = IPS_GetInstanceListByModuleID("{CB197E50-273D-4535-8C91-BB35273E3CA5}");
IPS_SemaphoreEnter("Critical_ModBus", 1000);
foreach ($myArray as $myMod)
{
//IPS_SetProperty($myMod , "Poller", $mytime);
//IPS_ApplyChanges($myMod);
ModBus_RequestRead($myMod);
}
IPS_SemaphoreLeave("Critical_ModBus");
?>
Sodele,
nachdem ich den Text jetzt 2mal geschrieben habe, kann ich nicht mehr
Hoffe das hilft erstmal weiter.
Gruß
Maze