Pokey55E mit IPSymcon

Ich brauche wegen der Anbindung der Pokeys56 Schaltung über Modbus TCP-Modus Hilfe.

Ich habe festgestellt, dass das Abfrage der Adresse 1 nicht nur die Adresse 1 sondern auch die Nachbaradresse abfragt und anzeigt.
Ein Bespiel:


IPS fragt:
05.02.2012 19:52:04.00 |          TRANSMITTED | 00 52 00 00 00 06 01 02 00 00 00 01 
Pokey antwortet:
05.02.2012 19:52:04.00 |             RECEIVED | 00 52 00 00 00 04 01 02 01 03


Wobei das letzte Byte (in obiger Zeile = 03) auch das Nachbarbit mit anzeigt.
Ist nur die abgefragte Adresse High erscheint eine „1“,
ist sie „0“ aber das Nachbarbit gesetzt, erscheint eine „2“,
ist die abgefragte Adr =„1“ und das NachbarBit auch „1“, erscheint eine „3“.

Nun habe ich mir gedacht: ich frage die Adressen in 2er Gruppen ab, nur das Abfragen ist mit einer Boolen Variablen und EINER Adresse verknüpft.

Ich dachte mir daraufhin: Werte die Schnittstelle, den Client Socket aus.

Nur die Antworten sind nicht Adressbezogen, soll heißen: die Antwort ist im Muster von allen Adressabfragen gleich.
Ausschnitt:

05.02.2012 19:52:04.00 |          TRANSMITTED | 00 52 00 00 00 06 01 02 00 00 00 01 
05.02.2012 19:52:04.00 |             RECEIVED | 00 52 00 00 00 04 01 02 01 03 

05.02.2012 19:52:05.00 |          TRANSMITTED | 00 53 00 00 00 06 01 01 00 03 00 01 
05.02.2012 19:52:05.00 |             RECEIVED | 00 53 00 00 00 04 01 01 01 03 

05.02.2012 19:52:06.00 |          TRANSMITTED | 00 54 00 00 00 06 01 01 00 02 00 01 
05.02.2012 19:52:06.00 |             RECEIVED | 00 54 00 00 00 04 01 01 01 03 

05.02.2012 19:52:06.00 |          TRANSMITTED | 00 55 00 00 00 06 01 02 00 00 00 01 
05.02.2012 19:52:06.00 |             RECEIVED | 00 55 00 00 00 04 01 02 01 03 

05.02.2012 19:52:07.00 |          TRANSMITTED | 00 56 00 00 00 06 01 01 00 03 00 01 
05.02.2012 19:52:07.00 |             RECEIVED | 00 56 00 00 00 04 01 01 01 03 

05.02.2012 19:52:08.00 |          TRANSMITTED | 00 57 00 00 00 06 01 01 00 02 00 01 
05.02.2012 19:52:08.00 |             RECEIVED | 00 57 00 00 00 04 01 01 01 03 

05.02.2012 19:52:09.00 |          TRANSMITTED | 00 58 00 00 00 06 01 02 00 00 00 01 
05.02.2012 19:52:09.00 |             RECEIVED | 00 58 00 00 00 04 01 02 01 03 

Hier laut Wiki die Bedeutung der Bytes.

Transaktionsnummer, Protokollkennzeichen, Zahl der noch folgenden Bytes, Adresse, Funktion, Daten =
…2 Byte…, 2 Byte (immer 0x0000), 2 Byte (n+2)…, .1 Byte., …1 Byte., n Byte.

Hätte jemand eine Lösung für mich??

Nachtrag:
In dem PDF vom Pokeys56E steht:
[i]Modbus support
PoKeys56E supports slave (server) operation of Modbus TCP communication protocol. Modbus TCP compatible devices on the network can read the values from the device and set the outputs. To elevate the security, user can define which peripherals are accessible via Modbus TCP.
Modbus TCP uses TCP protocol on port 502 (default), which can be changed in Modbus settings (accessible from the menu Device – Modbus configuration…). The Modbus TCP connection is disconnected after 3 seconds of inactivity (this default value can be changed in the Modbus settings).
Discrete inputs/outputs

Supported operations:
0x01: Read coils
0x02: Read discrete input
0x05: Write single coil
0x0F: Write multiple coils[/i]

Könnte ich mit der " 02 " - Abfrage was werden und wie könnte Die sein? Hat sich erledigt, nur lesen oder lesen/schreiben ist 2 oder 1.
Gruß Helmut

