# Word (hex) to 4x Char



## Andy082 (5 November 2009)

Abend.

Ein Kunde will in seinem Datamatrixcode als fortlaufende Nummer (wird am Tagesanfang zurückgesetzt) eine 4 stellige HEX-Zahl stehen haben.

Das Ganze sieht in etwa so aus....
xxxxxxxxxxxxxxxxxx2F03 (x steht für den restlichen Dateninhalt)

Bei jedem Druck eines Labels erhöhe ich dieses Word um B#16#01, also um eins.
Um das Ganze an meinen Labeldrucker übergeben zu können muss ich den Inhalt nun in Char's umspeichern.

C#1: '2'
C#2: 'F'
C#3: '0'
C#4: '3'

Das Ganze sieht in meinem Funktionsbaustein nun so aus:

```
SET   
      L     #Eingabe
      SLW   0
      SRW   12
      L     B#16#30
      +I    
      T     #C1
      L     B#16#3A
      <I    
      SPB   a001
      L     #C1
      L     B#16#7
      +I    
      T     #C1
a001: SET   
      L     #Eingabe
      SLW   4
      SRW   12
      L     B#16#30
      +I    
      T     #C2
      L     B#16#3A
      <I    
      SPB   a002
      L     #C2
      L     B#16#7
      +I    
      T     #C2
a002: SET   
      L     #Eingabe
      SLW   8
      SRW   12
      L     B#16#30
      +I    
      T     #C3
      L     B#16#3A
      <I    
      SPB   a003
      L     #C3
      L     B#16#7
      +I    
      T     #C3
a003: SET   
      L     #Eingabe
      SLW   12
      SRW   12
      L     B#16#30
      +I    
      T     #C4
      L     B#16#3A
      <I    
      SPB   a004
      L     #C4
      L     B#16#7
      +I    
      T     #C4
a004: SET
```
 
Die einen werden jetzt sagen, warum das hin- und herschieben und nicht ausmaskieren, andere sagen eventuell passt schon.
Was mir aber nicht ganz gefällt ist der Offset um einen Buchstaben, also A-F in einen Char umzuwandeln, auch wenn's funktioniert.

Hat jemand ne' andere Idee, denn ich lerne gerne dazu......


mfg,
Andy


----------



## MarkusP210 (5 November 2009)

Nun, nachdem S7-Steuerungen nicht gerade Meister in der Handhabung von Zeichen und Ketten davon sind (und nachdem ich vergeblich mit einigen Umwandlungsoperationen gespielt habe) würde ich folgende einfache Lösung in SCL wählen:

FUNCTION FC2 : VOID
VAR_TEMP
  // temporäre Variablen
  tmp_idx               :INT;
END_VAR

