Pokey55E mit IPSymcon

Ich würde gerne den Counter von Port41-43 auslesen.
Für die Abfrage eines Ports nehme ich

modbus_send($RegisterVariable_ID, CounterRead41);

und habe die Ports vorher so definiert

define('CounterRead41','C1 41 00 00 00 06 01 03 00 6F 00 01');
define('CounterRead42','C1 42 00 00 00 06 01 03 00 71 00 01');
define('CounterRead43','C1 43 00 00 00 06 01 03 00 73 00 01');

Klappt leider nicht. Counter wird mir immer mit 0 angezeigt
und folgende Fehlermeldung kommt siehe Bild.

Die betreffende Code Zeilen

    if($arr_modbus_receive[0] == "C1") { // C1 Modbus answer for counter read
        $hex = $arr_modbus_receive[11].$arr_modbus_receive[12].$arr_modbus_receive[9].$arr_modbus_receive[10];
        $dec = hexdec($hex);
        $max = pow(2, 4 * (strlen($hex) + (strlen($hex) % 2)));
        $_dec = $max - $dec;
        if($dec > $_dec) {
           $value = -$_dec;
        } else {
           $value = $dec;
        }
        switch ($arr_modbus_receive[1]) {
            case "41":
                echo "Counter Read Pin41 = ".$value."
";
                break;
            case "42":
            	 echo "Counter Read Pin42 = ".$value."
";
                break;
            case "43":
           	 	 echo "Counter Read Pin43 = ".$value."
";
                break;
        }
    }

Jemand eine Idee

Hallo Marcus,

ich glaube der Fehler liegt bei den Hex-Strings. Richtig müsste es lauten:


define('CounterRead41','C1 41 00 00 00 06 01 03 03 70 00 02'); 
define('CounterRead42','C1 42 00 00 00 06 01 03 03 72 00 02'); 
define('CounterRead43','C1 43 00 00 00 06 01 03 03 74 00 02');  

Laut Pokeys Doku starten die Digital Counter Register bei 800 für Pin 1, 802 für Pin 2, … -> 880 für Pin 41, 882 für Pin 42, 884 für Pin 43.

Beispiel Pin 41
880 => 03 70 Hex und Du musst zwei Register lesen => 00 02

define(‚CounterRead41‘,‚C1 41 00 00 00 06 01 03 03 70 00 02‘);

P.S. Ich hatte in meinen Codebeispielen bei den Countern einen Fehler.
Ist jetzt korrigiert.

Vielen Dank,
ich hatte mir damit beholfen, die Eingänge auf 1 2 und 5 zu legen:D
I/O´s sind ja genug da und Not macht erfinderisch.
Wärest Du so nett und würdest mir an einer Hex Zeile von Dir erklären,
was die einzelnen Bits bedeuten. Ich find da im Moment einfach keinen Draht dazu.
Ich würde es aber gerne verstehen.

___________________?–?--?–?--?–?--?–?--?–?--?–?
define(‚DigitalRead01‘,‚D1 01 00 00 00 06 01 01 00 00 00 01‘);

Manual:
Reading of inputs

  • byte 2: 0x30
  • byte 3: pin ID (0-54)
  • byte 4-6: 0
  • byte 7: request ID

Returned packet:

  • byte 2: 0x30
  • byte 3: 0 - OK, 1+ error ID
  • byte 4: input value
  • byte 5-6: 0
  • byte 7: request ID

Hier steht was von 7 byte, bei dir zähle ich aber 12 :confused:
Wäre schön wenn du da Licht in mein Dunkel bringst.

Dann könnte ich vielleicht auch mein LCD Problem selber lösen.

Hallo Marcus,

kein Problem! Die HEX Sequenz ist eine Modbus Sequenzfolge, welche einfach Byte für Byte an Pokey gesendet wird. Die Erklärung der Sequenz findest Du auch als Comments im PHP Code von Post#7.

D1 01 00 00 00 06 01 01 00 00 00 01

Startpunkt ist hier: Modbus

Die ersten zwei Bytes „D1 01“ sind die Transaktionsbytes. Die kannst Du willkürlich wählen. In der „Antwort“ vom Modbus Device findest Du genau diese beiden Bytes wieder. Damit kannst Du also eine Zuordnung Requeststring zu Responsestring machen.

Byte 3,4 „00 00“ ist das Protokollkennzeichen und per Definition immer 00 00.

Byte 5,6 „00 06“ gibt die Anzahl der noch folgenden Bytes an. In diesem Fall folgen in der Sequenz also noch 6 Bytes.