Ich bekam gerade die Mitteilung, dass der Fehler im nächsten Update behoben sein würde.

Hi, Helmut

Thank you for sending us your observation. Indeed, there was a flaw in bit addressing. This will be fixed with the next update.

Best regards / Z lepimi pozdravi,

Matevž Bošnak, B.Sc.

You can expect the update in less than a month.

Gruß Helmut

Nun hatte ich den Pokeys56E Entwicklern noch einen Fehler gemailt, den hat er aber abgewiesen,
und zwar bekomme ich keine Variable für das Lesen von den analogen Registern einzeln als unsigniert_Word gelesen.

Nur Doppelword geht, was als Variablenwert unbrauchbar ist.
Ich habe mal ein Png von 2 analog-Register-lesen (11 und 12) angehängt.

Das Debugfenster der Modbus Instanz gibt schon die richtigen Werte raus.

Die Variable wird nur aktualisiert, wenn ich Dword signiert nehme, was unbrauchbar ist.
Dann aber liefert er im Debugfenster zyklisch die Werte, bei Word nur sporadisch.

Was mache ich falsch?

Gruß Helmut

Edit, 8.2.2012

Der Single Coil-Befehl funktioniert mit neuer Programmversion, Herr Matevž Bošnak (Fa. PoLabs) schickte mir ein neues File :wink: .

Hallo Helmut,

dies ist ja ein hochinteressantes Device!
Hast Du schon Erfahrungen bezüglich der Stabilität der LAN-Verbindung sammeln können?
Beim AVR Net-IO ist dieser Punkt ja etwas enttäuschend.

Hast Du das Device direkt über www.poscope.com oder über einen dort eingetragenen Distributor gekauft?

Ich kann über andere Net-IOs nichts sagen und über Pokeys56E auch keine Referenz geben, aber das Teil läuft gut.

Meine Empfehlung: über die Herstellerseite, ohne Schraubklemmen bestellen, kommt trotzdem mit, wenn nicht, tauschen wir :wink:

Schade ist, dass die 1Wire Bausteine nicht über Modbus TCP gelesen werden können, ich wüßte nicht wie.

Aber dass, was über Modbus TCP beschrieben ist, selbst LCD und PWM funktioniert super:
Modbus TCP support (access to digital IO, analog inputs, encoders’ counters, digital counters values, PWM outputs, LCD display, LED matrix display, PoExtBus devices, matrix keyboard status)

Die 1Wire Software, da gibt es noch 'ne Extrasoft mit 'zig DS18B20, läuft bei mir nicht (Win7).

Ich habe auch noch 'ne Purebasicsoft, die alles ausliest, aber noch keine Genehmigung Die zu verändern und weiterzugeben (Schreiben kann sie nicht).

Irgendwann bekomme ich von Paresy auch 'ne Rückmeldung, was ich mit IPSymcon falsch mache, wegen der Registerausleserei.

Gruß Helmut

Hallo Helmut,

nur nicht aufgeben, Unterstützung naht! :wink:
Hab mir gerade so ein Ding bestellt.

Hallo Helmut,

PoKeys56E ist angekommen und ich habe auch schon etwas damit getestet.
Ich denke, dass die IPS ModBus Unterstützung „Out Of The Box“ nicht alle Funktionen dieses Device unterstützt. Laut Handbuch PoKeys braucht man bestimmte Function Codes um z.B. die Counter zu lesen und zu schreiben. Ich habe alle möglichen Variationen in der IPS ModBus Instanz durchprobiert. Bestimmte Function Codes werden aber von IPS einfach nicht verwendet.

Da aber ModBus TCP recht simpel ist, habe ich die HEX Byte Strings über eine Register Variable selber an PoKeys geschrieben und siehe da, alles scheint zu funktionieren!

Den Client Socket zur PoKeys IP wurde ja schon mit der ModBus Instanz angelegt. Man muss jetzt noch manuell eine Register Variable anlegen, den Client Socket als Übergeordnete Instanz definieren und ein neues Script als Ziel Script definieren. Beim schreiben der HEX Byte Strings hat mir folgendes Dokument sehr geholfen. http://www.modbus-ida.org/docs/Modbus_Application_Protocol_V1_1b.pdf

