Phoenix Modbusserver

Justuz

Level-1
Beiträge
12
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo nochmal,

ich habe mal wieder ne klitzekleine frage zu nem Phoenix problem:
ich würde gerne die Prozessdaten aus meinem Programm per modbus server bereitstellen. Das wären einige Temperaturwerte, ein paar analoge Ein und Ausgangswerte und einige Boolesche Variabeln.

wie um alles in der Welt befülle ich das COM_ARR_W_0_7167 datenword mit diesen Daten ? soweit ich alles verstanden habe gibt es dieses eine word was übergeben wird (am anschluss MODBUS Data), das ist 16 bit lang irgendwie scheint mir das zu kurz für alle meine daten oder habe ich da einen denkfehler?

Vielen Dank schon mal
Justuz
 
Sprichst du evtl. vom MBTCPS_ARR_W_0_2004 beim FB "MODBUS_TCP_Server_V1_2x"?
Ansonsten ist COM_ARR_W_0_7167 ein Array aus 7168 Words.
Welche Lib hast du denn eingebunden?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich hab die Comunications library eingebunden.
wie kann ich denn dieses Array befüllen ? mal angenommen ich gebe jeder Variable ein wort zur verfügung (das ist bei binären ein/ausgängen evt. ein bischen überdimensioniert - aber egal).
Ich programmiere mit funktionsbausteinen.

vielen Dank schon mal
 
Schau mal hier, vielleicht hilft das.
 

Anhänge

  • PC_WORX_5_Modbus_TCP_Communication.rar
    3,6 MB · Aufrufe: 79
Vielen Dank, das ist so ziemlich genau das was ich gesucht habe, warum findet man solche dokumentationen auf euere Website eigentlich nicht ?

Ich werde das mal austesten und mich bestimmt noch mal zu der Thematik melden :)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Man findet sie. Ich suche z.B. immer erst nach dem ILC 350 ETH. Dann auf Downloads und ganz unten stehen Anwendungsbeispiele oder wenn die Kategorie neu ist "use_case", dann wurde es noch nicht geändert, ist ne Art Platzhalter. Dann lädst du dir das Setup runter, installierst es. Und dann gehst du in den Ordner, das was du willst und dort sind dann die PDF's in englisch und deutsch.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
32bit über Modbus

Hallo zusammen,

bin gerade auf diesen Beitrag gestoßen. Habe auf einer ILC130 den Modbus TCP Server (1_07) am Laufen, der auch erfolgreich eine Verbindung zum Client (IP-Symcon) aufgebaut hat.
Damit kann ich bereits Boolsche Variablen, Zahlen bis 65535 und Wörter (16bit) vom ILC130 mit der Ip-Symcon empfangen. Soweit, so gut...

Nun habe ich aber 32bit Gleitkommazahlen und DWORD's weiterzuleiten. Dazu müßte ich nach IEEE 754 umwandeln und zwei Wörter zusammenfügen.
Wie kann ich das in PCWORX realisieren. Hätte dazu jemand ggfs. ein Programmierbeispiel?

Gibt es da etwas fertiges? Oder muss man da ganz viele Bit schieben? :eek:

Danke und LG
Upuaut
 
Hallo,

also von Phoenix gibt es da leider nix. Deshalb habe ich mir mal zwei Bausteine geschrieben.