Byte 7 „01“ ist die Adresse des Modbus Device. Ist im TCP Modus egal, da kein weiteres Pokey Device mit der gleichen IP Adresse existieren kann.

Ab jetzt wird es Spannend! Du brauchst nun folgendes Dokument:
http://www.modbus-ida.org/docs/Modbus_Application_Protocol_V1_1b.pdf

Byte 8 „01“ gibt die Funktion (Function Code oder „supported operation“ im PoKey Manual) an. 0x01 -> Siehe Kapitel 6.1 Read Coils

Nach dem Function Code 01 folgen zwei Bytes mit der Start Adresse „00 00“ und zwei Bytes mit der Anzahl der Register „00 01“.

Welche Startadresse nun „Digital Read Pin 1“ hat, bekommst Du aus der aktuellen „Pokey manual“ PDF, welche mit der jeweiligen Programm Version mit installiert wird. (Die Doku auf der Webseite ist nicht aktuell!!!)

Siehe Modbus1.jpg. Dort erkennst Du, dass die Modbus Startadresse für die Digital Read Register bei 0 Dezimal beginnt. Es wird auch ein Hinweis gegeben, welche „Function Codes“ unterstützt werden. Welchen „Function Code“ nun für welche Funktion benötigt wird steht dort expliziert nicht! Hier muss man ein bisschen Jugend forscht betreiben.

Den Aufbau der Modbus Antwort findest Du auch in dem Modbus-ida.org Dokument.

Für das Lesen und Schreiben der 32Bit Counter brauchst Du die Infos aus Modbus2.jpg! Schau Dir wie gesagt nochmal den PHP Code in meinen Beitrag #7 an. Dort ist erklärt wie die Sequenz zustande kommt.

Super wie du das erklärt hast. Das hilft bestimmt auch anderen.
Mein Fehler lag schon daran, das ich die ersten Byte zum Pokey geordnet habe
und nicht zum Übertragungs Protokoll. Vielen Dank für deine Zeit und Mühe.

Hallo Marcus, hallo Uwe,
habt ihr das LCD-Display mit IPSymcon hinbekommen?
Darf ich abschreiben?

Gruß Helmut

Hallo Helmut,
ich habe es mangels Kenntnisse nicht hinbekommen.
Ich wäre sehr an einer Lösung Interessiert, aber ich muß mir eingestehen
das ich es noch nicht mal Ansatzweise verstehe.
Ich poste mal meinen Ansatz, vielleicht erkennt jemand den Fehler.

	$ClientSocket_ID = 22706 /*[Client Socket Pokey]*/ ;
	$RegisterVariable_ID = 41691 /*[Geräte\PoKey\PoKey55E]*/ ;
#
### Define #####################################################################
//			  							 					 2  3  4  5  6  7  8  9
   define ('LCDinit',	'DD 01 00 00 00 07 01 D1 01 00 00 01 01');   		//01 init
   define ('LCDclear',	'DD 01 00 00 00 07 01 D1 10 00 00 01 01');  			//10 clear
   define ('LCDmove',	'DD 02 00 00 00 07 01 D1 20 01 01 01 01');   		//20 move 01 colum 01 row
   define ('LCDprint',	'DD 02 00 00 00 09 01 D1 30 01 01 01 01 00 00');   //30 print 01 colum 01 row
	//define('LCD',...
### Funktionen #################################################################
#
	function strtohex($string) {
	    $hexstr = unpack('H*', $string);
	      return strtoupper(array_shift($hexstr));
	}

	function hextostr($hex) {
	    $str='';
	     $hex = str_replace(' ', '', $hex);
	     for ($i=0; $i < strlen($hex)-1; $i+=2) {
	         $str .= chr(hexdec($hex[$i].$hex[$i+1]));
	     }
	    return $str;
	}

	function dechex_lsb_msb($decvalue) {
	    $hexstr=dechex($decvalue);
	    for ($i = strlen($hexstr); $i < 8; $i++) {
	        $hexstr="0".$hexstr;
	    }
	    return substr($hexstr, 4, 4).substr($hexstr, 0, 4);
	}

	function status_hex ($status) {
	    if($status == 1) {
	        return "FF 00";
	    } else {
	       return "00 00";
	    }
	}

	function modbus_send($ID, $hex) {
	    RegVar_SendText($ID, hextostr($hex));
	    IPS_Sleep(10);
	}
### ab hier ####################################################
if($IPS_SENDER == "Execute") {
    // Reconnect Client Socket.
    IPS_ApplyChanges($ClientSocket_ID);
		}
    modbus_send($RegisterVariable_ID, LCDclear);

:wink:

Das ist auch nicht einfach. iM komm’ ich auch nicht dazu, deshalb mein Luscher-Angriff.

Der Ansatz mit dem XLM-File ist ev. einfacher, versuche Den doch mal. Da sind die 1Wire-Fühler nicht so gut faßbar, aber alles andere.

Gruß Helmut

Danke für den Tipp mit dem XML File.
Gibt es dazu irgendwo eine Doku, ich finde dazu einfach nichts.
Selbst Google spuckt nichts vernünftiges aus.

Edit: Wenn ein Passwort im Gerät gesetzt ist, dann kann man das XML-File nicht lesen.

-----Also, wie im Script schon geschrieben: im XML Script schauen, was wie „verpackt“ ist und Das denn abfragen.

:wink: ist ja immer so: hatte es gerade ausprobiert um es hier zu schreiben, geht nicht: Fehlermeldung. Muß was mit der neuen Soft sein, vorher ging es.

Warning: simplexml_load_file(): http://ip_adress/devStat.xml:1: parser error : Start tag expected, ‚<‘ not found in C:\IP-Symcon\scripts\45182.ips.php on line 3

Hab’ ne Mail an den Support losgeschickt.
Das Script fing so an:


<?
$array = simplexml_load_file('http://192.168.1.91/devStat.xml');

// im XML Script schauen, was wie "verpackt" ist und Das denn abfragen.

//echo $array->anIn[0]." ".$array->anIn[1]." ".$array->anIn[2]." ".$array->anIn[3]." ".$array->anIn[4]." ".$array->anIn[5]." ".$array->anIn[6];

$ANALOG1 = $array->anIn[0];
SetValueString(44314 /*[ModBus Pokey\Pokeys56E Analog 1]*/,dechex(hexdec($array->anIn[0])));
SetValueString(33297 /*[ModBus Pokey\Pokeys56E Analog 2]*/,dechex(hexdec($array->anIn[1])));
SetValueString(58078 /*[ModBus Pokey\Pokeys56E Analog 3]*/,dechex(hexdec($array->anIn[2])));
SetValueString(29089 /*[ModBus Pokey\Pokeys56E Analog 4]*/,dechex(hexdec($array->anIn[3])));
SetValueString(16929 /*[ModBus Pokey\Pokeys56E Analog 5]*/,dechex(hexdec($array->anIn[4])));
SetValueString(30500 /*[ModBus Pokey\Pokeys56E Analog 6]*/,dechex(hexdec($array->anIn[5])));
SetValueString(43316 /*[ModBus Pokey\Pokeys56E Analog 7]*/,dechex(hexdec($array->anIn[6])));
$Encoder = $array->enc[0];
SetValueString(22653 /*[ModBus Pokey\Pokeys56E Encoder 1]*/,dechex(hexdec($array->enc[0])));
SetValueString(26644 /*[ModBus Pokey\Pokeys56E Encoder 2]*/,dechex(hexdec($array->enc[1])));
SetValueString(47391 /*[ModBus Pokey\Pokeys56E Encoder 3]*/,dechex(hexdec($array->enc[2])));
SetValueString(59704 /*[ModBus Pokey\Pokeys56E Encoder 4]*/,dechex(hexdec($array->enc[3])));
SetValueString(10313 /*[ModBus Pokey\Pokeys56E Encoder 5]*/,dechex(hexdec($array->enc[4])));
SetValueString(53911 /*[ModBus Pokey\Pokeys56E Encoder geht bis 24 Stück]*/,dechex(hexdec($array->enc[5])));

var_dump($array);
//echo $array->in[0];
?>

Kannst ja mal in die Adressleiste deines Browsers eingeben: „IP-Adresse“ anpassen:
http://ip-adresse/devStat.xml

Gruß Helmut

Nachtrag: um die digitalen Pin’s zulesen, füge diesen Code in’s Script:


$Digitale = $array->in[0];
SetValueString(44662 /*[ModBus Pokey\Pokey56_Digi_IN 1]*/,dechex(hexdec($array->in[0])));
SetValueString(50057 /*[ModBus Pokey\Pokey56_Digi_IN 2]*/,dechex(hexdec($array->in[1])));
//... usw bis mögliche 55

Hier werden 2 String-Variablen gefüllt.

Wenn Du Pin 1 und Pin 5 haben willst, mußt Du vom „in“-Array die in[0] und in[4] verarbeiten bzw in eine Variable schreiben.
Das Beispiel hier liest Pin 1 und Pin 2 aus.

Gruß Helmut

Vielen Dank für die Antwort.
Das auslesen und setzen der I/O´s klappt,
Das habe ich sogar mit Uwes Code hinbekommen.
Nur das mit dem LCD bekomme ich nicht hin.

