LREAL umwandeln in double

chefsalat-

Mitglied
Hallo zusammen,
fogende Ausganssituation:
Ich muss ein Programm in C++ schreiben, mit dem ich Werte aus einer Beckhoff-SPS (mitTwincat programmiert) ereignisgesteuert auslesen soll.

Das Beckhoff-Programm steht schon. In meinem C++ Programm kann ich DINT und REAL-Werte schon auslesen.
Nur mit LREAL-Werten habe ich noch massive Probleme.

Die Test-Callback-Funktion soll erst mal nix anderes machen, als den Wert, den sie über pNotification->data übergeben bekommt, umzuwandeln und in einem CString abzuspeichern.

Meine Callback-Funktion für int (DINT) sieht folgendermaßen aus:
C++:
void fn_Callback(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser) {
    CString sWert = "";
    sWert.Format("%d", *(ULONG *)pNotification->data);
}

Für Float (REAL) nehme ich diese Umwandlung:
C++:
sWert.Format("%f", *(float *)pNotification->data);

Das klappt dann auch wunderbar.

Nur für double (LREAL) gibt es mir immer 0.0000... aus.
C++:
sWert.Format("%f", *(double *)pNotification->data);

Und eigentlich passt das mit double ja schon, weil ich beim Schreiben von LREAL-Werten in die SPS ja auch double verwende.

Hat jemand einen Vorschlag, wie ich das Problem beheben kann?

Gruß chefsalat-
 
Hi,

was für ein Wert steht denn in pNotification->data, wenn du ihn gelesen hast? Mein Vorschlag wäre, eine Variable temporär zu definieren und sie dann im Debugger zu kontrollieren.
Code:
double test;
test=*(double *)pNotification->data; 
sWert.Format("%f", *(double *)pNotification->data);
Ich vermute, dass etwas mit diesem Wert nicht stimmt.

Mfg

langer
 
Laut Beckhoff Information System sieht das Ding so aus:
C++:
typedef struct {
  ULONG           hNotification;
  __int64         nTimeStamp;
  ULONG           cbSampleSize;
  UCHAR           data[ANYSIZE_ARRAY];
} AdsNotificationHeader, *PAdsNotificationHeader;


Wie du dem Screenshot entnehmen kannst, steht in pNotification->data "" drin...


Wenn ich int auslese, steht in pNotification->data der Wert drin.
Bei float steht in pNotification->data wieder "" drin. Allerdings kommt nach der Umwandlung der richtige Wert raus.


Ich werd daraus einfach nicht schlau...

Gruß chefsalat-
 

Anhänge

  • pNotification-data.JPG
    pNotification-data.JPG
    96,2 KB · Aufrufe: 61
Hallo,

also hätten wir erstmal einen Ansatzpunkt. Hast du mal eine temporäre Variable genutzt wie vorgeschlagen? Was steht da drin? Leider kenne ich mich mit diesem Beckhoff überhaupt nicht aus (nie gehört vorher) und kann deshalb auch nicht beurteilen, was der Typ LREAL repräsentiert.

Mfg

langer
 
Morgen,
also ich hab das mit der temporären Variable mittlerweile probiert. Hab es erst gar nicht kapiert, was du meinst, aber dann den Code gesehn :)

C++:
double test;
test = *(double *) pNotification->data;  //test = -2.5302632229820895e-098

double test;
test = *(float *) pNotification->data;   //test = 0.00000000000000000

float test;
test = *(float *) pNotification->data;   //test = 0.000000

Also ich weiß ja nicht, aber ich denke, dass das Beckhoff TwinCat n Problem mit den LREAL = double Werten hat.
Mit REAL = float und DINT = int funktioniert es ja tadellos.
Das andere komische ist, die Callback-Funktion bei den LREAL's wird nur ein einziges Mal aufgerufen. Irgendwie reagiert er da dann auf keine Änderung mehr.