Ich habe in dem Script mal die verschiedenen Request Strings eingebaut. Es zeigt nur die Vorgehensweise und wertet die PoKeys Antwort nicht aus sondern schreibt sie als Hex-String ins Log. Die Auswertung muss man manuell in dem Debug Fenster der Client Socket Instanz machen. Es sollte aber kein Zauberwerk mehr sein, ein entsprechendes Script zu schreiben. Die einzelnen HEX Bytes (nur die Antwortbytes) müssen nur entsprechend umgerechnet und einer Variable zugewiesen werden.

Werde mich da in den nächsten Tagen mal dransetzen.


<?

$RegisterVariable_ID = 37006 /*[Register Variable]*/;

function strtohex($string) {
	$hexstr = unpack('H*', $string);
  	return 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;
}


if($IPS_SENDER == "RegisterVariable") {
	echo strtohex($IPS_VALUE);
}

if($IPS_SENDER == "Execute") {
	// 2 Bytes Transaction Identifier -> 00 00 For synchronization between messages of server & client
	// 2 Bytes Protocol Identifier    -> 00 00 Zero for Modbus/TCP
	// 2 Bytes Length Field           -> 00 xx Number of following bytes in this frame
	// 1 Byte  Unit Identifier        -> 01
	// 1 Byte Function Code           -> xx siehe ModBus Protokoll Doku
	// n Bytes Data bytes             ->

	$PinRead =      hextostr("00 00 00 00 00 06 01 01 00 00 00 01");
	// siehe ModBus Doku Kapitel 6.1 Read Coils
	// Function Code = 01 | Starting Address = 00 00 (Pin 1) | Quantitiy of coils = 00 01 (1 Byte lesen)
	
	$PinRead2 =     hextostr("00 00 00 00 00 06 01 02 00 00 00 01");
	// siehe ModBus Doku Kapitel 6.2 Read Discrete Inputs
	// Function Code = 02 | Starting Address = 00 00 (Pin 1) | Quantitiy of inputs = 00 01 (1 Byte lesen)

	$PinWrite =     hextostr("00 00 00 00 00 06 01 05 00 02 FF 00");
	// siehe ModBus Doku Kapitel 6.5 Write Single Coil
	// Function Code = 05 | Starting Address = 00 02 (Pin 3) | Output Value FF 00 oder 00 00 (Ein / Aus)

	$CounterRead =  hextostr("00 00 00 00 00 06 01 03 03 20 00 02");
	// siehe ModBus Doku Kapitel 6.3 Read Holding Registers
	// Function Code = 03 | Register Address = 03 20 (Counter Pin 1 Address 800) | Quantity of registers = 00 02 (2 Register lesen)

	$CounterWrite = hextostr("00 00 00 00 00 10 03 20 00 02 04 AB CD");
	// siehe ModBus Doku Kapitel 6.12)  Write Multiple registers
	// Function Code = 10 | Register Address = 03 20 (Counter Pin 1 Address 800) | Quantity of registers = 00 02 (2 Register schreiben) | Byte Count 04 (4*8 = 32bit) | Value AB CD (z.b. 43981 setzen)

	$AnalogRead =   hextostr("00 00 00 00 00 06 01 04 00 0A 00 01");
	// siehe ModBus Doku Kapitel 6.4 Read Input Register
	// Function Code = 04 | Register Address = 00 0A (Pin 41A) | Quantity of Registers 00 01 (1 Register lesen)

	$HexString = $PinRead; // Hier die entsprechende Variable einsetzen, Script ausführen und Client Socket Debug anschauen!
	//$HexString = $CounterRead; $HexString = ...

	RegVar_SendText($RegisterVariable_ID, $HexString);
}
?>

Hallo Uwe,

ich habe mit den Entwicklern einen netten Mailkontakt, ich hatte durch Zufall gesehen, dass deren Preise im Shop auf 0,81 € pro Gerät gefallen waren.
Habe ich Denen gemailt und aus Dankbarkeit bekomme ich 20% Rabatt für 3 Tage.
Darauf hin meinte ich, Geld ist nicht alles :wink: und bat um Unterstützung um einfach das Gerät an sprechen zu können, ohne DLL und Co.

Dann bekam ich ein XML-File, das ich mit grossartiger Hilfe von Christian aus diesem Tread benutzen kann.
Das nochmal hier zu schreiben spare ich mir, steht hier im Tread.

Damit ist das Auslesen rel. einfach.
Gerade vorhin habe ich dann noch eine Mail erhalten, in der der Entwickler, auch das einfache Beschreiben über die Adresszeile des Browsers zeigt.

