Vai al contenuto
PLC Forum

Partecipa anche tu alla Live su Youtube martedì 28/01/2025 per festeggiare i 24 anni di PLC Forum

Per ulteriori informazioni leggi questa discussione: https://www.plcforum.it/f/topic/326513-28012025




Ret_val In Formato String - Perche' db.stringa non acquisisce RET_VAL ?


Messaggi consigliati

Inserito: (modificato)

...Premetto che ho gia usato la funzione cerca...

Ciao a tutto il forum,

Vorrei riscrivermi la funzione Real to String, ma non avendo nessuna esperienza coi puntatori

mi sono subito arenato :unsure:

Il codice che ho scritto (per il momento) e' tutto qui sotto (ovviamente chiamato da OB1)

ma con tabella variabili "alla mano" ho gia' visto che la DB120.DBB0..100 (area del

SEND_DATA.InputString) non viene aggiornato col valore di RET_VAL.

-------------------------FC1--------------------------

CALL FC 32

Value :=MD130 <--valore real da convertire

RET_VAL:="SEND_DATA".InputString <--P#DB120.DBX0.0

---------------------------------------------------------

-------------------------FC32--------------------------

L P##RET_VAL <---di tipo string[254]

LAR1

L 'S' <-- Vorrei scrivere il carattere "S" sul primo carattere utile di RET_VAL

T B [AR1,P#2.0]

---------------------------------------------------------

C'e' qualcuno che mi puo' dire perche' SEND_DATA.InputString non viene aggiornato col

valore di RET_VAL?

Grazie anticipatamente per le risposte che mi darete.

Over.

Modificato: da over
  • 4 weeks later...

Matteo Montanari
Inserita: (modificato)

dichiari di voler "scrivere" una funzione Real to String, nè esiste già una fatta nelle librerie Siemens (FC 30 R_STRNG nella libreria "IEC Function Blocks").

comunque per risolvere il problema che hai posto:

      L     P##RET_VAL  
      LAR1  
      L     W [AR1,P#0.0]    
      T     #w_db_nr                     // appoggio per puntare il blocco dati "puntato"
      AUF   DB [#w_db_nr]
      L     D [AR1,P#2.0]   
      LAR1  
      LAR2                              
//;
      L     'S'                        
      T     B [AR2,P#2.0]

Il codice risulta essere questo.

in Siemens i primi due caratteri sono utilizzati dal sistema. (quindi la prima Word)

il carattere "S" viene visualizzato in DB120.DBB2, il primo carattere disponibile.

Modificato: da keosmm
Inserita:
dichiari di voler "scrivere" una funzione Real to String

...no B)

...piuttosto di voler ri-scrivermi :D la funzione real to string

nè esiste già una fatta nelle librerie Siemens (FC 30 R_STRNG nella libreria "IEC Function Blocks").

si e' vero, ma non mi garba il formato che ottengo da questa stringa, e' per questo che la voglio riscrivere.

Comunque intanto grazie 1000 dello snippet; oggi pomeriggio lo esamino meglio.

Ciao e grazie.

Matteo Montanari
Inserita:

dunque, se ti interessa il codice della funzione FC 30 R_STRNG nella libreria "IEC Function Blocks" potresti vedere qui sotto:

FUNCTION FC 30
TITLE = Real to String
STANDARD
VERSION : 0.0


VAR_INPUT
  IN : REAL;    // REAL
END_VAR
VAR_TEMP
  l_Exp_10 : DINT;    // 10er Exponent
  d_Temp : DWORD;    // Zwischenspeicher
  l_Mantis : DINT;    // Mantisse als DINT
  l_Man_High : DINT;    // High-Teil Mantisse > 9.999.999
  l_BCD_Hi : DINT;    // High-Teil Mantisse BCD
  l_BCD_Lo : DINT;    // Low-Teil Mantisse BCD
  w_db_nr : WORD;    
  y_LoopCnt : BYTE;    // Schleifenzähler
  b_Sign : BOOL;    // Vorzeichen IN 0=neg., 1=pos.
  b_Sign_Exp : BOOL;    // Vorzeichen Exponent
  b_Fehl1 : BOOL;    // Fehlermerker eingerichter String zu kurz
  b_q_NaN : BOOL;    // Fehlermerker IN kein REAL
  b_Null : BOOL;    // Merker IN = 0.0

  RET_VAL  : STRING [254]
END_VAR
BEGIN
NETWORK
TITLE =
// Voreinstellungen
      SET  ; 
      SAVE ; // BIE := 1
      S     #b_Sign; 
      S     #b_Sign_Exp; // Vorzeichen '+'
      R     #b_Null; // Fehlermerker rücksetzen
      R     #b_q_NaN; 
      L     L#0; 
      T     #l_BCD_Hi; // Merker BCD löschen
      T     #l_BCD_Lo; 
      T     #l_Exp_10; // Exponent löschen
// Pointer auf IN

      L     P##RET_VAL; //STRING zeiger (db_nr)
      LAR1 ; 
      L     W [AR1,P#0.0]; //db_nr laden
      T     #w_db_nr; 
      AUF   DB [#w_db_nr]; 
      L     D [AR1,P#2.0]; //STRING offset im db
      LAR1 ; 
      LAR2 ; // Adressreister 1/2 auf Anfang String
// Pruefung ob Ziel lang genug eingerichtet, Minimum 14 Bytes

      L     B [AR1,P#0.0]; //res. Länge im DB
      L     14; // kleiner als 14 Byte
      <I   ; // ja, dann Fehler
      =     #b_Fehl1; 
      SPB   FEHL; //int string > ges. string

// Pruefung ob IN eine Gleitpunktzahl

      L     #IN; // IN + 0.0
      SLD   1; // Vorzeichen schieben
      U     ==0; // IN positiv
      =     #b_Sign; // Sign:= 1;
      SRD   1; // IN zurückschieben -> damit ist
      L     0.000000e+000; // IN die Betragszahl
      +R   ; // IN muss definiert sein als REAL
      U     UO; // Ergebnis liefert unordered? 
      S     #b_q_NaN; // Merker IN kein REAL
      SPB   FEHL; 
      U     ==0; // wenn IN = 0
      S     #b_Null; // wird ein Nullstring ausgegeben
      SPB   NWE2; 

// 1. Lösungsansatz: Exponent zur Basis 10 suchen
// Exp_10 = log IN/b; wobei b=Mantisse, wird mit 1 angenommen
// Log   a = Ln(a)/Ln(10)
//    10

      LN   ; // LN(IN);
      L     2.302585e+000; //ln (10)
      /R   ; 
      RND+ ; 
      T     #l_Exp_10; // Ergebnis ist Exponent zur Basis 10 als INT    
      L     0; 
      +D   ; 
      U     >=0; 
      =     #b_Sign_Exp; // Merker Vorzeichen Exponent
      SPB   Wert; 
      NEGD ; 
      T     #l_Exp_10; 
Wert: T     #l_Exp_10; // Betrag von Exp_10

// Nachbildung von 10^x; x steht im LB3 (Temp);
      L     1.000000e+000; 
      UN    L      3.0; 
      SPB   E02; 
      L     1.000000e+001; 
      *R   ; 
E02:  UN    L      3.1; 
      SPB   E04; 
      L     1.000000e+002; 
      *R   ; 
E04:  UN    L      3.2; 
      SPB   E08; 
      L     1.000000e+004; 
      *R   ; 
E08:  UN    L      3.3; 
      SPB   E016; 
      L     1.000000e+008; 
      *R   ; 
E016: UN    L      3.4; 
      SPB   E032; 
      L     1.000000e+016; 
      *R   ; 
E032: UN    L      3.5; 
      SPB   FERT; 
      L     1.000000e+032; 
      *R   ; 

//    2. Lösungsansatz: Mantisse mit Exp_10 berechnen.
//    Mantisse = IN/10^EXP_10, mit 10^x aus obiger Nachbildung

FERT: L     #IN; // Eingangswert IN / 10^x * 10^7
      TAK  ; 
      UN    #b_Sign_Exp; // wenn Sign_Exp negativ
      SPB   Mul; // dann IN*10^x
      /R   ; // sonst IN/10^x
      SPA   Weit; 
Mul:  *R   ; 
Weit: L     1.000000e+007; // Kommastellen REAL schieben nach rechts
      *R   ; 
      RND  ; // Mantisse als Int.
      T     #l_Mantis; 

NETWORK
TITLE =
// BCD wandel in String und kopieren
NWE2: U     #b_Null; 
      SPB   ZERO; 
      L     L#10000000; // Mantisse / 10000000 -> 
      /D   ; 
      T     #l_Man_High; // liefert Stellen > 9.999.999
      DTB  ; 
      T     #l_BCD_Hi; // BCD-Wert der Mantisse High
      L     #l_Man_High; 
      L     L#10000000; // High_Mantisse * 10000000 - Mantisse
      *D   ; // = Mantisse <=9.999.999
      L     #l_Mantis; 
      TAK  ; 
      -D   ; 
      DTB  ; // Mantisse Low -> BCD
      T     #l_BCD_Lo; 

// Wandlung Mantisse High in String

ZERO: L     #l_BCD_Hi; // Mantisse High hat nur eine Stelle
      OD    DW#16#30; // 1. Stelle mit 30h verodern -> BCD to ASCII
      T     B [AR1,P#3.0]; // kopiere in String an 3.Stelle
      SPA   SCHL; 

// Wandlung Mantisse Low in String und Übertragung in String, es wird mit
// der kleinsten Stelle der Mantisse begonnen

SCHL: +AR1  P#11.0; 
      L     7; // Schleifenzähler := 7 Zeichen= Nachkommastellen
LOP:  T     #y_LoopCnt; 
      L     #l_BCD_Lo; 
      UD    DW#16#F; // eine Tetrade einblenden
      OD    DW#16#30; // mit 30h. verodert -> BCD to ASCII
      T     B [AR1,P#0.0]; // in String ablegen
      L     #l_BCD_Lo; 
      SRD   4; // nächste Tetrade rechtsbündig    
      T     #l_BCD_Lo; 
      L     -8; // AR1 - 1 Bytestelle
      +AR1 ; 
      L     #y_LoopCnt; 
      LOOP  LOP; // im String steht: -x-xxxxxxx----

// feste Stellen in String eintragen

// Vorzeichen Mantisse eintragen

      U     #b_Sign; // wenn Vorzeichen +
      L     '+'; // dann ASCII + für Mantisse
      SPB   SIG; 
      L     '-'; // sonst -
SIG:  T     B [AR2,P#2.0]; 

// Dezimalpunkt

      L     '.'; // Dezimalpunkt nach erster Stelle
      T     B [AR2,P#4.0]; 

// Zeichen Exponent 'E'

      L     'E'; // ASCII E für Exp.
      T     B [AR2,P#12.0]; 

// Vorzeichen Exponent übergeben

      U     #b_Sign_Exp; // wenn Vorzeichen +
      L     '+'; // dann ASCII + für Mantisse
      SPB   ***P; 
      L     '-'; // sonst -
***P: T     B [AR2,P#13.0]; 

// Exponent eintragen

      L     #l_Exp_10; // Exponent -> BCD
      ITB  ; 
      PUSH ; // A1 -> A2
      SLW   4; // A1 um eine Tetrade verschieben
      OW   ; // -> -x-x, schafft je um eine Tetrade Platz
      UW    W#16#F0F; 
      OW    W#16#3030; // BCD -> ASCII
      T     W [AR2,P#14.0]; // in String
      L     14; 
      T     B [AR2,P#1.0]; // Anzahl Bytes := 14
      SPA   ENDE; 
FEHL: CLR  ; // ja, dann BIE:=0
      SAVE ; 
ENDE: BE   ; 
END_FUNCTION

chiaramente devi sistemarlo un pochino se incontri degli errori...

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...