Forum: Mikrocontroller und Digitale Elektronik CAPL Float Anzeige Problem


von Michl M. (michemache)


Angehängte Dateien:

Lesenswert?

Hallo,

ich bin im Moment am rätseln (es rächt sich im Moment das nicht 
vorhandene Informatik - Studium - ich glaube ich hab einfach einen 
Denkfehler bei der Anzeige von Float) über die Anzeige von Float einmal 
als Kommazahl und der Dezimalrepräsentation (was immer das ist, aber ich 
bin bei meiner Suche darüber gestolpert und versuche zu verstehen wo 
hier der Denkfehler liegt) Da ich aber schon länger darüber fast 
verzweifle frage ich einfach mal die Experten, da ich gesehen habe, daß 
hier auch CAPL - Fragen kompetent beantwortet werden.

Zu meinem Problem :

Ich habe hier eine ECU, die mir Sensorwerte als 4Byte Float IEEE754 
ausgibt. Da CAPL 8Byte - Float verwendet und ich leider nicht über eine 
Datenbasis auf den Wert zugreifen kann, da dies im Code - Teil "on 
Message *" nicht funktioniert, habe ich die Umrechnung manuell 
durchgeführt, was auch klappt. Der Code sieht so aus :
1
//#################################################################################################     
2
            
3
4
    qword   Var_Temp_Hex;
5
    qword   Var_Temp;
6
    
7
    float   Var;
8
  
9
    qword   Vorzeichen; 
10
    qword   Exponent;   
11
    qword   Mantisse;   
12
13
14
15
16
              Var_Temp_Hex          =             ((this.Byte(4)                      // 4 Byte IEEE754 
17
                                                 + (this.Byte(3) << 8)
18
                                                 + (this.Byte(2) << 16)
19
                                                 + (this.Byte(1) << 24))); 
20
            
21
              write("Var_Temp_Hex = %llx", Var_Temp_Hex);
22
            
23
              Mantisse = ((Var_Temp_Hex & 0xFFFFFF) - 0x800000);          
24
                                                                          //  Abspaltung des Nachkommateils -> 24 bit und "normierung" durch abtrennen des ersten Bits             
25
              Mantisse = (Mantisse << 29) ;                               // auffüllen der restlichen Stellen (52bit)   
26
27
                                                                          
28
                       
29
              Exponent = ((Var_Temp_Hex & 0xFFF00000) >> 23);             
30
              
31
              Exponent = (Exponent - 0x7F) & 0xFF;                        // Exponent = Exponent - 127 (Bias) & maskieren
32
              
33
                                                                                                
34
              Vorzeichen = (Var_Temp_Hex >> 31) & 0x1;              
35
                                                                          
36
            
37
              Var_Temp = (Mantisse + (Vorzeichen << 63) + ((Exponent + 0x3FF) << 52)) &0xFFFFFFFFFFFFFFFFLL  ; // 8 Byte IEEE754 
38
            
39
              write("Var_Temp = %f    %llx", Var_Temp, Var_Temp);
40
41
            
42
              Var = (float) Var_Temp; 
43
44
              write("Var = %f    %llx", Var, Var);
45
            
46
47
              @sysvar::Main_Panel_XCP_Read::Variable_Answer_Float[@sysvar::Main_Panel_XCP_Read::Receive_Step] =  Var; // (float) Var_Temp; 
48
         
49
 
50
        write("@sysvar::Main_Panel_XCP_Read::Variable_Answer_Float[%i] = %f",@sysvar::Main_Panel_XCP_Read::Receive_Step,@sysvar::Main_Panel_XCP_Read::Variable_Answer_Float[@sysvar::Main_Panel_XCP_Read::Receive_Step]);    
51
        
52
            
53
//##################################################################################################


Die Antwort im Write - Fenster sieht folgendermaßen aus :

Var_Temp_Hex = 42e6851f
Var_Temp = 115.260002    405cd0a3e0000000
Var = 4637811118541111300.000000    43d0173428f80000
@sysvar::Main_Panel_XCP_Read::Variable_Answer_Float[0] = 
4637811118541111300.000000




Ich glaube ich habe hier irgendeinen Denkfehler. Was ich erwarten würde, 
wäre die Anzeige von "115.260002", was dem Wert der Sensoren entspricht 
und auch der formatierten Anzeige
von "Var_Temp" im Write - Fenster und nicht 
"4637811118541111300.000000".

Wieso bekomme ich eben diese "4637811118541111300.000000" als Float - 
Wert und nicht "115.260002", wie in der "Var_Temp" ja doch richtig mit 
dem Format - String "%f" angezeigt wird ?
Und wieso wird in der Variablen "Var" für den Wert 
""4637811118541111300.000000" plötzlich der Hex - Wert 
"43d0173428f80000" ausgegeben ? (Diesem Dezimalwert müsste doch 
"405cd0a3e0000000" entsprechen)

Ich hoffe ich habe es nicht zu verwirrend wiedergegeben (bin ich im 
Moment wirklich ^^ ) und danke euch schon mal im Voraus !