Zitat:[QUOTE]
[i][b]
First, you have to enable the option ‚Enable toggling of outputs‘ in the web interface configuration in PoKeys software.
Furthermore, you have to disable anonymous access, create a user and assign a password. Before toggling the outputs, you have to log in first with the user name and password you selected.
Then you will be able to use the command below.

Web interface is meant mainly for user-PoKeys interaction. For the direct access, I would advise using the PoKeys protocol (TCP port 20055) directly or via the PoKeys dll communication library.

You can use the following command:

setDO.html?Pin=[PinIndex]&State=[PinState]

Where [PinIndex] is a pin index on the PoKeys board and [PinState] is one of the following:
T - toggles output pin
0 - turns off the output pin
1 - turn on the output pin

For example

setDO.html?Pin=1&State=T

toggles the pin 1.

Regards,[/[/b][/i]QUOTE]

Habe ich noch nicht nicht probiert, sollte aber auch hier in einem Script verpackt gehen.

Du bist ja noch viel versierter in PHP, XML und Co KG.

Ich hänge Dir das XML-File mal hier ran. Einfach an die IP-Adresse hängen.

Die 3.21er Pokey56E-Version ist auf meinem Hinweis hin gemacht worden, weil ich es hier mit dem Bitbefehl nicht richtig ausgewertet bekam, die Byte, Word, DWordfehler wären aber nicht sein Bier, meinte er.

Gruß Helmut

devStat.xml (1.23 KB)

Hi,

Ich habe mal in einem Script meine Versuche der letzten Woche mit PoKeys56E zusammen gefasst. Der Support des Herstellers Poscope kann man nur als vorbildlich bezeichnen. Probleme und Fragen wurden umgehend gelöst und beantwortet. Aber nicht nur das. Meine per Mail angefragten Wünsche in Bezug auf fehlende Modbus Funktionen wurden umgehend umgesetzt und befinden sich jetzt in der aktuellen Firmware. Wenn ich das richtig sehe, sind jetzt alle Funktionen des Devices per Modbus verfügbar. Ein paar Sachen konnte ich noch nicht testen, bin aber guter Dinge das alles funktionieren wird.

Wie in diesem Post bereits beschrieben, sind einige Funktionen nicht über die native IPS Modbus Instanz nutzbar. Ist aber nicht tragisch, da Modbus TCP simpel zu Scripten ist. Erklärungen über Modbus TCP finden sich hier und vor allem hier.

Bei Modbus sende ich von IPS über TCP einen Hex String mit einer Lese oder Schreib Anforderung. Die Antwort vom Device ist auch ein Hex String. Ich benutze ich die Transaktionsnummer (Byte 1 + 2) um die Anfrage an das Device und die Antwort vom Device zuordnen zu können. Ich habe willkürlich in dem Script folgende Definitionen verwendet.

Digitalport lesen = D1
Analogport lesen = A1
Counter lesen = C1
Sensor lesen = 11

Digitalport schreiben = D0
Counter schreiben = C0

Die Pinnummer kodiere ich im nächsten Byte als normalen Dezimalwert
Pin1 = 01, Pin2 = 02, … Pin10=10 (nicht 0A!!), Pin11 = 11, usw.

Die Transaktionsnummer wird immer vom Device am Anfang der Antwort mitgeliefert. Wenn meine Antwortsequenz z.B. mit C1 19 beginnt, kann ich genau sagen, dass die Antwort das Ergebnis für „Counter lesen von Pin 19“ ist!.

Im anhängendem Bild ist die IPS Konfiguration abgebildet. Ich brauche eine „Client Socket“ Instanz für die IP Verbindung zum PoKeys56E. (Port 502)
Die „Register Variable“ hat diesen „Client Socket PoKeys56E“ als übergeordnete Instanz sowie das „PoKeys56E“ Script als Ziel Skript definiert.
Das Ziel Script „PoKeys56E“ wird durch einen zyklischen Timer alle 10 Sekunden gestartet.

Durch den Timer bekommen ich im Script alle 10 Sekunden ein „TimerEvent“. Das TimerEvent nutze ich, um alle Werte, die ich benötige bzw. angeschlossen habe, vom Device zu requesten. Die entsprechenden Request Strings muss ich in der if($IPS_SENDER == „TimerEvent“) Schleife anpassen.

