# Variablen aus WinCC 6.0 protokollieren



## PHW (19 August 2010)

Hallo,

Erstmal zu meinem Vorhaben:

Ich habe einen Pc mit WinCC mit dem ich diverse Anlagen visualisiert habe und somit steuern und beobachten kann!
Jede Anlage schaltet auf "Volllast" wenn sie produziert und wenn sie ohne produzieren eingeschaltet ist, schaltet sie automatisch auf "Teilllast".

Ich hab mir eine Variable für jede Anlage angelegt die mir bei Vollast den Wert "2" liefert und bei Teillast den Wert "1".

Ziel soll es sein, das ich einmal täglich, wöchentlich und monatlich auswerten kann wieviel die Anlage auf Teil-bzw. Vollast gelaufen ist.
Dies soll über Excel geschehen.

Ich hab es bereits über eine OPC DA Verbindung versucht, allerdings bekomm ich da immer nur den aktuellen Wert der Variable in einer Zelle angezeigt!

Ist es möglich über VB oder ähnliches automatisch eine Exceltabelle zu generieren mit der ich die gewünschten Variablenwerte erfasse und in Excel aufliste. Am Besten wirds nur eingetragen bei Änderung des Wertes der Variablen und dann eben mit "Zustandsdauer" eingetragen. Sodass ich eben eine Exceltabelle habe mit der ich die Zeiten auswerten kann und graphisch darstellen. Aber das ist dann ein anderes Thema!

Wie die Exceltabelle aussehen könnte hab ich mal angehängt. Nur das es vielleicht besser verständlich wird. Selbstverständlich müssen die einzelnen Perioden von Wertigkeit "1" und "2" nicht extra aufgelistet werden. Falls es einfacher ist soetwas wie einen "Zähler" im Hintergrund mitlaufen zu lassen und einmal täglich die Zeitwerte in eine Tabelle zu schreiben ist das auch ok. Bin da für alle Lösungsvorschläge offen.

Wär super wenn mir dabei jemand helfen könnte. Meine Kenntnisse in VB oder anderen Hochsprachen beschränkt sich leider auf das Anwenden von vorgefertigten Skripten etc. Hab bis jetzt immer nur mit S7 und eben WinCC gearbeitet.

Vielen Dank schonmal


----------



## Dr. OPC (19 August 2010)

PHW schrieb:


> Ich hab es bereits über eine OPC DA Verbindung versucht, allerdings bekomm ich da immer nur den aktuellen Wert der Variable in einer Zelle angezeigt!



Mit OPC bist du ja schon mal auf einem richtigen Weg! Wenn du die Werte nur bei Änderung überträgst ist es ganz einfach, denn bei jeder Anderung bekommst du über OPC nicht nur den "Wert" sondern auch den "Zeitstempel" geliefert. Wenn du diesen auch in deine Excel-Tabelle abfüllst, kannst du mit Excel (Datums-Mathematik-Funktionen) ausrechnen wie lange der "Wert"=2 gewesen ist und wielange "1", dann hast du deine "Zustandsdauer".


----------



## PHW (19 August 2010)

Den Zeitstempel hab ich ebenfalls bereits in meiner Exceldatei.

Bis jetzt sieht meine xls so aus.

Zelle A2 mein Variablenname
Zelle B2 der aktuelle Wert 0,1 oder 2
Zelle D2 Zeitstempel

Jedesmal wenn sich mein Wert der Variable ändert, werde die Zellen aktualisiert!
Allerdings wird ja dann der vorherige Wert, inkl. Zeitstempel usw. überschrieben und macht somit eine Auswertung unmöglich. Da wird immer nur der aktuelle Zustand der Variablen angezeigt. Kein "Protokoll".

Wenn ich eine Möglichkeit finden würde die mir die Spalte nicht immer nur aktualisiert sondern bei jeder Änderung das in eine andere Spalte einträgt?
Sodass ich am Ende des Tages eine Liste habe mit den jeweiligen Daten!
Vollast/Teillast ändert sich am Tag unregelmäßig bis zu 20mal!

Das Skript aus meiner xls sieht wie folgt aus:


       MyOPCGroup.IsSubscribed = True

    Exit Sub



  ErrorHandler:

    MsgBox "Error: " & Err.Description, vbCritical, "ERROR"

  End Sub



  '---------------------------------------------------------------------

  ' Sub StopClient()

  ' Purpose: Release the objects and disconnect from the server

  '---------------------------------------------------------------------

  Sub StopClient()

    '----------- Release the Group and Server objects

    MyOPCGroupColl.RemoveAll

    '----------- Disconnect from the server and clean up

    MyOPCServer.Disconnect

    Set MyOPCItemColl = Nothing

    Set MyOPCGroup = Nothing

    Set MyOPCGroupColl = Nothing

    Set MyOPCServer = Nothing

  End Sub



  '---------------------------------------------------------------------

  ' Sub MyOPCGroup_DataChange()

  ' Purpose: This event is fired when a value, quality or timestamp in our Group has changed

  '---------------------------------------------------------------------

  '----------- If OPC-DA Automation 2.1 is installed, use:

  Private Sub MyOPCGroup_DataChange(ByVal TransactionID As Long, ByVal NumItems As Long, ClientHandles() As Long, ItemValues() As Variant, Qualities() As Long, TimeStamps() As Date)

   '----------- Set the spreadsheet cell values to the values read

    Range("B2").Value = CStr(ItemValues(1))

    Range("C2").Value = Hex(Qualities(1))

    Range("D2").Value = CStr(TimeStamps(1))


  End Sub



  '---------------------------------------------------------------------

  ' Sub worksheet_change()

  ' Purpose: This event is fired when our worksheet changes, so we can write a new value

  '---------------------------------------------------------------------

  Private Sub worksheet_change(ByVal Selection As Range)

    '----------- Only if cell "B3" changes, write this value

    If Selection <> Range("B3") Then Exit Sub

    Values(1) = Selection.Cells.Value

    '----------- Write the new value in synchronous mode

    MyOPCGroup.SyncWrite 1, ServerHandles, Values, Errors

  End Sub


----------



## Dr. OPC (19 August 2010)

Für den "Zeilenvorschub" machst du dir eine globale Zählvariable "i", die du auf "0" setzt wenn du dich verbindest. Dort machst du auch einmalig einen Read um den Ausgangszustand zu bekommen und den Zeitstempel von dem aus die Berechnung anfängt. Die Werte aus dem initialen Read füllst du in die dritte Zeile ab.


```
MyOPCGroup.SyncRead OPCCache, 1, ServerHandles, Values, Errors, Qualities, TimeStamps)

if (Erros(1)=0) then
  if (Qualities(1)=192)then
     cells (3,2)=Values(1)
     cells (3,4)=TimeStamps(1)
  end if
end if
```
Dann geht es im Eventhandler für Datachanges weiter. Diesen Eventhandler erweiterst Du einfach und schreibst zusätzlich das "wert" und "Zeitstempel" Paar in einen neue Zeile, falls die Quality Good war. 


```
Private Sub MyOPCGroup_DataChange(ByVal TransactionID As Long, ByVal NumItems As Long, ClientHandles() As Long, ItemValues() As Variant, Qualities() As Long, TimeStamps() As Date)
   
   '----------- Set the spreadsheet cell values to the values read
   
    Range("B2").Value = CStr(ItemValues(1))
   
    Range("C2").Value = Hex(Qualities(1))
   
    Range("D2").Value = CStr(TimeStamps(1))

if (Qualities(1) = 192) then
  cells(4+i,2) = ItemValues(1)
  cells(4+i,4) = TimeStamps(1)
  cells(4+i-1,5) = cells(4+i,4) - cells(4+i-1,4) ' Dauer des vorangegangenen Wertes
  i = i +1 ' Zeilenvorschub erhöhen
end if    
   
  End Sub
```
so zeichnest du dir alle Zustandswechsel auf mit dem Zeitstempel wann der neue Zustand ("Vollast" oder "Teilast" Betrieb) jeweils angefangen hat. Nun billdest du in der Spalte daneben immer die Differenz zum Vorgänger dann hast du die Dauer des jeweiligen Zustands. Anschließend brauchst du nur noch alle Zeitdifferenzen für jeden Zustand zu addieren und fertig.