: Verschoben durch User
von Michl M. (michemache)


Lesenswert?

Hat niemand eine Antwort oder ist das Problem so uninteressant ? O_o

von Peter (Gast)


Lesenswert?

Hallo,

unabhängig von der manuellen Umrechnung der Werte -

hast du schon ein typecast der message objects probiert ?

Ich weiß, dass man generische Msg-Objekte auf definierte Botschaften 
casten kann, um die richtigen Signale zu lesen / zu schreiben. Das 
sollte doch auch hier möglich sein ?!


((message 0x123) AMessage).Signal = 1234;
oder
A = ((message 0x123) AMessage).Signal;

Gruß

von Michl M. (michemache)


Lesenswert?

Hallo Peter,

bisher noch nicht, diese Methode war mir unbekannt. Ich dachte im Teil 
"on message *" kann ich nicht auf Signale zugreifen, ich hab doch 
geahnt, daß es irgendwie doch möglich sein sollte. Die Vector - Hilfe 
ist hier leider immer wieder sehr lückenhaft was die Fähigkeit der 
eigenen Produkte angeht %)

Ich hab Deinen Vorschlag mal eben getestet :


-> implizieter Typecast :
1
double Var
2
3
Var = ((message 0x626)XCP_Receive).Four_Byte_XCP_Answer_Float;

Das Signal ist definiert als Wertetyp "IEEE Float".
Als Signallänge habe ich das Signal 32bit lang definiert.

Leider bekomme ich als Fehlermeldung "invalid type cast", ebenso als 
expliziten Type - Cast :

-> explizieter Typecast :
1
double Var
2
3
Var = (double) ((message 0x626)XCP_Receive).Four_Byte_XCP_Answer_Float;

Die Methode an sich wäre schon gut, wenn ich jetzt noch die Syntax 
hinbekommen könnte...


Peter schrieb:
> Hallo,
>
> unabhängig von der manuellen Umrechnung der Werte -
>
> hast du schon ein typecast der message objects probiert ?
>
> Ich weiß, dass man generische Msg-Objekte auf definierte Botschaften
> casten kann, um die richtigen Signale zu lesen / zu schreiben. Das
> sollte doch auch hier möglich sein ?!
>
>
> ((message 0x123) AMessage).Signal = 1234;
> oder
> A = ((message 0x123) AMessage).Signal;
>
> Gruß

von Michl M. (michemache)


Lesenswert?

#solved

hab´s jetzt per memcpy in eine Struktur mit 8Byte Double gelöst und 
jetzt bleibt mir auch der originale Hex - Wert der Variablen "qword" 
erhalten. Sieht folgendermaßen aus :
1
    qword   Var_Temp_Hex;
2
    qword   Var_Temp;
3
  
4
    qword   Vorzeichen; 
5
    qword   Exponent;   
6
    qword   Mantisse;   
7
  
8
    Struct Wrap_IEEE_4Byte_To_Double
9
    {
10
          dword IEEE_4Byte;
11
          double IEEE_8Byte;
12
    }IEEE_Wrapper;
13
    
14
    byte IEEE_8Byte_Raw[8];
15
16
17
              Var_Temp_Hex          =             ((this.Byte(4)                      
18
                                                 + (this.Byte(3) << 8)
19
                                                 + (this.Byte(2) << 16)
20
                                                 + (this.Byte(1) << 24))); 
21
            
22
              write("Var_Temp_Hex = %llx", Var_Temp_Hex);
23
   
24
              Mantisse = ((Var_Temp_Hex & 0xFFFFFF) - 0x800000);          //  http://ti.dev.geekbetrieb.de/   // Umwandlung von Dezimal nach Double IEEE 754
25
                                                                          //  Abspaltung des Nachkommateils -> 24 bit und "normierung" durch abtrennen des ersten Bits             
26
              Mantisse = (Mantisse << 29) ;                               // auffüllen der restlichen Stellen (52bit)   
27
28
                                                                          // write("Mantisse = %llx    %llu", Mantisse, Mantisse);
29
                       
30
              Exponent = ((Var_Temp_Hex & 0xFFF00000) >> 23);             // http://board.gulli.com/thread/1470012-umrechnung-von-hexadez-in-ieee754/
31
              
32
              Exponent = (Exponent - 0x7F) & 0xFF;                        // Exponent = Exponent - 127 (Bias) & maskieren
33
              
34
                                                                          // write("Exponent = %i", Exponent);                       
35
              Vorzeichen = (Var_Temp_Hex >> 31) & 0x1;              
36
                                                                          // write("Vorzeichen = %i", Vorzeichen);
37
            
38
              Var_Temp = (Mantisse + (Vorzeichen << 63) + ((Exponent + 0x3FF) << 52)) &0xFFFFFFFFFFFFFFFFLL  ; 
39
   
40
              // write("Var_Temp = %f    %llx    %llu", Var_Temp, Var_Temp, Var_Temp);
41
42
            
43
              j = 0; 
44
            
45
              for (i = 0; i<= 7; i++)    