Alle Antworten vom Device landen in der if($IPS_SENDER == „RegisterVariable“) -Schleife. Hier kann durch eine String Analyse die Art der Antwort, der angesprochenen Pin und der übermittelte Wert festgestellt werden. Diese Daten werden durch If und Case Schleifen separiert. Ich habe in dem Script ein Simples „Echo“ als Ausgabe verwendet. Man sieht die Ausgaben dadurch im Log. Anstelle des „Echo“ müsste dann z.B. eine Zuweisung des Wertes zu einer IPS Variablen vorgenommen werden. Da durch die freie Zuordnung der 55 Pins unzählige Variationen möglich sind habe ich nicht alle Fälle aufgeführt. Wenn ich z.B. die Pins 19-55 nicht nutze, brauche ich sie auch nicht in die Case Schleife aufnehmen.

In die if($IPS_SENDER == „Execute“) - Schleife habe ich ein paar Beispiele zum Beschreiben des Devices eingefügt. Bei manuellem Ausführen des Scriptes werden sie ausgeführt. Diese Befehle machen dort keinen praktischen Sinn und müssten in entsprechenden Aktionsscripte ausgelagert werden.

Ich hoffe, dass ich ich das Prinzip verständlich erklärt habe. Beispiele für das Auslesen von 1Wire und I2C habe ich in den unten stehenden Code hinzugefügt. Ich habe es aber erst nur mit 1Wire und nicht mit I2C Sensoren getestet. Das Sensoren auslesen über Modbus funktioniert allerdings erst mit Firmware 3.0.26. Wichtig ist hierbei auch die richtige Konfiguration der Modbus Berechtigung. Ohne Häkchen bei Read Access kann man die Sensoren nicht auslesen. :wink:


<?
$ClientSocket_ID = 23330 /*[Client Socket PoKeys56E]*/;
$RegisterVariable_ID = 37006 /*[Register Variable]*/;

define('DigitalRead01','D1 01 00 00 00 06 01 01 00 00 00 01');
define('DigitalRead02','D1 02 00 00 00 06 01 01 00 01 00 01');
define('DigitalRead03','D1 03 00 00 00 06 01 01 00 02 00 01');
define('DigitalRead04','D1 04 00 00 00 06 01 01 00 03 00 01');
define('DigitalRead05','D1 05 00 00 00 06 01 01 00 04 00 01');
define('DigitalRead06','D1 06 00 00 00 06 01 01 00 05 00 01');
define('DigitalRead07','D1 07 00 00 00 06 01 01 00 06 00 01');
define('DigitalRead08','D1 08 00 00 00 06 01 01 00 07 00 01');
define('DigitalRead09','D1 09 00 00 00 06 01 01 00 08 00 01');
define('DigitalRead10','D1 10 00 00 00 06 01 01 00 09 00 01');
define('DigitalRead11','D1 11 00 00 00 06 01 01 00 0A 00 01');
define('DigitalRead12','D1 11 00 00 00 06 01 01 00 0B 00 01');
//define('DigitalReadxx','...

define('AnalogRead41','A1 41 00 00 00 06 01 04 00 0A 00 01');
define('AnalogRead42','A1 42 00 00 00 06 01 04 00 0B 00 01');
define('AnalogRead43','A1 43 00 00 00 06 01 04 00 0C 00 01');
define('AnalogRead44','A1 44 00 00 00 06 01 04 00 0D 00 01');
define('AnalogRead45','A1 45 00 00 00 06 01 04 00 0E 00 01');
define('AnalogRead46','A1 46 00 00 00 06 01 04 00 0F 00 01');
define('AnalogRead47','A1 47 00 00 00 06 01 04 00 10 00 01');

define('CounterRead01','C1 01 00 00 00 06 01 03 03 20 00 02');
define('CounterRead02','C1 02 00 00 00 06 01 03 03 22 00 02');
define('CounterRead05','C1 05 00 00 00 06 01 03 03 28 00 02');
define('CounterRead06','C1 06 00 00 00 06 01 03 03 2A 00 02');
define('CounterRead09','C1 09 00 00 00 06 01 03 03 30 00 02');
define('CounterRead11','C1 11 00 00 00 06 01 03 03 34 00 02');
//define('CounterReadxx','...