----------



## PHW (19 August 2010)

Super vielen Dank!

Ich werd das morgen gleich mal ausprobieren!


----------



## Dr. OPC (19 August 2010)

Eine Sache ist mir noch eingefallen, da du ja WinCC verwendest.
Bei der obigen Lösung mit OPC DA hängst du ja "permanent" mit deiner Excel-Tabelle am OPC Server dran und zeichnest dir die "Historie" dieser Variablen selber auf. Also quasi ein TagLogging mit Excel selbst gebastelt. Bei ca 65.000 Zustandswechseln ist die Tabelle dann voll gelaufen und Excel macht die Grätsche. Da brauchst du dann eine Strategie um kurz vorher ein neues Tabellenblatt anzufangen usw. OPC DA liefert immer den aktuellen Wert einer Variablen, um den "Verlauf" aufzuzeichnen musst du also immer mit dem OPC Server verbunden sein sonst "verpasst" du eventuell einen Zustandswechsel.

Alternativ (also wenn das erstmal läuft) kannst du auch noch die Variable in das TagLogging Archiv von WinCC stecken. Dann zeichnet WinCC die Historie für dich auf und es geht nichts "verloren". Zum Zugriff auf das Archiv bietet WinCC einen OPC HDA Server an (Historical Data Access). Das gibt es als Zusatzpacket zu kaufen, soweit ich mich erinnere, hieß mal "Connectivity-Pack" glaube ich.

Mit OPC HDA kann man einen sogenannten "ReadRaw" machen und hier gibt man, im Gegensatz zum DA::Read, als Parameter ein Zeitinterval mit an. Somit kann man "gezielt" Werte aus dem Archiv lesen. Man bekommt dann ein Array mit Wert-Zeitstempel-Paaren und kann dieses auswerten.

Das Ganze ist etwas kniffeliger, da du eine andere Automation.dll in dein Excel/VB einbinden musst. Es gibt sicher auch nicht so viele Beispiele dafür. Aber ich wollte es dennoch hier mal erwähnt haben, denn es ist eine Alternative zu der oben gezeigten Lösung.


----------



## PHW (19 August 2010)

Wenn mich nicht alles täuscht ist OPC HDA schon bei V6.0 verfügbar. Muss ich morgen mal schaun! Aber bin mir ziemlich sicher. Wenn nicht soll das ja nicht das Problem sein!

So eine Variante wär mir definitiv am liebsten. Allerdings konnte mir über so eine Auswertung noch keiner Auskunft geben und beschäftige mich seit einiger Zeit damit. Allerdings bin ich ganz bestimmt (noch) kein Profi in WinCC.
Das alles ist Teil meiner Technikerarbeit...bin quasi noch n Kleiner 

Hab die Variable auch schon im Tag Logging und lasse mir im Online Trend Control den Status der Variablen als "Kurve" anzeigen! Zumindest das wär schonmal getan.
Hab mich eben auch schonmal etwas mit Industrial Data Bridge befasst. Allerdings steht mir das ebenfalls nicht zur verfügung!


----------



## PHW (24 August 2010)

Soweit funktioniert fast alles!

Hab da aber noch einige Fragen!
Und zwar funktioniert bei mir der Read nicht. Bei mir kommen unterschiedliche Fehlermeldungen "Fehler beim Kompilieren" etc....
Aber vielleicht hab ich den Teil auch nur an der falschen Stelle eingebunden. Wo genau sollte das rein?