REAL_TO_IEEE754 sieht dann so aus:
Code:
REAL_TO_BUF_1(REQ:=xReq,BUF_FORMAT:=FALSE,BUF_OFFS:=DINT#0,BUF_CNT:=DINT#4,SRC:=IN,BUFFER:=aTmp);
IN := REAL_TO_BUF_1.SRC;
aTmp := REAL_TO_BUF_1.BUFFER;

IF IN <> rINLast THEN
    xReq := TRUE;
END_IF;

IF REAL_TO_BUF_1.DONE THEN
    xReq := FALSE;
END_IF;

dwTmp.B0 := aTmp[0];
dwTmp.B1 := aTmp[1];
dwTmp.B2 := aTmp[2];
dwTmp.B3 := aTmp[3];

OUT := dwTmp;

rINLast := IN;

Und IEEE754_TO_REAL sieht so aus:
Code:
BUF_TO_REAL_1(REQ:=xReq,BUF_FORMAT:=FALSE,BUF_OFFS:=DINT#0,BUF_CNT:=DINT#4,BUFFER:=aTmp,DST:=OUT);
aTmp := BUF_TO_REAL_1.BUFFER;
OUT:=BUF_TO_REAL_1.DST;

IF IN <> dwINLast THEN
    xReq := TRUE;
END_IF;

IF BUF_TO_REAL_1.DONE THEN
    xReq := FALSE;
END_IF;

aTmp[0] := IN.B0;
aTmp[1] := IN.B1;
aTmp[2] := IN.B2;
aTmp[3] := IN.B3;

dwINLast := IN;

Als Datentyp musst du dannoch diesen hier anlegen:
Code:
TYPE
    ARRAY_OF_BYTE_0_3 : ARRAY [0..3] OF BYTE;
END_TYPE

Den Rest siehe Anhang.
 

Anhänge

  • IEEE754.jpg
    IEEE754.jpg
    19,1 KB · Aufrufe: 35
  • IEEE754_2.jpg
    IEEE754_2.jpg
    60,4 KB · Aufrufe: 27
Hallo Mobi,

vielen Dank für Dein Beispiel. Die Umwandlung hat super funktioniert.
Die Umwandlung von IEEE754 zu Real zurück konnte ich natürlich nicht verwenden.
Dazu mußte erst mal ein PHP Script geschrieben werden. Nach einigen Unklarheiten mit der Reihenfolge der bits, funktioniert es nun.
Gerne veröffentliche ich das hier auch, wenn klar ist, dass es einwandfrei läuft.

LG
Upuaut
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo nochmal,

hier noch die passende Umwandlung von IEEE754 zurück in Float für PHP.
Bisher funktionert es zuverlässig, war aber letztendlich umsonst, da ich nun den Wert des Counterbausteines durch 1 teile, weil die Gleitkommazahl aus dem PCWORX Projekt zu ungenau ist. :confused: In PHP teile ich dann erst wieder... Siehe hier:

http://www.sps-forum.de/phoenix-contact/70224-gleitkommaberechnung-ilc130-mit-pcworx.html

Leider ist mir bis heute nicht klar, warum es Counterbausteine gibt (sowohl in der Solar Libary alsauch in der Building Automation Libary), die eigentlich nicht genau mit einem aufaddieren eines 0,002er Wertes klarkommen, aber die Anzahl der Impulse pro Einheit als Divisor in Float angegeben haben möchte. Man sollte diese Bausteine nur für ganze Zahlen schreiben.
Das ist ja auch nicht nur bei Phoenix so...
Das Fatale daran ist; Es fällt einem erst nach einer gewissen Zeit auf, weil der Counter am Anfang (kurz nach der Installation eines neuen Zählers) noch genau ist, später dann aber nur noch Blödsinn herauskommt.

Code:
<?
/********************************************************************************************/
/* Umrechnung von IEEE754 nach FLOAT siehe Wikipedia http://de.wikipedia.org/wiki/IEEE_754     */
/*                                                                                             */
/* Beispiel von Wikipedia mit IEE754 01000001100100110011001100110011 welche der Float Zahl */
/* 18,4 entpricht gerundet.                                                                    */
/* IEEE754 Rechner : http://www.h-schmidt.net/FloatConverter/IEEE754.html                     */
/* BIN -> DEC  DEC -> BIN http://acc6.its.brooklyn.cuny.edu/~gurwitz/core5/nav2tool.html     */
/*                                                                                             */                                                    */
/********************************************************************************************/

// Beginn Beispiel

//$input = "01000001100100110011001100110011"; // IEEE754 Zahl = 18,4
// 17972 -> 100011000110100
// 7096 ->  1101110111000

//echo "Erster Wert : " . bindec("100011000110100") . "<br>";    // Bit 0-15  Dezimal Zahl = 16787
//echo "Zweiter Wert: " . bindec("001101110111000") . "<br>";    // Bit 16-31 Dezimal Zahl = 13107
//ieee754ToFloat(17972 /*[Objekt #17972 existiert nicht]*/,7096) . "<br>";

// Ende Beispiel

SetValue(21829 /*[Steuerung Haus\Energie\Strom\Strom\Stromzähler]*/,ieee754ToFloat(GetValue(37365 /*[Steuerung Haus\Modbus\ModBus Adresse 1\Value]*/),GetValue(11651 /*[Steuerung Haus\Modbus\ModBus Adresse 0\Value]*/))/500);
SetValue(16749 /*[Steuerung Haus\Energie\Gas\Gas\Gaszähler]*/,ieee754ToFloat(GetValue(55831 /*[Steuerung Haus\Modbus\ModBus Adresse 5\Value]*/),GetValue(38100 /*[Steuerung Haus\Modbus\ModBus Adresse 4\Gaszähler]*/))/100);
SetValue(47637 /*[Steuerung Haus\Energie\Wasser\Wasser\Wasserzähler]*/,ieee754ToFloat(GetValue(30433 /*[Steuerung Haus\Modbus\ModBus Adresse 9\Value]*/),GetValue(54533 /*[Steuerung Haus\Modbus\ModBus Adresse 8\Wasserzähler]*/))/1000);



function ieee754ToFloat($Wert1,$Wert2) {

//echo "Wert 1 : " . $Wert1 . " Wert 2 : " . $Wert2 . "\n";

    $_32BIT_CONSTANT_BIAS_B = 127;

    // Workaround START
    // PHP lässt bei der Umwandlung von dec nach bin führende Nullen weg.
    // Da aber alle 32 Bits für das korrekte funktionieren des Algorithmus IEEE754 nach DEC wichtig sind
    // werden durch diese 2 Schleifen die fehlenden Nullen wieder hinzugefügt.

    $Wert1 = decbin($Wert1);

    if(strlen($Wert1) < 16) {
        while(strlen($Wert1) < 16) {
            $Wert1 = "0" . $Wert1;
        }
    }

    $BIT_0_15 = $Wert1;

    $Wert2 = decbin($Wert2);

    if(strlen($Wert2) < 16) {
        while(strlen($Wert2) < 16) {
            $Wert2 = "0" . $Wert2;
        }
    }

    $BIT_16_31 = $Wert2;

    // Workaround ENDE

   //echo "Wert 1 : " .     $BIT_0_15 . " Wert 2 : " .     $BIT_16_31 . "\n";

    $input =  $BIT_0_15 . $BIT_16_31;
    $mantisse = "1" . substr($BIT_0_15 . $BIT_16_31,9,31);
    //echo "Mantisse : " . $mantisse . "\n";
    $vorzeichen = substr($input,0,1);
    $bias = substr($input,1,8);
    $exponent = bindec($bias) - $_32BIT_CONSTANT_BIAS_B;
    $vorkommaStellen =  substr($mantisse,0,$exponent + 1);
    $nachKommastellen = "0" . substr($mantisse,$exponent + 1,strlen($mantisse));

    // Durchlaufe schrittweise den String $nachKommastellen im BINÄR-FORMAT
    // Hier werden Bitweise die 2er Potenzen addiert
    $sum = 0;
    for ($i = 0;$i < strlen($nachKommastellen);$i++) {
        // Lese Bit für Bit aus dem String $nachKommastellen
        $BIT = substr($nachKommastellen,$i,1);
        // Rechne bei jedem Durchlauf das aktuelle Bit mal 2 hoch -i  // Siehe Wikipedia
        // und rechne den Wert zur aktuellen Summe dazu
        $sum = $sum + $BIT * pow(2,-$i);
    }
    $floatWert = bindec($vorkommaStellen) . "," . substr($sum,2,strlen($sum));
    $vorzeichen = substr($BIT_0_15,0,1);

    if($vorzeichen == 1) {
        $floatWert = (-1) * $floatWert;
    }

    //Debugausgabe START
    /*
    echo "BIT 0 - 15: " . $BIT_0_15 . "\n";
    echo "BIT 16 - 31: " .$BIT_16_31 . "\n";
    echo "Vorzeichen: " . $vorzeichen . "\n";
    echo "Bias: BIN: " . $bias . " DEC: " . bindec($bias) . "\n";
    echo "Exponent:" . $exponent . "\n";
    echo "Vorkommastellen: BIN: " . $vorkommaStellen . " DEC: " . bindec($vorkommaStellen) . "\n";
    echo "Nachkommastellen: BIN: " . $nachKommastellen . " DEC: " . bindec($nachKommastellen) . "\n";
    echo "Nachkommastellen : " . $sum . "\n";
    echo "Ergebnis: " . $floatWert;
    */
    //Debugausgabe ENDE

    return $floatWert;

}
?>

Vielleicht kann ja jemand etwas damit anfangen.

Eine Frage hätte ich noch dazu; Wenn ich nun einen DWORD Wert über Modbus senden will, zerlege ich diesen ja auch wieder in zwei mal WORD, oder (siehe Beispiel)?
Danach bekomme ich aber keinen sinnvollen Werte wieder zusammengesetzt. Wie sende ich aber sonst eine 32bit große ganze Zahl über Modbus in PCWORX? Im Moment mache ich es über den IEEE754 Baustein von Mobi als umgewandelte Floatzahl (z.B. 7233842,0) und dann über mein Script.

DWORD2.jpg

LG
Upuaut
 
Vielleicht kann das die ILC 190 ETH 2TX besser. Die ist extra ausgelegt auf Gleitkomma-Arithmetik.
Aber das ist mir vor Jahren auch schon aufgefallen, das liegt halt daran wie die Zahl gespeichert wird.
 
Vielen Dank für die Funktionsbausteine zur IEEE754-Umwandlung Mobi.

Ich bin gerade auf ein anderes Problem gestoßen:
Und zwar möchte ich Messwerte per Modbus bereitstellen, das ein LabView Proramm einliest. Dieses Programm ließt gewissen Werte als "double" ( 64-bit) ein, sprich 4 Modbus Register (4 Word).

Ist es möglich ein LREAL in PC-Worx irgendwie in 4 Words zu zerlegen, damit ich sie bereitstellen kann?

Ich verwende eine ILC131 ETH.

Vielen Dank
 
Zurück
Oben