define('SensorRead01','11 01 00 00 00 06 01 03 01 90 00 02'); //I2C Sensors
define('SensorRead02','11 02 00 00 00 06 01 03 01 92 00 02');
define('SensorRead03','11 03 00 00 00 06 01 03 01 94 00 02');
define('SensorRead04','11 04 00 00 00 06 01 03 01 96 00 02');
define('SensorRead05','11 05 00 00 00 06 01 03 01 98 00 02');
define('SensorRead06','11 06 00 00 00 06 01 03 01 9A 00 02');
define('SensorRead07','11 07 00 00 00 06 01 03 01 9C 00 02');
define('SensorRead08','11 08 00 00 00 06 01 03 01 9E 00 02');
define('SensorRead09','11 09 00 00 00 06 01 03 01 A0 00 02');
define('SensorRead10','11 10 00 00 00 06 01 03 01 A2 00 02');

define('SensorRead11','11 11 00 00 00 06 01 03 01 A4 00 02'); //1Wire Sensors
define('SensorRead12','11 12 00 00 00 06 01 03 01 A6 00 02');
define('SensorRead13','11 13 00 00 00 06 01 03 01 A8 00 02');
define('SensorRead14','11 14 00 00 00 06 01 03 01 AA 00 02');
define('SensorRead15','11 15 00 00 00 06 01 03 01 AC 00 02');
define('SensorRead16','11 16 00 00 00 06 01 03 01 AE 00 02');
define('SensorRead17','11 17 00 00 00 06 01 03 01 B0 00 02');
define('SensorRead18','11 18 00 00 00 06 01 03 01 B2 00 02');
define('SensorRead19','11 19 00 00 00 06 01 03 01 B4 00 02');
define('SensorRead20','11 20 00 00 00 06 01 03 01 B6 00 02');



define('DigitalWrite01','D0 01 00 00 00 06 01 05 00 00'); // + FF 00 -> on + 00 00 -> off
define('DigitalWrite02','D0 02 00 00 00 06 01 05 00 01');
define('DigitalWrite03','D0 03 00 00 00 06 01 05 00 02');
define('DigitalWrite04','D0 04 00 00 00 06 01 05 00 03');
define('DigitalWrite05','D0 05 00 00 00 06 01 05 00 04');
define('DigitalWrite06','D0 06 00 00 00 06 01 05 00 05');
define('DigitalWrite07','D0 07 00 00 00 06 01 05 00 06');
define('DigitalWrite08','D0 08 00 00 00 06 01 05 00 07');
define('DigitalWrite09','D0 09 00 00 00 06 01 05 00 08');
define('DigitalWrite10','D0 10 00 00 00 06 01 05 00 09');
define('DigitalWrite11','D0 11 00 00 00 06 01 05 00 0A');
define('DigitalWrite12','D0 12 00 00 00 06 01 05 00 0B');
define('DigitalWrite13','D0 13 00 00 00 06 01 05 00 0C');
//define('DigitalWritexx','...


define('CounterWrite01','C0 01 00 00 00 0B 01 10 03 20 00 02 04'); // + 4 Byte value LSB/MSB
define('CounterWrite02','C0 02 00 00 00 0B 01 10 03 22 00 02 04');
define('CounterWrite05','C0 05 00 00 00 0B 01 10 03 28 00 02 04');
define('CounterWrite06','C0 06 00 00 00 0B 01 10 03 2A 00 02 04');
define('CounterWrite09','C0 09 00 00 00 0B 01 10 03 30 00 02 04');
define('CounterWrite11','C0 11 00 00 00 0B 01 10 03 34 00 02 04');
//define('CounterWritexx','...



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);
}

if($IPS_SENDER == "TimerEvent") {
	// Reconnect Client Socket. Not needed for timer cycles below the configured Modbus timeout
	IPS_ApplyChanges($ClientSocket_ID);

	// send the read request strings of the needed values
	modbus_send($RegisterVariable_ID, DigitalRead01);
	modbus_send($RegisterVariable_ID, DigitalRead02);
	//..
	modbus_send($RegisterVariable_ID, AnalogRead41);
	modbus_send($RegisterVariable_ID, AnalogRead42);
	//..
	modbus_send($RegisterVariable_ID, CounterRead01);
	modbus_send($RegisterVariable_ID, CounterRead02);
	//..
	modbus_send($RegisterVariable_ID, SensorRead11);
	modbus_send($RegisterVariable_ID, SensorRead12);
	//..

}