Hallo Marcus,

ich muss mir mal ein LCD Display zulegen um es zu testen.

Aber ich denke, dass Deine Sequenzen falsch sind.
Beispiel:


define ('LCDclear',    'DD 01 00 00 00 07 01 D1 10 00 00 01 01');

Siehe Anhang:
Addresse = 593 → HEX 02 51
„both bytes = 0xAA“ → zwei Bytes → ein Register → Function Code 0x06 → Write single register

DD 01 → Deine Transaktionsbytes
00 00 → Protokollkennzeichen immer 00 00
00 06 → 6 folgende Bytes
01 → Addresse ModBus Device
06 → Function Code
02 51-> Register Address (Hex-Wert von 593)
AA AA → Registers Values (2 * AA laut Anleitung Pokeys)

Meiner Meinung nach müsste Deine LCD Clear Sequenz lauten:


define ('LCDclear',    'DD 01 00 00 00 06 01 06 02 51 AA AA');

Danke Uwe,
mit dem LCD clear hat auf Anhieb funktioniert.
Ich hoffe das ich mit deinem Beispiel das beschreiben des Displays hin bekomme.
Werde mich da heute Abend nochmal mit beschäftigen.

Ich bekomme es nicht hin, da ich es immer noch nicht verstehe.
Diese Register sind wie ein Buch mit sieben Siegel für mich.
Benutze ich beim beschreiben auch nur ein Singel Register oder ein multibles Register.
Laut Manual stehen die Character ja in Byte 9-29, heißt das,
das ich auch bei den Character schon vorher angeben muss wie viele dann kommen?
Die Daten würden aus einer String Variablen kommen, ich weis aber noch gar nicht
wie viele Zeichen darin enthalten sind.
Müssen die Zeichen vorher auch erst in Hex umgewandelt werden?
Entschuldigt bitte meine Unwissenheit.

Ich stelle mein 4x20 LCD Display gerne zu Testzwecken jemanden zur Verfügung.

Schätze mal->
Schreib’ in die Adresse fortlaufend die Zeichen:
zB in Adresse 500 das Zeichen „H“:
jedes Zeichen hat eine Adresse ab 500 dez.

Adresse = 500 -> HEX 1F4
Ascii Code von hier ASCII-Tabelle zB „H“

DD 01 -> Deine Transaktionsbytes
00 00 -> Protokollkennzeichen immer 00 00
00 05 -> 5 folgende Bytes
01 -> Addresse ModBus Device
06 -> Function Code
01 F4 -> Register Address (Hex-Wert von 500)
48 → das Zeichen H

nächstes:

DD 01 -> Deine Transaktionsbytes
00 00 -> Protokollkennzeichen immer 00 00
00 05 -> 5 folgende Bytes
01 -> Addresse ModBus Device
06 -> Function Code
01 F5 -> Register Address (Hex-Wert von 501)
41 → das Zeichen A

usw

Gruß Helmut

Vielen Dank, die Richtung stimmt.
Wenn ich deinen Code benutze verschwindet das Zeichen an der ersten Stelle.
Habe dann ein bisschen probiert und mit folgendem Code bekomme ich das H
auf das Display geschrieben.

define ('LCDprint',	'DD 01 00 00 00 05 01 06 01 F4 00 48');   // print H

Was mir aufgefallen ist:
Das vorletzte Bit die 00 kann ich durch alles mögliche ersetzen und es funktioniert trotzdem.
Dann habe ich versucht die Anzahl der Bits von 00 05 auf 00 06 plus einen weiteren Character
am Ende einzufügen, aber er schreibt nur das erste Zeichen.
Heißt das, das jedes Zeichen einzeln gesendet werden muss?

Joo,
das denke ich.
Jedes einzelnes Zeichen eines Textes an die jeweilige einzelne ADR.

Kommt auch darauf an, welches Display verwendet wird.

Ein 16-Zeichen-Display hat nicht unbedingt fortlaufende Zeichen-ADR.

Gruß Helmut

Dann wäre es doch am besten wenn ich ein Array mit den Zeichen
und ein weiteres mit den Positionen erstelle.
Habt schon mal vielen Dank für eure Unterstützung.

Hi ich habe mir auch mal den Pokeys56E bestellt und er kam gestern.

Habe mal damit gespielt und soweit in IPS eingebunden, ich bekomme auch Hex Daten in die Registervariable.

Wie kann ich z.B. den Digitalen Pin 1 auslesen ?

Ich stehe voll auf dem Schlauch :-(:confused: