# WinCC-Variabelen in S7 über Rohdaten



## mortontower (28 Juni 2006)

Hi community,

die Werte aus Rohdaten in Variabelen krieg ich mittlerweile ja raus. Hier nochmal vielen Dank an Donnerkeil.  Jetzt versuche ich gerade Intergerwerte in die SPS zurückzuschreiben,  es kommt aber nur in jedem 2. Byte etwas an. Hat da jemand einen Vorschlag?
Zu guter letzt muss ich INT, DINT und REAL schreiben. Ich bin für jede Unterstützung dankbar.


----------



## mortontower (28 Juni 2006)

*Rohdaten mit Werten versorgen*

Hallo nochmal,

ich versuche es mit folgendem code: 


```
ub OnClick(ByVal Item)                                                                    
 
' Deklaration Rohdaten-Variable ( Wort 0-199 ) 
Dim dw0_199 
 
'lokale VB-Variable als Variant 
Dim db0 
Dim dw0(800) 'As Int 
 
Dim index 
Dim Errorlevel 
 
Set dw0_199 = HMIRuntime.Tags("RoheDaten") 
 
' Variabelenwerte in Array kopieren 
dw0(0) = HMIRuntime.Tags("Wert_1").read 
dw0(1) = HMIRuntime.Tags("Wert_2").Read 
dw0(2) = HMIRuntime.Tags("Wert_3").Read 
dw0(3) = HMIRuntime.Tags("Wert_4").Read 
dw0(4) = HMIRuntime.Tags("Wert_5").Read 
 
'Array nach Rohdatenvariabele kopieren 
For index = 0 To 4 
dw0_199.Value = dw0_199.Value + Chr(dw0(index)) 
Next 
'Rohdaten in SPS schreiben 
Errorlevel = dw0_199.write 
      
      
End Sub
```

allerdings wird in der SPS nur jedes 2. Byte beschrieben. was ist falsch dran? 

gruss

mortontower


----------



## Ulri (28 Juni 2006)

Hallo,

die Zeile in der For-Schleife sollte wie folgt lauten:

dw0_199.Value = dw0_199.Value + Chr(dw0(index)\&h100) + Chr(dw0(index) And &hff)

Für DINT funktioniert es in gleicher Weise, beginnend mit dem Term:

ddw(index)\&h1000000 And &hff + ...

Auf VBS-Ebene muß man REALs IMHO zusammen "basteln". Für nicht denormalisierte Gleitkommazahlen habe ich eine Funktion geschrieben,
aber noch nicht vollständig getestet. Bei Bedarf kann ich sie posten.


----------



## volker (28 Juni 2006)

Ulri schrieb:
			
		

> Auf VBS-Ebene muß man REALs IMHO zusammen "basteln".


 
ne.
du kannst im script ohne probs sowas schreiben

```
[SIZE=2][COLOR=#ff0000]VAR_200[/COLOR][/SIZE][SIZE=2]=3.1415
[/SIZE]
```
wobei var_200 an der steuerung hängt und vom typ: real ist. (z.b. MD200)


----------



## mortontower (28 Juni 2006)

*Rohdaten mit Werten versorgen,*

Danke für den Vorschlag, funktioniert allerdings nur bedingt. ich habe für die Variabele Wert1 = 1025 eingegeben, Wert2 ist 2. Heraus kommt in der SPS folgendes:

Byte0=4
Byte1=0
Byte2=1
Byte3=0
Byte4=0
Byte5=0
Byte6=2
Byte7=0
​Es wird immer ein Byte mit 0 zwischendurch belegt. ich habe versucht den String zu trimmen usw, aber ohne ergebnis. Rohdaten sind ja ein Array von Bytes, aber es kommt mir so vor als ob immer Wörter beschrieben würden. So, what the hell could this be? Oder Chr macht noch'n byte leer hinten dran.


----------



## volker (28 Juni 2006)

mortontower schrieb:
			
		

> Oder Chr macht noch'n byte leer hinten dran.


nah dran.  


```
[URL="mk:@MSITStore:D:\Siemens\Step7\S7bin\s7bashdA.chm::/BAS00803.htm"][COLOR=#0000ff]STRING[/COLOR][/URL] 
Definiert eine Gruppe von maximal 254 Zeichen (Datentyp CHAR).
Der Standardbereich, der für einen Zeichenkette reserviert ist,
besteht aus 256 Bytes. Dies ist der Platz, der benötigt wird,
um 254 Zeichen und [COLOR=red]einen Kopf von 2 Bytes[/COLOR] zu speichern. 
Sie können den Speicherplatz für eine Zeichenkette verringern, 
indem Sie auch die Anzahl der Zeichen definieren, die in der 
Zeichenkette gespeichert werden sollen (z. B. : string[9] ‘Siemens’).
```


----------



## mortontower (28 Juni 2006)

Schlaumeier, mal lesen worums geht. selbst folgender code


```
dw0_199.Value = "HAllo"
```

liefert in der SPS

Byte0=48
Byte1=00
Byte2=41
Byte3=00
Byte4=6C
Byte5=00
Byte6=6C
Byte7=00​Somit kanns ja nicht am String liegen. Man schreibt bytes die Wortweise übergeben werden. kann man ein Byte-Array explizit anlegen? Ist also mit der Deklaration der Rohdatenvariabele etwas nicht Richtig?


----------



## Ulri (28 Juni 2006)

Hallo,

folgendes Programmfragment funktioniert in mehreren Anlagen.
Hier wird ein Textstring von max. 30 Bytes an Byteoffset 5 der Rohdatenvariablen geschrieben:

    Dim partNo : PartNo = "xyz"
    Dim arrSend, strSend
    Dim i, l

    ' ' '

    ' Bytearray via Rohdatenvariable synchron lesen
    arrSend = HMIRuntime.Tags(strSend).Read (1)
    If VarType(arrSend) < vbArray Then' Hier erfolgt eine Fehlerbahandlung
        Exit Sub​End If



    l = Len (PartNo)
    If l > 0 ThenIf l > 30 Then l = 30
        For i=1 To larrSend(i+5) = Asc (Mid (PartNo, i, 1))​Next​End If

    If l < 30 ThenFor i=l+1 To 30arrSend(i+5) = &h20​Next​End If

    ' Bytearray via Rohdatenvariable asynchron schreiben
    HMIRuntime.Tags(strSend).Write arrSend, 0

   ' ' '


----------



## mortontower (28 Juni 2006)

*Rohdaten mit Werten versorgen*

Alles supergut. Danke Ulri für den support. mit folgendem Code kann man auf tastendruck (oder was auch immer) Rohdaten mit integer versorgen:


```
SubOnClick(ByValItem)                                                                                                        
' Integerwerte an Rohdatenblock übergeben und in SPS-Schreiben
' von mortontower, mit freundlicher Unterstützung von Ulri
' es werden die in Anz angegebenen Variabelen geschrieben
' WINCC:TAGNAME_SECTION_START
Const TagNameInAction = "RoheDaten"
' WINCC:TAGNAME_SECTION_END

'lokale VB-Variablen deklarieren als Variant
Dim dw0(800)
Dim arrSend, strSend
Dim i, Anz, Prefix

' konstanten vorbesetzen
    Anz = 4                 'Anzahl von Variabelen
    Prefix = "Wert_"        'Prefix für die Variabelen aus denen gelesen wird
    strSend = "RoheDaten"    'Name der Rohdatenvariable

' Bytearray via Rohdatenvariable synchron lesen
    arrSend = HMIRuntime.Tags(strSend).Read (1)

'Prüfen ob Ergebnis auch ein Array ist
If VarType(arrSend) < vbArray Then
       ' Hier erfolgt eine Fehlerbahandlung
       MsgBox " kein Array in der Variable"
       Exit Sub
End If

' Variabelenwerte aus WinCC in Array vorbereitend einlesen
HMIRuntime.Trace "---------geschriebene Werte------------ "& vbCrLf
For i = 0 To Anz
    dw0(i) = HMIRuntime.Tags(prefix & i).read
    HMIRuntime.Trace "Wert_" & i &" : " & dw0(i) & vbCrLf
Next    

' Temporäres Array an Rohdaten übergeben 
    For i = 0 To anz
        arrSend(i*2)  = dw0(i)\&h100
        arrsend(i*2+1) = dw0(i) And &hff
    Next

' Bytearray via Rohdatenvariable asynchron schreiben
HMIRuntime.Tags(strSend).Write arrSend, 0

End Sub
```


Die Schwierigkeit lag wohl in der Definition des Arrays. Der vorherige versuch war keins. Wenn mans so indirekt macht klappts. bleibt noch die Umwandlung von Gleitkommazahlen (123.456) in 4 bytes IEEfloat. Wenn jemand ne Idee hat, immerzu.

Danke nochmal an Ulri


----------



## Ulri (28 Juni 2006)

Hallo,

die folgende q&d Funktion (incl. Testumgebung für Test außerhalb von WinCC) soll Gleitkommazahlen einfacher Genauigkeit in ein 4-Byte-Array mit Motorola-Byteorder wandeln.
Die Funktion ist allerdings kaum getestet und untestützt nur normalisierte Zahlen. Aber vielleicht hilfts ein wenig?


```
Option Explicit

Const Sng = -123.456

Dim arrBin : arrBin = Sng2Bin(Sng)
Dim i, strTmp :    strTmp = "arrBin=" & vbCrLf

For i=0 To 3 :    strTmp = strTmp & Hex(arrBin(i)) & " ":    Next
MsgBox strTmp

'==============================================================================
' IEEE 754 Single (Float32) in ein Byte-Array entspr. der internen
' PLC-Darstellung wandeln.
'
' BEACHTE! Denormalisierte Zahlen werden (noch) nicht unterstützt.
'
'    Parameter:
'        BYVAL sng        Variant mit Gleitkommazahl
'    Rückgabe:
'        arrBin(3)        4-Byte-Array mit binärem Image der Zahl (Motorola)
'
'    Hist.:
'    31.05.06    Ri    preliminary
'==============================================================================
Public Function Sng2Bin (BYVAL sng) 'As Array(3)

    Dim i, j
    Dim sign :    sign = 0                ' Vorzeichen 
    Dim exp :    exp = 127                ' Offset für Single entspr. IEEE 754
    Dim dblFract :    dblFract = 1
    Dim arrResult :    arrResult = Array (0,0,0,0)
    
    If sng <> 0 Then
        If sng < 0 Then    sng = sng * -1 :    sign = 1

        ' Normalisieren
        Do While sng >= 2 :    sng = sng / 2 :    exp = exp + 1 :    Loop
        Do While sng < 1 :    sng = sng * 2 :    exp = exp -1 :    Loop

        If (exp And 1) = 0 Then sng = sng - 1
        arrResult(0) = sign * 128 + exp \ 2
        
        For i=1 To 3
            For j=7 To 0 Step -1
                If sng > dblFract Then
                    arrResult(i) = arrResult(i) + 2^j
                    sng = sng - dblFract
                End If
                dblFract = dblFract/2
            Next
        Next

    End If
    
    Sng2Bin = arrResult
End Function
```


----------



## Gast (29 Juni 2006)

Hallo,
in c habe ich es so gelöst:

#define SWAP_32(x) ((((x) >> 24) & 0x000000FF) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8 ) | (((x) & 0x000000FF) << 24 ))


void S7ToFloat( float* fVal, void* source )
{
  int iTemp;
  memcpy( &iTemp, source, 4);
  iTemp = SWAP_32( iTemp );
  memcpy( fVal, &iTemp, 4);
}

void FloatToS7( float fVal, void* destination )
{
  int iTemp;
  memcpy( &iTemp, &fVal, 4);
  iTemp = SWAP_32( iTemp );
  memcpy( destination, &iTemp, 4);
}


----------



## mortontower (29 Juni 2006)

*Float in Rohdaten*

Danke Ulri und Gast für eure beiträge. Muss leider auf IBN, werd mich am Wochenende weiterkümmern. (nachdem wir ins halbfinale eingezogen sind!!!)

so long 

mortontower


----------



## mortontower (11 Juli 2006)

*Float in Rohdaten*

Hi community,

hab mittlerweile die Zeit und eine Lösung für Floatvariabele in Rohdaten auf Knopfdruck gefunden. Kann man ja noch ne Funktion draus machen. Der Code sieht so aus:


```
Sub OnClick(ByVal Item)                                                                                                                          
    ' REAL-Werte an Rohdatenblock übergeben und in SPS-Schreiben
    ' von mortontower, mit freundlicher Unterstützung von Ulri
    ' es werden die in Anz angegebenen Variabelen übergeben
    
    'lokale VB-Variablen deklarieren als Variant
    Dim arrSend, strSend
    Dim i, j, k, Anz, Prefix
    Dim sign :    sign = 0                ' Vorzeichen 
    Dim Exp :    Exp = 127                ' Offset für Single entspr. IEEE 754
    Dim dblFract :    dblFract = 1
    Dim arrResult :    arrResult = Array (0,0,0,0)
    Dim invar
    
    ' konstanten vorbesetzen
    Anz = HMIRuntime.Tags("Anzahl").Read '1                     'Anzahl von Variabelen
    Prefix = "RealWert_"        'Prefix für die Variabelen aus denen gelesen wird
    strSend = "RohDatenReal"    'Name der Rohdatenvariable
    
    ' Bytearray via Rohdatenvariable synchron lesen
    arrSend = HMIRuntime.Tags(strSend).Read (1)
    
    'Prüfen ob Ergebnis auch ein Array ist
    If VarType(arrSend) < vbArray Then
    ' Hier erfolgt eine Fehlerbahandlung
    MsgBox " kein Array in der Variable"
    Exit Sub
    End If
    
    ' Grenzen abfragen, nicht mehr als 400 Bytes im Rohdatum
    If Anz < 1 Then     Anz = 1
    If Anz > 100 Then     Anz = 100
    
    ' Variabelen in Rohdaten kopieren
    For k = 0 To (Anz - 1)
        
        ' Initialisierungswerte vorbelegen
        sign = 0
        Exp = 127
        dblFract = 1
        arrResult = Array (0,0,0,0)
        
        ' Variabele einlesen    
        invar = HMIRuntime.Tags(prefix & k).Read (1)   '123.55
            
        '==============================================================================
        ' IEEE 754 Single (Float32) in ein Byte-Array entspr. der internen
        ' PLC-Darstellung wandeln.
        ' BEACHTE! Denormalisierte Zahlen werden (noch) nicht unterstützt.
        '==============================================================================
    
        If invar <> 0 Then
        
            If invar < 0 Then    invar = invar * -1 :    sign = 1
        
            ' Normalisieren
            Do While invar >= 2 :    invar = invar / 2 :    Exp = Exp + 1 :    Loop
            Do While invar < 1 :    invar = invar * 2 :    Exp = Exp -1 :    Loop
        
            If (Exp And 1) = 0 Then invar = invar - 1
            arrResult(0) = sign * 128 + Exp \ 2
            
            For i=1 To 3
                For j=7 To 0 Step -1
                    If invar > dblFract Then
                        arrResult(i) = arrResult(i) + 2^j
                        invar = invar - dblFract
                    End If
                    dblFract = dblFract/2
                Next
            Next
        
        End If
            
        ' Temporäres Array an Rohdaten übergeben 
        For i = 0 To 3
            arrSend((k * 4) + i) = arrResult(i)
            HMIRuntime.Trace "Wert_" & ((k * 4) + i) &" : " & arrResult(i) & vbCrLf
        Next
    Next

    ' Bytearray via Rohdatenvariable asynchron (direkt) schreiben
    HMIRuntime.Tags(strSend).Write arrSend

End Sub
```

Was noch gesagt werden muss: 

         !!!     Die beste Mannschaft ist dritter geworden.     !!!


Wenn einer noch ne Lösung for Rohdaten --> float hat, bitte posten. Wenn ich's habe melde ich mich. Ciao

Mortontower


----------