if($IPS_SENDER == "RegisterVariable") {
	$hexstring = strtohex($IPS_VALUE);
	$arr_modbus_receive = str_split(strtohex($IPS_VALUE), 2);

	if($arr_modbus_receive[0] == "D1") { // D1 -> Modbus answer for digital read
		// read the status of the PIN
		if($arr_modbus_receive[9] == "01") {
			$value = 1;
		} else {
		   $value = 0;
		}
		// Assign status to
		switch ($arr_modbus_receive[1]) {
			case "01":
				echo "Digital In Pin1 = ".$value."
";
				break;
			case "02":
            echo "Digital In Pin2 = ".$value."
";
				break;
		}
	}
	
 	if($arr_modbus_receive[0] == "A1") { // A1 Modbus answer for analog read
		$value = hexdec($arr_modbus_receive[9].$arr_modbus_receive[10]);
		// 12bit 3.3V max -> $volt = $value * 3.3 / 4095
		$volt = number_format($value * 3.3 / 4095, 3);
		switch ($arr_modbus_receive[1]) {
			case "41":
				echo "Analog In Pin41 = ".$volt." V
";
				break;
			case "42":
            echo "Analog In Pin42 = ".$volt." V
";
				break;
			case "43":
            echo "Analog In Pin43 = ".$volt." V
";
				break;
			case "44":
            echo "Analog In Pin44 = ".$volt." V
";
				break;
			case "45":
            echo "Analog In Pin45 = ".$volt." V
";
				break;
			case "46":
            echo "Analog In Pin46 = ".$volt." V
";
				break;
			case "47":
            echo "Analog In Pin47 = ".$volt." V
";
				break;
		}
	}

	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 "01":
				echo "Counter Read Pin1 = ".$value."
";
				break;
			case "02":
            echo "Counter Read Pin2 = ".$value."
";
				break;
			case "05":
            echo "Counter Read Pin5 = ".$value."
";
				break;
			case "06":
            echo "Counter Read Pin6 = ".$value."
";
				break;
		}
	}
	
	if($arr_modbus_receive[0] == "11") { // 11 Modbus answer for sensor 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;
		}
		// Temperature convert
		$value = $value / 100;
		switch ($arr_modbus_receive[1]) {
			case "01":
				echo "Sensor01 Read = ".$value." °C
";
				break;
			case "02":
            echo "Sensor02 Read = ".$value." °C
";
				break;
			case "11":
            echo "Sensor11 Read = ".$value." °C
";
				break;
			case "12":
            echo "Sensor12 Read = ".$value." °C
";
				break;
		}
	}

	if($arr_modbus_receive[0] == "D0") { // D0 -> Modbus answer for digital write
		// read the status of the PIN
		$hexstr = strtoupper($arr_modbus_receive[10].$arr_modbus_receive[11]);
		if($hexstr == "FF00") {
		   $status = 1;
		} else {
		   $status = 0;
		}
		// Assign status to Pin
		switch ($arr_modbus_receive[1]) {
			case "01":
				echo "Set Digital Out Pin1 = ".$status."
";
				break;
			case "02":
            echo "Set Digital Out Pin2 = ".$status."
";
				break;
			case "03":
            echo "Set Digital Out Pin3 = ".$status."
";
				break;
			case "04":
            echo "Set Digital Out Pin4 = ".$status."
";
				break;
			//case...
		}
	}

	if($arr_modbus_receive[0] == "C0") { // C0 Modbus answer for counter write
		switch ($arr_modbus_receive[1]) {
			case "01":
				echo "Set Counter Value Pin1
";
				break;
			case "02":
				echo "Set Counter Value Pin2
";
				break;
			//case ...
		}
	}
}

if($IPS_SENDER == "Execute") {
	// Reconnect Client Socket. 
	IPS_ApplyChanges($ClientSocket_ID);

	//here are some write examples

	// Set Digital Output Pin3 to on = 1
	modbus_send($RegisterVariable_ID, DigitalWrite03.status_hex(1));
	// Set Digital Output Pin4 to off = 0
	modbus_send($RegisterVariable_ID, DigitalWrite04.status_hex(0));


	// Set Counter value of Pin 1 to 123456789
	modbus_send($RegisterVariable_ID, CounterWrite01.dechex_lsb_msb(123456789));
	// Set Counter value of Pin 2 to -111
	modbus_send($RegisterVariable_ID, CounterWrite02.dechex_lsb_msb(-111));

}

?>

Hi,

ich habe das Auslesen von 1Wire und I2C im oberen Post nachgetragen. Laut Mail vom PoKeys Support soll das nächste Firmware Release auch den DS18S20 unterstützen. Momentan werden nur DS18B20 ausgelesen.
Es soll wohl auch noch in diesem Jahr eine Firmware herauskommen, mit der kleine Programme auf dem Device ausgeführt werden können.