Bei REAL und DINT werden die Callback-Funktionen, wie gewünscht, bei jeder Änderung des Wertes aufgerufen.

Gruß chefsalat-
 
Hallo,

hab mal was ausprobiert:
Code:
	// So wie ich das sehe bekommst du die Werte in einem CHAR-Array:
	// Der ungefähr so aussehen könnte:

	UCHAR data[5/*ANYSIZE_ARRAY*/];

	data[0] = '1';
	data[1] = '2';
	data[2] = '.';
	data[3] = '2';
	data[4] = '\0';

	// mit unten stehenden Anweisungen bekommst du nur den Zeiger auf das Array, 
	// nicht die Daten!
	int nTest;
    nTest = *(int *) /*pNotification->*/data;  //test = -2.5302632229820895e-098
							// nTest == Zeiger auf das data-Array
    double dTest;
    dTest = *(double *) /*pNotification->*/data;   //test = 0.00000000000000000
							// dTest == Zeiger auf das data-Array
    float fTest;
    fTest = *(float *) /*pNotification->*/data;   //test = 0.000000
							// dTest == Zeiger auf das data-Array
 

	// Hier ein kleines Beispiel wie du die richtigen Werte bekommen könntest:
	//TEST
	CString testDataStr;
	testDataStr.Format("%s",(char*)data);

	CString strForKommaZahlen, strNachKommaZahlen;

	int nDataLen = strlen((char*)data);
	int i;
	float f=1;
	
	bool bKommaDa = false;
	for (i=0; i<nDataLen; i++)
	{
		if (bKommaDa == false)
		{
			if (data[i] != '.')//bzw ',')
			{
                strForKommaZahlen += data[i];
			}
			else
			{
				bKommaDa = true;
			}
		}
		else
		{
             strNachKommaZahlen += data[i];
			 f*=10;
		}
	}
	   
	nTest = StrToInt(strForKommaZahlen); // = 12
	dTest = nTest + ((float)(StrToInt(strNachKommaZahlen))/f); // = 12.1999999....

PS. Ist vielleicht nicht die schönste Lösung,
aber ich hoffe ich könnte dir helfen

Gruß

titanic
 
Hmm, sieht mal nicht schlecht aus. Werds nach der Mittagspause ausprobieren und melde mich dann wieder.
Danke!!

Gruß chefsalat-
 
Also ich habs mal getestet und bekomme schon in "testDataStr" nur ""
Die Länge ist demnach auch 0.

So langsam beschleicht mich echt das ungute Gefühl, dass Beckhoff's TwinCAT da Mist baut.

Gruß chefsalat-
 

Anhänge

  • Ads ereignisgesteuertes lesen.JPG
    Ads ereignisgesteuertes lesen.JPG
    91,3 KB · Aufrufe: 39
Hallo chefsalat,

deine Callback-funktion ist glaube ich eine Klassenfunktion(static) deiner Dialogklasse,
die du glaube ich als protected deklariert hattest.
Vielleicht könnte es der Fehler sein?

Oder ich weiß nicht. Weißt du denn genau, ob da was gesendet wurde?

Gruß

titanic
 
Ja, stimmt. Die Callback-Funktion ist static und protected.
Aber das protected macht schon mal nix aus. Auch wenn es public ist, kommt nix an.
Das static sollte ich, glaube ich, schon dran lassen. Bei int's und float's funktioniert es ja auch.

Was mich eben am meisten stutzig macht, ist, dass die Callback-Funktion nur ein einziges mal aufgerufen wird, und dann nicht mehr. (Sie reagiert gar nicht auf Wertänderung im TwinCAT).
Die int- & float- Callback-Funktionen werden bei jeder Änderung mit den richtigen Werten wieder aufgerufen.

Ob TwinCAT die double-Callback-Funktionen wirklich aufruft und was sendet, weiß ich nicht. Ich hab leider auch keinen Plan, wie ich das herausfinden kann.

Gruß chefsalat-
 

Neue Beiträge

Zurück