ich habe eine kleine Steuerung (µC 8051 mit Wickenhäuser Compiler) an IPS. Dort ist ein Wert als Float abgelegt (müßte 4 Byte sein). Diesen will ich übertragen und auch als Float in IPS verwenden. Die Daten bekomme ich schon als $inbuf[1…4]. Wie kann ich aus diesen Werten wieder ein Float machen? Pointer mit Float und $inbuf[1…4] auf selbe Adresse? Habe noch zu wenig Erfahrungen mit diesen Werten.
Wer kann helfen?
In Delphi kann ich Werte übereinanderlegen, d.h. als array speichern und als float(single) auslesen mittels „absolute“.
Da ja hoffentlich die Speicherung der Float Werte in beiden Steuerungen gleich ist, sollte dann als Resultat auch das gleiche rauskommen.
Ich hoffe, mit diesen Informationen kann man was anfangen. Ein Auslesen aus dem µC und Umrechnen in Delphi bringt jedenfalls die korrekten Resultate.
Ja, ich will alles im IPS machen. Dies war nur ein Beispiel, wie ich es mit Delphi machen würde.
Der Puffer $inbuf[1…4] ist schon im IPS. Den hole ich mittels einen Comportaufrufes schon vom µC. Die Werte sind an sich schon in IPS, nur diese 4 Bytes muss ich in einen Float umgewandelt bekommen.
SetValueString("V24_InBuffer",""); // clear Buffer
$string = "Anfrage float";
COMPort_SendText(50911, $string);
while (strlen(GetValueString("V24_InBuffer"))<6) ;
$inbuf = GetValueString("V24_InBuffer");
if (ord($inbuf[0])==1) { //wenn Anwort OK vom Protokoll
return ("Laenge = ".strlen($inbuf)."|".ord($inbuf[0])."|".ord($inbuf[1])."|".ord($inbuf[2])."|".ord($inbuf[3])."|".ord($inbuf[4])."|".ord($inbuf[5])."|".ord($inbuf[6]));
//hier werden Werte angezeigt; in $inbuf 1..4 stehen dann die Werte, wie oben schon beschrieben.
//return ($inbuf[1]);
}
else
return 255; //error
Hat keiner eine Idee?
Im Grunde genommen kopiere ich nur ein Speicherabbild von einer Steuerung in eine andere. Da ja offensichtlich auch der Typ „float“ bei beiden Steuerungn gleich ist, sollte man das Speicherabbild von Steuerung 1 in Steuerung 2 schieben können. Der Wert, der dann angezeigt werden sollte, sollte bei beiden wieder gleich sein.
Letzten Endes könnte ich mir einen Speicherbereich aus Steuerung 1 reservieren, dann den Float mit sprintf reinschreiben, dann diese Bytes übertragen und mittels einer PHP Funktion wieder in ein „float“ umwandeln. Da ich aber aus verschiedenen Steuerungen diverse Werte holen will, wäre mir ein Kopieren des Speicherabbildes (jeweils ein Wert) lieber. Wenn ich ein Byte aus Steuerung 1 hole und dann in Steuerung 2 ablege, geht das ja auch. Mit Integer wirds es dann schon kniffliger, da zu beachten ist, welches Byte low und welches high ist. Aber man kann es schon zusammenbauen mittels $wert= $inbuf[1]*256 + $inbuf[2].
Ich versuch’s mit „pack“, aber nochmal zur Erklärung.
Jedes „float“ wird normalerweise in 4 Bytes abgespeichtert. Anzusprechen ist der Wert dann immer mit „$wert“. Dahinter verbergen sich aber 4 Bytes. In Steuerung 2 (IPS) hat man auch einen Wert „$wert2“. Dieser hat intern auch 4 Bytes. Wenn man nun die 4 Bytes nimmt und in die neue Steuerung überträgt, dann sollte man unter „$wert2“ auch wieder den gleichen Wert haben.
Einige Zeilen nach unten ist Funktion „function bin2float ($bin)“ zu finden.
Möglicherweise gibt es eine einfachere Funktion, aber ich habe schon alles mögliche probiert (inkl. Eurer Tipps)
Hier nochmal die Anzeige, in Delphi programmiert.
Rausgekommen ist: 19,9598770141602
In der Steuerung wird die Temperatur gelesen, die ich dann ab und zu in IPS einlesen will.
Mit der besagten Formel scheint es erst mal zu gehen, bei Werten um die 20°C. Im Moment werden 17 °C angezeigt.
Das passt ja mit der Aussentemperatur zusammen. Andere Werte habe ich noch nicht. Mal sehen, wenn es kälter wird.
Wenn man die float Variable im PHP direkt beschreiben könnte (jedes Byte einzeln), dann wäre das Problem gelöst. Ich denke, dass dies auch in C geht, aber in Delphi habe ich mehr Erfahrung.
Hier die Funktion nochmals, die ich zum Test geschrieben habe.
procedure TForm7.FormShow(Sender: TObject);
var
f1 : single;
a : array[1…4] of byte absolute f1;
inbuf : array[1…4] of byte;
begin
//die Werte kommen schon von meiner Übertragungsroutine
inbuf[1]:=65;
inbuf[2]:=159;
inbuf[3]:=173;
inbuf[4]:=212;
Das Skript führt mit den von Dir angegebenen Werten zum selben Ergebnis: 19.95987701416
Völlig ohne Rechenaufwand ginge es, wenn man wie in C oder Delphi zwei Variablen im Speicher übereinander legen könnte. Aber eine solche Möglichkeit ist mir in PHP nicht bekannt.
Du hast Recht, es funktioniert mit der unpack-Funktion einwandfrei.
Ich bin darüber allerdings ziemlich überrascht, da PHP im Manual den Eindruck erweckt, dass es gar keine 32bit Float-Werte (single) kennt, sondern nur 64bit (double).
Aber das ist nicht der einzige Punkt, wo das Manual bisweilen ungenau oder gar widersprüchlich ist. :o
Auf jeden Fall ist die Lösung sehr elegant.
Kennst Du vielleicht eine Möglichkeit, wie man mit Adressen und Zeigern das von zeras verwendete „absolute“-Verfahren von Delphi nachbilden kann?
wie schon HJH berichtet, geht es, nur habe ich Probleme mit der automatischen Typkonvertierung. Für mich als Delphiprogrammierer ist das ein Riesennachteil bei PHP. Wenn es in Delphi nicht paßt, dann kommt eine Fehlermeldung, bei PHP wird irgendwas gerechnet. Es muss aber nicht immer passen.
Danke trotzdem für die Tipps. Jetzt kann ich sehen, wie sich die Aussentemperatur verhält.
Mir hat das wissen um diese Funktion ein ruhiges Gefühl gegeben in PHP. Die Variable ist zwar immernoch „unisex“ aber sie wird intern als float zwangs-betitelt.
Das ist zwar auch nicht Idiotensicher, aber wenn man sauber programmiert kann es einem nicht passieren, dass man versehendlich den falschen Typ am Wickel hat.