Frei nach Apple: „Ein unglaubliches Gerät zu einem unglaublichen Preis!“ :smiley:

Hi Uwe,

habe jetzt den PoKeys56E laufen, Fehler lag natürlich bei mir…

Ich habe jetzt mal die notwendigen Sockets und Instanzen erstellt, Dein Script kopiert, angepasst und bekommen bei:

function modbus_send($ID, $hex) {
	 RegVar_SendText($ID, hextostr($hex));
    IPS_Sleep(10);
}

immer den Fehler:

TransactionID does not match

vor der Angabe des Wertes: „Digital In Pin1=1“

Hast Du dazu eine Idee?

Hallo,
Zitat Uwe:
Den Client Socket zur PoKeys IP wurde ja schon mit der ModBus Instanz angelegt. Man muss jetzt noch manuell eine Register Variable anlegen, den Client Socket als Übergeordnete Instanz definieren und ein neues Script als Ziel Script definieren. Beim schreiben der HEX Byte Strings hat mir folgendes Dokument sehr geholfen.

Kann nur die Registervariable oder der Modbus Client Socket gemeint sein.

Auslöser des Scriptes ist die Registervariable!

Gruß Helmut

Hallo Helmut,

dass ist ja alles klar und entsprechend konfiguriert. Trotzdem kommt der Fehler.

So, hier der Fehler…

pokeys-fehler.JPG

So, Uwe hat den Fehler gefunden. Ich hatte den Client Socket benutzt der über den Weg ModBus-Gerät -> Modbus-TCP -> Client Socket angelegt wurde. Offensichtlich speichert IPS dann noch eine ID, die so nicht gebraucht wird.

Nachdem Uwe den Client Socket neu angelegt hatte, war der Fehler verschwunden. Wenn man also Uwe’s Script benutzt, den Client Socket immer direkt als neue Instanz anlegen, ModBus-Instanzen werden dann nicht verwendet!

Hallo Marcus,

Ich habe das nochmal bei mir nachgestellt. Das Problem war nicht der „Client Socket“ sondern die Splitter Instanz „Modbus RTU/TCP“ (siehe Anhang)
Wenn diese im Modus „Modbus TCP“ an den vom Script verwendeten Client Socket gebunden ist, kommt das beschriebene Problem.

Meine Vermutung: Die TransactionIDs der eingehenden Nachrichten „kollidieren“ mit dem internen TransactionID Zähler der „Modbus RTU/TCP“ Instanz.
Da diese Instanz die Modbus Anfrage nicht selber gesendet hat, kann sie natürlich keinen Bezug AnfrageID = AntwortID herstellen und sendet zu Recht einen Fehler.

Als Versender sollte von IPS dann aber besser „ModBus RTU/TCP“ statt „Client Socket“ im Log verwendet werden! :confused:

ModBus RTU_TCP.JPG

Hi, bevor ich mir mein Display beschädige frag ich lieber mal nach.
Wie muß ich die Ein und Ausgänge für ein HD44780 4x20 Display konfigurieren?
Pin 28 Pokey soll an Pin5 LCD angeschlossen werden, da es der R/W kanal ist,
muß ich den Port 28 auf digital Ein oder Ausgang stellen?
Pin 29 müßte ja ein Digitaler Ausgang sein, oder ?
Für Hilfe wie immer Dankbar.

Hallo Pokeyfreund!

Der R/W kommt nach GND und zwar fest.

Weil, aus dem Display werden keine Daten gelesen.

Habe zwar noch kein LCD angeschlossen, aber es müßten alles Ausgänge werden, denke ich.

Gruß Helmut

Vielen Dank für die Info!
Da ich erst Freitag wieder zuhause bin und den Pokey einbinden kann,
kommt direkt die nächste Frage :smiley:
Sendet der Pokey automatisch ohne polling seine Werte an IPS?

Pokey ist eingebunden,
dank eurer tollen Vorarbeit ging das sehr schnell.

Lcd ist auch angeschlossen und funktioniert.
Zumindest kann ich mit der Software Text eingeben.
Aber wie ich das aus IPS machen kann.:confused:

Hat jemand einen Lösungsansatz. Ich weiß im Moment
nicht mal, ob ich bei Modbus, AVR, dll´s suchen muß.
Am liebsten würde ich mir den Inhalt von 4 String-Variablen;
auf dem Display anzeigen lassen.