hallo,
habe heute mal einPHP Problem.
ich lese Daten von der seriellen Schnittstelle. das funktioniert auch bis jetzt sehr gut.
$mein_string = GetValueString("test");
/* Sowohl das Tabulator- als auch das
Leerzeichen als Token zum Zerlegen verwendet */
$tok = strtok($mein_string, " ");
$i=0;
while ($tok !== false) {
$temp[$i]=$tok;
$tok = strtok(" ");
$i++;
}
$i=0;
settype($temp[],"float");
for($i=0; $i<2;$i++) {
$temp[$i]=$temp[$i]/10;
}
Wie man sieht, kommt immer nur ein Datensatz an, der als String weiterbehandelt wird. Soweit , sogut.
Jetzt möchte ich fünf Datensätze von der Com-Schnittstelle lesen . Wie fange ich das am besten an?
iich will einfach nur fünf Strings die durch "
\r " getrennt sind und hintereinander an der COM anliegen, lesen. Bei oben aufgführter Methode klappt das nicht. Da liest man nur einen String.
Hallo Wolfi,
wenn ich dich recht verstehe, stehen im String 5 Datensätze drin. Also per Schleife einen Datensatzt nach dem anderem aus dem String lesen.
$mein_string = GetValueString ("test");
for ($nIndex=0; $nIndex<5; $nIndex++)
{
.... // hier deine Codezeilen einfügen
}
Das „$temp[$i]“ müßte dann noch zwei Dimensional angelegt werden, also „$temp[$nIndex][$i]“.
Vielleicht hlift dir das.
das Problem liegt offentsichtlich im Timing.
Im Debugger sieht es so aus,:
…Variablenmanager variable test(string),Value: a1:0
…Variablenmanager variable test(string),Value: a2:0
…Variablenmanager variable test(string),Value: a3:123
…Variablenmanager variable test(string),Value: a4:245
Ich kann offentsichtlich die Variable nicht schnell genug abfragen. sie wird dann vom nächsten wert schon wieder überschrieben.
das Problem mit der seriellen Schnittstelle liegt darin, dass man nicht vorhersehen kann, wann der Trigger wirklich erfolgt. Windows liefert die Daten meist dann, wenn sein interner Puffer zu einem bestimmten Prozentsatz gefüllt ist oder wenn nach dem letzten Zeichen ein Timeout eingetreten ist. Dadurch werden die Daten in kleineren Portionen an IPS übergeben, wobei jedesmal ein Schreibzugriff auf die Registervariable und somit auch ein OnUpdate Trigger eintritt. Leider kann man daraus häufig keine Zuordnung zwischen Datensatz und Trigger ableiten. Man kann also nicht sagen, dass nach dem ersten Trigger der erste Datensatz ansteht und nach dem zweiten der nächste usw. Die Trigger können durchaus auch mittendrin auftreten. Es ist daher meist nötig, den Datenstrom erst einmal aufzusammeln und ihn anschließend zu trennen.
Eigentlich sollte das von Paresy vorgeschlagene Verfahren funktionieren. Falls nicht, dann versuche mal folgendes:
den COM-Port direkt mit der Registervariablen verbinden, ohne CutChars
die Registervariable im „Append“-Modus betreiben
das zugehörige Skript von der Registervariablen OnUpdate triggern lassen
im Skript eine Wartezeit (z.B. 500ms) einfügen, um dem Datenstrom Zeit zu geben vollständig einzutreffen
dann erst die Registervariable mit GetValueString(…) auslesen (nicht mit $IPS_VALUE !)
nach dem Auslesen nicht vergessen, die Registervariable wieder zu löschen
den ausgelesenen String mit explode("
", String) aufsplitten (explode liefert ein Array mit den Teil-Strings)
Paresy, das verstehe ich nicht ganz. Für mich ergibt sich dann folgender Ablauf:
[ol]
[li]ComPort kann nicht gewährleisten, dass immer ein ganzer Datensatz auf einmal weitergegeben wird.
[/li][li]RegisterVariable empfängt dann das Datensatzfragment.
[/li][li]Zielvariable wird mit dem Fragment beschrieben.
[/li][li]PHP kann das natürlich nicht auswerten.
[/li][li]ComPort liefert Rest des Datensatz.
[/li][li]RegisterVariable überschreibt damit im Overwrite-Modus die Var.
[/li][li]PHP kann erst nichts auswerten -> Datensatz verloren!
[/li][/ol]
Habe ich da einen Überlegungsfehler? Kannst Du das mal etwas erläutern, damit wir den richtigen Weg zum Ziel finden.
Ich betreibe das bei mir auch im Append-Modus und warte einfach, bis ein ganzer Datensatz zusammengekommen ist. Dann wird er ausgewertet und aus der Quellvariable entfernt.
wie schon oben erwähnt sollte das von Paresy beschriebene verfahren problemlos funktionieren.
Es basiert auf dem „Overwrite“-Modus der Registervariablen. Zusätzlich wird hier auch das CutChars-Modul benötigt. Der Ablauf ist etwa so:
der COM-Port liefert „häppchenweise“ Daten an das CutChars-Modul
das CutChars-Modul wartet auf einen CutChar (z.B. CR)
wurde vom CutChars-Modul ein CutChar empfangen, werden alle bis dahin empfangenen Daten an die Registervariable weitergereicht
die Übergabe an die Registervariable ist ein Schreibvorgang und stellt damit ein Trigger-Ereignis dar
das zugehörige Skript wird gestartet
die System-Variable $IPS_VALUE enthält dann den Datensatz (ohne den CutChar)
Das Overwrite-Verfahren erfordert ein eindeutiges Kriterium, anhand dessen der Datenstrom zuverlässig an der gewünschten Stelle unterteilt werden kann. In diesem Falle ist das CR-Zeichen das geeignete Kriterium. Die Unterteilung übernimmt das CutChars-Modul. Es funktioniert aber auch ohne CutChars, wenn sich zwischen den einzelnen Datensätzen eine kurze Pause befindet.
Das „Append“-Verfahren hat den Nachteil, dass man per Skript alles „zu Fuß“ erledigen muss. Dafür funktioniert es aber immer. Man muss allerdings wissen, was man zu tun hat.
Hallo,
vielen Dank an alle die sich hier für mich Gedanken gemacht haben.
Meine Lösung funktioniert jetzt folgendermaßen:
Script wird immer dann ausgeführt, wenn an der COM-Schnittstelle sich etwas tut.
D.h. es wird auf die Registervariable Test getriggert.
Die Registervariable ist im Mode override und split = CR