Die Zählvariable i hab ich einfach mit

Dim i as integer eingebunden? Weiß nicht ob das astrein ist, aber funktioniert!

Dann hab ich noch ein Problem und zwar: Wenn ich die Exceltabelle schließe und wieder öffne, dann werden die bereits beschriebenen Zeilen in meiner Exceltabelle überschrieben(Das Protokoll fängt wieder in der ersten Zeile an). Gibts ne Möglichkeit mit der man einfach in Zeile xy fortfährt? Je nachdem welche Zeile eben schon voll ist!

Danke für die Hilfe!


----------



## PHW (24 August 2010)

Soweit funktioniert fast alles!

Hab da aber noch einige Fragen!
Und zwar funktioniert bei mir der Read nicht. Bei mir kommen unterschiedliche Fehlermeldungen "Fehler beim Kompilieren" etc....
Aber vielleicht hab ich den Teil auch nur an der falschen Stelle eingebunden. Wo genau sollte das rein?

Die Zählvariable i hab ich einfach mit

Dim i as integer eingebunden? Weiß nicht ob das astrein ist, aber funktioniert!

Dann hab ich noch ein Problem und zwar: Wenn ich die Exceltabelle schließe und wieder öffne, dann werden die bereits beschriebenen Zeilen in meiner Exceltabelle überschrieben(Das Protokoll fängt wieder in der ersten Zeile an). Gibts ne Möglichkeit mit der man einfach in Zeile xy fortfährt? Je nachdem welche Zeile eben schon voll ist!

Danke für die Hilfe!


----------



## Dr. OPC (24 August 2010)

Der Read sollte an die Stelle kurz bevor die Gruppe "scharf" geschaltet wird.

```
' TODO: hier den Read
MyOPCGroup.IsSubscribed = True
```
 Oder direkt nach dem Hinzufügen des Items.
	
	



```
MyOPCGroup.AddItem(xxxxx)
' TODO: hier den Read
```
du musst darauf achten welchen Datentyp die Parameter der Read Funktion haben und diese richtig befüllen. Sonst geht der Aufruf nicht.

Zu deinem anderen Problem


> Wenn ich die Exceltabelle schließe und wieder öffne,


Du solltest dir beim Schließen vom Excel z.B. in der Funktion "Sub StopClient()"
   den letzten Stand von "i" merken und irgendwo (z.B. in eine Zelle) reinschreiben. Beim nächsten Start kurz nachdem du "i" angelegt hast, belegst du "i" mit diesem Wert vor.
	
	



```
Dim i as Integer
if cells(x,y)="" then
  i=0
else
  i=cells(x,y)
end if
```
Ausserdem musst du das Ergebnis vom ersten initialen Read auch jeweils um die bestehenden Zeilen versetzt abfüllen. Denn es ist ja der "neue" Anfang deiner Aufzeichnung.


----------



## PHW (24 August 2010)

Super, ich versuch mein Glück!

Danke für die genaue Hilfe  echt top!

Grüße


----------



## PHW (26 August 2010)

Ach mist ich komm echt nicht klar...ist halt schlecht wenn man mit Hochsprachen noch nie etwas zu tun gehabt hat!

Hab heute den initialen Read testen wollen aber kamen wieder Fehlermeldungen beim kompilieren und andere Meldungen. mal konnte ich den Client nicht mehr starten etc.

Das ich mir den Zustand von "i" in eine Zeile schreibe und dann wieder Abfrage hat ebenfalls nciht funktioniert!

Wärst du vielleicht so nett und könntest mir das in das Sktipt das ich mal gepostet habe einbinden?
Wär echt der Hammer, habs wieder 2 Tagellang versucht, aber will einfach nicht!

Danach bin ich auch wunschlos glücklich 

Danke und viele Grüße Philipp


----------