46
              {
47
                  IEEE_8Byte_Raw[i] = ((Var_Temp >> j )& 0xFF) ;
48
                  j = j + 8;                
49
                  // write("IEEE_8Byte_Raw[%i] = %x", i, IEEE_8Byte_Raw[i]); 
50
              }  
51
            
52
              memcpy_off(IEEE_Wrapper, 8, IEEE_8Byte_Raw, 0, 8); // IEEE_Wrapper.IEEE_8Byte
53
            
54
            
55
              @sysvar::Main_Panel_XCP_Read::Variable_Answer_Float[@sysvar::Main_Panel_XCP_Read::Receive_Step] = IEEE_Wrapper.IEEE_8Byte;
Michl M. schrieb:
> Hallo Peter,
>
> bisher noch nicht, diese Methode war mir unbekannt. Ich dachte im Teil
> "on message *" kann ich nicht auf Signale zugreifen, ich hab doch
> geahnt, daß es irgendwie doch möglich sein sollte. Die Vector - Hilfe
> ist hier leider immer wieder sehr lückenhaft was die Fähigkeit der
> eigenen Produkte angeht %)
>
> Ich hab Deinen Vorschlag mal eben getestet :
>
>
> -> implizieter Typecast :
>
>
1
> 
2
> double Var
3
> 
4
> Var = ((message 0x626)XCP_Receive).Four_Byte_XCP_Answer_Float;
5
> 
6
>
>
> Das Signal ist definiert als Wertetyp "IEEE Float".
> Als Signallänge habe ich das Signal 32bit lang definiert.
>
> Leider bekomme ich als Fehlermeldung "invalid type cast", ebenso als
> expliziten Type - Cast :
>
> -> explizieter Typecast :
>
>
1
> 
2
> double Var
3
> 
4
> Var = (double) ((message 0x626)XCP_Receive).Four_Byte_XCP_Answer_Float;
5
> 
6
>
>
> Die Methode an sich wäre schon gut, wenn ich jetzt noch die Syntax
> hinbekommen könnte...
>
>
> Peter schrieb:
>> Hallo,
>>
>> unabhängig von der manuellen Umrechnung der Werte -
>>
>> hast du schon ein typecast der message objects probiert ?
>>
>> Ich weiß, dass man generische Msg-Objekte auf definierte Botschaften
>> casten kann, um die richtigen Signale zu lesen / zu schreiben. Das
>> sollte doch auch hier möglich sein ?!
>>
>>
>> ((message 0x123) AMessage).Signal = 1234;
>> oder
>> A = ((message 0x123) AMessage).Signal;
>>
>> Gruß

von Peter (Gast)


Angehängte Dateien:

Lesenswert?

Hi Michl,

hab jetzt mal fix eine CANoe-Config zusammengeklickt:

DBC mit einer Botschaft, mit einem 32bit float SIgnal
Capl-Knoten mit on message *
IG mit Sinus

on message *
{
  float test =0;
  test = ((message 0x10)this).TestFloat;
  write ("value was: %f",test);
}

Screenshot der Ausgabe
Sicherlich ist bei "on message" noch der Identifier abzuprüfen

Apropos: Warum on message *, nicht on message Identifier ?

von Michl M. (michemache)


Lesenswert?

Hallo Peter,

danke für die Antwort und sorry für die späte, war etwas länger afk ^^

Deine Methode sieht auch sehr gut aus, werd ich mal testen wenn ich das 
Programm vom "quick and dirty" zu einem guten Zwischenstand verändere.

on message *
{
  float test =0;
  test = ((message 0x10)this).TestFloat;
  write ("value was: %f",test);
}

Und zu Deiner Frage, warum "on message *" und nicht der direkte 
Identifier : ich bastel mir einen XCP - Kommunikations - Nachbau im 
CANalyzer (davon haben wir viele hier - aber nur 1 CANape).
Und da die Projekte sich in Zukunft nicht auf einen Kunden beschränken 
werden die Addressen sich natürlich ändern, können damit in einer GUI 
frei eingegeben werden.
Damit fange ich die richtige ID aber schon darunter mit
"if (this.ID == @sysvar::Main_Panel_XCP_Read::XCP_Receive_ID)" ab.




btw. die Vector - Antwort zum Problem war (heute erst erhalten) :

Die Bytes bekommt man in einen double in CANoe V8.0 nur mit einem etwas 
umständlichen Trick:



1) in der DBC eine Dummy-CAN-Botschaft anlegen (convertmsg) mit DLC 8 
Bytes

2) auf diese Botschaft ein Dummy-Signal legen (doublesig) mit Wertetyp 
IEEE double

3) in CAPL eine Variable vom Botschaftstyp anlegen, darauf die Bytes 
schreiben und das Signal lesen:



message convertmsg msg;

msg.qword(0) = q;

d = msg.doublesig;



Seit CANoe V8.5 gibt es auch eine direkte CAPL-Funktion dafür:

d = interpretAsDouble(q);



Und ab V8.5 SP4 kann man auch ein Byte-Array als double auslesen:

byte bytes[8];

d = bytes.double(0);

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.