// Ausmaskieren und Zeichen bestimmen
FOR tmp_idx := 4 TO 1 BY -1 DO
  Test_DB.c[tmp_idx] := Test_DB.Zeichen[WORD_TO_INT(SHR(IN:=Test_DB.Eingabe,N:=4*(tmp_idx-1)) AND W#16#000F)];
END_FOR;

END_FUNCTION

Worin die Variable Test.xxx einem DB entstammen.

Markus


----------



## Andy082 (5 November 2009)

Ich hätte erwähnen sollen, dass ich's in AWL schreiben will.

Edit:
Mein SCL-Editor funktioniert nicht, weiß der Teufel warum.


----------



## forendiva (5 November 2009)

Andy082 schrieb:


> Edit:
> Mein SCL-Editor funktioniert nicht, weiß der Teufel warum.



Man hat mich gerufen? :evil:


----------



## Andy082 (5 November 2009)

lol....

Was war das Schlüsselwort....?
SCL-Editor oder Teufel.....


Lt. Info ist der SCL-Editor mit meiner Prof.Edition meines 5.4 mitinstalliert.
Auch die benötigte License is drauf und aktiv, aber ich hab nicht die Möglichkeit eine SCL-Quelle zu erstellen.


----------



## Ralle (5 November 2009)

Ich kann mich noch daran erinnern: http://www.sps-forum.de/showthread.php?t=10754&highlight=Sprungliste

Ist so ähnlich, ich habs damals mit Sprungleiste gemacht.


----------



## vierlagig (6 November 2009)

ich würde es mit hilfe einer linearen funktion machen 

y = m*x + n ... ihr erinnert euch?

einzig der böse sprung um die 40h stört, aber den kann man ja interpolieren 

also, wir nehmen an, die hexwerte 30-39 und 41-46 seien dezimal
damit bestimmen wir eine lineare funktion

x1 = 0
x2 = 15
y1 = 30
y2 = 46

-> m = 16/15; n = 30;

daraus folgt folgende wertetabelle:


```
X	Y
0	30
1	31,06666667
2	32,13333333
3	33,2
4	34,26666667
5	35,33333333
6	36,4
7	37,46666667
8	38,53333333
9	39,6
10	40,66666667
11	41,73333333
12	42,8
13	43,86666667
14	44,93333333
15	46
```

39,6 gerundet wäre 40 ... also müssen wir an der stelle "interpolieren" aber so, dass y(10) gerundet 41 ergibt ... also -0,11 sollte genügen

also ist die resultierende funktion *y ≈ 16/15 * x + 29,89*

ich hab das mit dem schieben mal so gelassen und die ganze funktionalität in eine schleife gepackt:


```
*
FUNCTION "word_to_char" : VOID
TITLE =
//this function realize the word_to_char exchange
//
//DATE:     06.11.2009
//AUTHOR:   4lagig
//VERSION:  V0.1 BasicVer
VERSION : 0.1


VAR_INPUT
  wIn : WORD ;	
END_VAR
VAR_OUTPUT
  C1 : CHAR ;	
  C2 : CHAR ;	
  C3 : CHAR ;	
  C4 : CHAR ;	
END_VAR
VAR_TEMP
  iLoopCounter : INT ;	
  aChar : ARRAY  [0 .. 3 ] OF BYTE ;	
END_VAR
BEGIN
NETWORK
TITLE =

      LAR1  P##aChar;            //start für zwischenspeicher

      L     4;                   //schleife initialisieren
next: T     #iLoopCounter; 
      L     -4;                  //links schieben
      *I    ;                    //errechnen
      +     16;                  //mit y=-4*x+16
      L     #wIn; 
      SLW   ; 
      SRW   12;                  //nibble maskieren
      DTR   ;                    //in real wandeln
      L     1.066667e+000;       //----------------------
      *R    ;                    //      16
      L     2.989000e+001;       // y = ---- * x + 29,89
      +R    ;                    //      15
      RND   ;                    //----------------------
      ITB   ;                    //gerundet als BCD
      T     B [AR1,P#0.0];       //in Byte speichern

      +AR1  P#1.0;               //pointer erhöhen
      L     #iLoopCounter; 
      LOOP  next;                //NEXT

//nach außen kopieren
      L     #aChar[0]; 
      T     #C1; 
      L     #aChar[1]; 
      T     #C2; 
      L     #aChar[2]; 
      T     #C3; 
      L     #aChar[3]; 
      T     #C4; 
     
      SET;
      SAVE;

END_FUNCTION
```

wenn du das ganze in einen FB packst, kannste dir die TempChars auch noch sparen ...


----------



## hovonlo (6 November 2009)

Ich kann einfach nur meinen Hut ziehen vor dieser doch sehr "anderen" Lösung der alten Hex->Asc Wandlungsaufgbe.

Klasse 4L!


----------



## vierlagig (6 November 2009)

hovonlo schrieb:


> Ich kann einfach nur meinen Hut ziehen vor dieser doch sehr "anderen" Lösung der alten Hex->Asc Wandlungsaufgbe.
> 
> Klasse 4L!



danke, nachtschicht machts möglich ...
ich hab mir die blöde ASCII-table angeguckt und so über das blöde @ geflucht ... das hätte ja wohl auch woanders platz gehabt


----------



## MarkusP210 (6 November 2009)

> Mein SCL-Editor funktioniert nicht, weiß der Teufel warum.



Must Du unbedingt ändern...

Markus


----------



## Andy082 (6 November 2009)

Danke für all die Vorschläge.

Da es sich bei mir aber nur um 4 Chars handelt, denke ich, dass ich's bei meiner kleinen AWL-Funktion belassen werde.

mfg,
Andy


----------



## vierlagig (7 November 2009)

Andy082 schrieb:


> Danke für all die Vorschläge.
> 
> Da es sich bei mir aber nur um 4 Chars handelt, denke ich, dass ich's bei meiner kleinen AWL-Funktion belassen werde.
> 
> ...



warum fragst du dann? oO


----------



## Andy082 (7 November 2009)

Na, da ich dachte man könnte meine Funktion in AWL noch einfacher gestalten.....

Den Vorteil in deiner Funktion sehe ich darin, da es so einfacher ist längere hex-Anweisungen in Chars umzuwandeln.

Ich hoffe dies hat nicht zu viel Zeit in anspruch genommen....


----------



## vierlagig (7 November 2009)

Andy082 schrieb:


> Ich hoffe dies hat nicht zu viel Zeit in anspruch genommen....



hat es nicht. wenn man weiß, wo man hin will, dauert das kommentieren am längsten ...

nicht nur die länge der auswertung sehe ich als vorteil, sondern auch die stabilität der zykluszeit ... keine bedingten sprünge, schleifen abbrüche oder sonstiges ... einfach 4*11zeilen ...


----------



## argv_user (7 November 2009)

vierlagig schrieb:


> hat es nicht. wenn man weiß, wo man hin will, dauert das kommentieren am längsten ...
> 
> nicht nur die länge der auswertung sehe ich als vorteil, sondern auch die stabilität der zykluszeit ... keine bedingten sprünge, schleifen abbrüche oder sonstiges ... einfach 4*11zeilen ...



Du hast sehr geschickt einfache Ganzzahloperationen durch Gleitkommarechnung ersetzt. Dabei ist noch nicht einmal sicher, dass der Zeitbedarf einer Multiplikation unabhängig von den Operanden ist.


----------



## vierlagig (7 November 2009)

argv_user schrieb:


> Dabei ist noch nicht einmal sicher, dass der Zeitbedarf einer Multiplikation unabhängig von den Operanden ist.



ich kann an dieser stelle nur der operationsliste glauben schenken, die keine ausnahmen und/oder besonderheiten definiert ...


----------



## Andy082 (7 November 2009)

*wie würde das Ganze dann mit Dez to Char ablaufen....*

Hab hier einen FC einer Zulieferfirma erhalten, welcher aber in SCL geschrieben ist.

Da die Umwandlung von hex in char so wunderbar geklappt hat, dachte ich mir ich lass mal rätseln, wie man denn Dezimalzahlen in Chars umwandelt.

Meiner Ansicht nach ungleich schwieriger.... da zumindest ich in AWL an meine Grenzen stoße.

Form:
Eingabe: 12345
C#1: 1
C#2: 2
C#3: 3
C#4: 4
C#5: 5

oder

Eingabe: -45
C#1: 0
C#2: 0
C#3: -
C#4: 4
C#5: 5

oder

Eingabe: -1234
C#1: -
C#2: 1
C#3: 2
C#4: 3
C#5: 4


----------



## vierlagig (7 November 2009)

IEC Function Blocks -> FC5 DI_STRNG -> die einzelnen Bytes stellen die CHAR dar ...


----------



## Andy082 (7 November 2009)

Abend.

Ist mir bekannt....
Aber selbst eine Funktion zu basteln, welche dies bewerkstelligt?
bzw. eben direkt Chars ausgibt und nicht einen String hierzu benötigt?

mfg,
Andy


----------



## vierlagig (8 November 2009)

ich hab da mal bei dem einen oder anderen bier drüber nachgedacht ... eigentlich ist das gar nicht so schwer ... /10 -> Rest (<10) + w#16#30 -> char ... mit dem quotienten weiter ...
dann noch rausfinden, wo das minus stehen soll ...


```
*
FUNCTION FC 4 : VOID
TITLE =
VERSION : 0.1


VAR_INPUT
  dInput : DINT ;    
END_VAR
VAR_OUTPUT
  C_0 : CHAR ;    
  C_1 : CHAR ;    
  C_2 : CHAR ;    
  C_3 : CHAR ;    
  C_4 : CHAR ;    
  C_5 : CHAR ;    
  C_6 : CHAR ;    
  C_7 : CHAR ;    
  C_8 : CHAR ;    
  C_9 : CHAR ;    
  C_10 : CHAR ;    
END_VAR
VAR_TEMP
  xMin : BOOL ;    
  xFirstNumber : BOOL ;    
  xMinus : BOOL ;    
  dTemp : DINT ;    
  iLoop : INT ;    
  aChar : ARRAY  [0 .. 10 ] OF BYTE ;    
  iMinusPos : INT ;    
  dMOD : DINT ;    
  dCompare : DINT ;    
END_VAR
BEGIN
NETWORK
TITLE =

//initialisieren
      CLR   ; 
      =     #xMinus; 
      =     #xMin; 
      L     1; 
      T     #iMinusPos; 
//sonderfall
      L     #dInput; 
      L     L#-2147483648; 
      ==D   ; 
      SPBN  nmin; 
      =     #xMin; 
      L     #dInput; 
      +     1; 
      SPA   min; 

//input ist minus??
nmin: L     #dInput; 
      L     L#0; 
      <D    ; 
      L     #dInput; 
      SPBN  nonu; 
min:  SET   ; 
      =     #xMinus; 
      L     L#-1; 
      *D    ; 
nonu: T     #dTemp; 

//ja, ist minus - position für - berechnen
      U     #xMinus; 
      SPBN  ohmi; 
      L     10; 
      T     #dCompare; 
      L     10; 
nex1: T     #iLoop; 
      L     #dTemp; 
      L     #dCompare; 
      <D    ; 
      SPBN  noch; 
      L     #iLoop; 
      T     #iMinusPos; 
      SPA   ohmi; 
noch: L     #dCompare; 
      L     L#10; 
      *D    ; 
      T     #dCompare; 
      L     #iLoop; 
      LOOP  nex1; 

//ausgabe der einzelnen stellen
ohmi: LAR1  P##aChar; 
      L     11; 
next: T     #iLoop; 
      L     #dTemp; 
      L     10; 
      MOD   ; 
      L     W#16#30; 
      +I    ; 
      T     B [AR1,P#0.0]; 
      L     #dTemp; 
      L     10; 
      /D    ; 
      T     #dTemp; 
      +AR1  P#1.0; 
      L     #iLoop; 
      LOOP  next; 

//ausgabe -
      U     #xMinus; 
      SPBN  end; 
      LAR1  P##aChar; 
      L     11; 
nex2: T     #iLoop; 
      L     #iMinusPos; 
      ==I   ; 
      SPBN  naec; 
      L     W#16#2D; 
      T     B [AR1,P#0.0]; 
      SPA   end; 
naec: +AR1  P#1.0; 
      L     #iLoop; 
      LOOP  nex2; 

//rauskopieren
end:  L     #aChar[10]; 
      T     #C_0; 
      L     #aChar[9]; 
      T     #C_1; 
      L     #aChar[8]; 
      T     #C_2; 
      L     #aChar[7]; 
      T     #C_3; 
      L     #aChar[6]; 
      T     #C_4; 
      L     #aChar[5]; 
      T     #C_5; 
      L     #aChar[4]; 
      T     #C_6; 
      L     #aChar[3]; 
      T     #C_7; 
      L     #aChar[2]; 
      T     #C_8; 
      L     #aChar[1]; 
      T     #C_9; 
      U     #xMin; 
      L     #aChar[0]; 
      SPBN  nee;       
      +     1;       
nee:  T     #C_10;      
      SET   ; 
      SAVE  ; 
END_FUNCTION
```


----------



## Andy082 (8 November 2009)

Grandios, und das bei einigen Bieren....   

Ich würde glatt zweimal danke sagen, wenn's denn ginge.....


Andy


----------



## vierlagig (8 November 2009)

Andy082 schrieb:


> Grandios, und das bei einigen Bieren....



mit bißchen geduld und drüber nachdenken, hättest du das sicher auch hinbekommen. it's not magic, it's only logic!


----------

