Verwendung DotNetSiemensPLCToolBoxLibrary von Jochen Kühner

hanjo

Level-1
Beiträge
28
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute

Zur Verwendung der „DotNetSiemensPLCToolBoxLibrary“von J. Kühne habe ich mindestens zwei Fragen.
Ich verwende Visualstudio 2010 und arbeite mit Visualbasic.

Frage 1
Ich möchte eine vorgegeben Byteanzahl aus der SPS in ein Bytearray einlesen um die eingelesenen Daten anschließend in verschiedene Datenformate zu konvertieren.
Die Sub-Routine „Test()“ soll die Aufgabe realisieren.
Allerdings funktioniert sie nicht. Beim Lesen der Bytes aus der SPS in das Bytearray tritt ein Fehler auf.
Was stimmt in dem Code nicht ?


Sub Test()
'Dieses Testmodul soll 6 Merkbytes ab Merkerbyte 500 in ein Bytearray lesen

'Die Verbindung zur SPS funktioniert und wurde mit dem Aufruf des Konfigurationsmenü eingestellt und getestet
'So wurde die Verbindung aktiviert:
'Konfigurationsmenü Verbindung 1
'Configuration.ShowConfiguration("SPS1", True)
'PLCCon1.Configuration.ConnectionName = "SPS1"
'Mit "PLCCon1.Connect()"

Dim aVar As New PLCTag
Dim Bytearray(100) As Byte
Dim S8 As Byte
Dim S16 As Short
Dim S32 As Integer
Dim Real As Single

aVar.ByteAddress = 500
aVar.BitAddress = 0
aVar.DatablockNumber = 200

aVar.LibNoDaveDataSource = TagDataSource.Flags
aVar.LibNoDaveDataType = TagDataType.ByteArray
aVar.ArraySize = 6
MsgBox("Init ok")

PLCCon1.ReadValuesFromByteArray(aVar, Bytearray, 0)
MsgBox("Read ok")

S8 = libnodave.getS8from(Bytearray, 0)
S16 = libnodave.getS16from(Bytearray, 0)
S32 = libnodave.getS32from(Bytearray, 0)
Real = libnodave.getFloatfrom(Bytearray, 0)

MsgBox("S8=" & S8 & " S16=" & S16 & " S32=" & S32 & " Real=" & Real)

aVar = Nothing
End Sub


Frage 2

Um ein Byte in die SPS zu schreiben, verwende ich folgenden Programmteil.
Dieser Programmteil funktioniert. – die Textbox „Me.txt_Wert1“ enthält z.B. „23“ – die 23 wird zur SPS übertragen.
Das Array Adr ist ein String-Array.
- Adr(0) enthält die Zeichenkette “500”, die Adr(1) enthält die Zeichenkette “0”.
- DBNr ist ein String und enthält „200“.
- Die Variable „Bereich“ = „Merker“
- Der String „VarTyp“ = Byte“

If VarTyp = "Byte" Then
Dim Var As New Communication.PLCTag

Var.ByteAddress = CInt(Adr(0))
Var.BitAddress = CInt(Adr(1))
Var.DatablockNumber = CInt(DBNr)
Var.LibNoDaveDataType = TagDataType.Byte
If Bereich = "Daten" Then Var.LibNoDaveDataSource = TagDataSource.Datablock
If Bereich = "Eingänge" Then Var.LibNoDaveDataSource = TagDataSource.Inputs
If Bereich = "Ausgänge" Then Var.LibNoDaveDataSource = TagDataSource.Outputs
If Bereich = "Merker" Then Var.LibNoDaveDataSource = TagDataSource.Flags

Value = Me.txt_Wert1.Text
Var.ParseControlValueFromString(Value)
PLCCon1.WriteValue(Var)
'Me.txt_Wert1.Text = Var.Value
Var = Nothing
End If

Nun meine Frage :

Wie muss der Programmteil aussehen, wenn ein REAL-Wert zur SPS übertragen werden soll.
Der folgende Programmteil funktioniert nicht – er überträgt immer eine 0.0.
Welcher Wert muss in der Textbox stehen „Me.txt_Wert1.Text“– damit die Übertragung einer REAL-Variablen in die SPS erfolgreich ist?
Das Array Adr ist ein String-Array.
- Adr(0) enthält die Zeichenkette “500”, die Adr(1) enthält die Zeichenkette “0”.
- DBNr ist ein String und enthält „200“.
- Die Variable „Bereich“ = „Merker“
- Der String „VarTyp“ = REAL“

If VarTyp = "REAL" Then
Dim Var As New Communication.PLCTag

Var.ByteAddress = CInt(Adr(0))
Var.BitAddress = CInt(Adr(1))
Var.DatablockNumber = CInt(DBNr)
Var.LibNoDaveDataType = TagDataType.Float
If Bereich = "Daten" Then Var.LibNoDaveDataSource = TagDataSource.Datablock
If Bereich = "Eingänge" Then Var.LibNoDaveDataSource = TagDataSource.Inputs
If Bereich = "Ausgänge" Then Var.LibNoDaveDataSource = TagDataSource.Outputs
If Bereich = "Merker" Then Var.LibNoDaveDataSource = TagDataSource.Flags

Value = Me.txt_Wert1.Text
Var.ParseControlValueFromString(Value)
PLCCon1.WriteValue(Var)
Me.txt_Wert1.Text = Var.Value
Var = Nothing
End If


 
Hallo erst mal.

Das lesen funzt nicht da du die Funktion ReadValuesFromByteArray(aVar, Bytearray, 0) verwendest. Diese Funktion ist dazu da um den Tag mit Werten aus einem ByteArray zu befüllen das du z.B. per TCP direkt auf den PC schickst.

du kannst den Tag einfach mit
PLCCon1.ReadValue(aVar)
einlesen.

Da du aber Verschiedene Variablen willst, würde Ich das ganz anderst angehen.

Du legst dir eine Liste mit verschiedenen PLCTags an, und liest diese mit PLCCon1.ReadValues ein.

An meiner lib soll ja der Vorteil sein, das du dieses zerlegen eines ByteStreams in die einzelnen Variablen nicht mehr machen musst!

Beispielcode:

Code:
 Dim Tags As New List(Of PLCTag)

        Dim val1 As New Communication.PLCTag("MB500")
        val1.LibNoDaveDataType = TagDataType.Byte
        Tags.Add(val1)

        Dim val2 As New Communication.PLCTag("MW501")
        val1.LibNoDaveDataType = TagDataType.Int
        Tags.Add(val2)

        Dim val3 As New Communication.PLCTag("MD503")
        val1.LibNoDaveDataType = TagDataType.Dint
        Tags.Add(val3)

        Dim val1 As New Communication.PLCTag("MD507")
        val1.LibNoDaveDataType = TagDataType.Float
        Tags.Add(val4)
        PLCCon1.ReadValues(Tags)
 
Zur 2. Frage

Wie gesagt - den ersten Teil werde ich testen.

Die zweite Frage würde ich gern noch mal wiederholen - dabei ging es um das Schreiben eines Real-Wertes.

Frage 2

Um ein Byte in die SPS zu schreiben, verwende ich folgenden Programmteil.

Dieser Programmteil funktioniert. – die Textbox „Me.txt_Wert1“ enthält z.B. „23“ – die 23 wird zur SPS übertragen.
Das Array Adr ist ein String-Array.
- Adr(0) enthält die Zeichenkette “500”, die Adr(1) enthält die Zeichenkette “0”.
- DBNr ist ein String und enthält „200“.
- Die Variable „Bereich“ = „Merker“
- Der String „VarTyp“ = Byte“

If VarTyp = "Byte" Then
Dim Var As New Communication.PLCTag

Var.ByteAddress = CInt(Adr(0))
Var.BitAddress = CInt(Adr(1))
Var.DatablockNumber = CInt(DBNr)
Var.LibNoDaveDataType = TagDataType.Byte
If Bereich = "Daten" Then Var.LibNoDaveDataSource = TagDataSource.Datablock
If Bereich = "Eingänge" Then Var.LibNoDaveDataSource = TagDataSource.Inputs
If Bereich = "Ausgänge" Then Var.LibNoDaveDataSource = TagDataSource.Outputs
If Bereich = "Merker" Then Var.LibNoDaveDataSource = TagDataSource.Flags

Value = Me.txt_Wert1.Text
Var.ParseControlValueFromString(Value)
PLCCon1.WriteValue(Var)
'Me.txt_Wert1.Text = Var.Value
Var = Nothing
End If

Nun meine Frage :

Wie muss der Programmteil aussehen, wenn ein REAL-Wert zur SPS übertragen werden soll.
Der folgende Programmteil funktioniert nicht – er überträgt immer eine 0.0.
Welcher Wert muss in der Textbox stehen „Me.txt_Wert1.Text“– damit die Übertragung einer REAL-Variablen in die SPS erfolgreich ist?
Das Array Adr ist ein String-Array.
- Adr(0) enthält die Zeichenkette “500”, die Adr(1) enthält die Zeichenkette “0”.
- DBNr ist ein String und enthält „200“.
- Die Variable „Bereich“ = „Merker“
- Der String „VarTyp“ = REAL“

If VarTyp = "REAL" Then
Dim Var As New Communication.PLCTag

Var.ByteAddress = CInt(Adr(0))
Var.BitAddress = CInt(Adr(1))
Var.DatablockNumber = CInt(DBNr)
Var.LibNoDaveDataType = TagDataType.Float
If Bereich = "Daten" Then Var.LibNoDaveDataSource = TagDataSource.Datablock
If Bereich = "Eingänge" Then Var.LibNoDaveDataSource = TagDataSource.Inputs
If Bereich = "Ausgänge" Then Var.LibNoDaveDataSource = TagDataSource.Outputs
If Bereich = "Merker" Then Var.LibNoDaveDataSource = TagDataSource.Flags

Value = Me.txt_Wert1.Text
Var.ParseControlValueFromString(Value)
PLCCon1.WriteValue(Var)
Me.txt_Wert1.Text = Var.Value
Var = Nothing
End If
 
Sollte nun auch gehen.

War noch ein Fehler in meiner Lib.
Hatte bei der Funktion ParseControlvalueFromString Float vergessen!
 
Nach dem versprochenem Test

Punkt 1 - Wie versprochen habe ich heute das Lesen und Schreiben von einzelnen Variablen in verschiedenen Formaten getestet.
SPS : S7-400 CPU417-3
CP : TCP-Verbindung

Das Ergebnis ist in der Übersicht Bild "Ergebnis" im Anhang enthalten
Bei den rot markierten Positionen traten Fehler beim Lesen bzw. Schreiben auf.

Punkt 2 – Wie von Jochen vorgeschlagen habe ich verschiedene Variablen in einer Liste des Typs PLCTag zusammengefasst und aus der SPS gelesen bzw. geschrieben.
Leider hat weder das Lesen noch das Schreiben der Liste funktioniert.
Hier auszugsweise der Code:
Die Routine „Sub InitListe“ füllt die Variablenliste „TagList“ mit PLCTag Variablen
Sub InitListe(ByRef TagList As List(Of PLCTag))
'Tags entspricht einer Liste von PLCTags
'Tags = Nothing

Dim val1 As New PLCTag
'BOOL-Variable M500.0
val1.LibNoDaveDataSource = TagDataSource.Flags
val1.LibNoDaveDataType = TagDataType.Bool
val1.DatablockNumber = 200
val1.ByteAddress = 500
val1.BitAddress = 0
TagList.Add(val1)
val1 = Nothing


'====================================================
'Bytevariable MB501
Dim val2 As New PLCTag
val2.LibNoDaveDataSource = TagDataSource.Flags
val2.LibNoDaveDataType = TagDataType.Byte
val2.ByteAddress = 501
val2.BitAddress = 0
val2.DatablockNumber = 200
val2.ArraySize = 1
TagList.Add(val2)
val2 = Nothing

'S-Bytevariable MB502
Dim val3 As New PLCTag
val3.LibNoDaveDataSource = TagDataSource.Flags
val3.LibNoDaveDataType = TagDataType.SByte
val3.ByteAddress = 502
val3.BitAddress = 0
TagList.Add(val3)
val3 = Nothing

'BCD-Bytevariable MB503
Dim val4 As New PLCTag
val4.LibNoDaveDataSource = TagDataSource.Flags
val4.LibNoDaveDataType = TagDataType.BCDByte
val4.ByteAddress = 503
val4.BitAddress = 0
TagList.Add(val4)
val4 = Nothing

End Sub

Die Routine zum lesen der Daten aus der SPS lautet „ListeLesen“ – sie soll die Variablenwerte aus der SPS laden und in ein DatagridView eintragen.
Sub ListeLesen()
If Con1_Verbunden = True Then
Dim Tags As New List(Of PLCTag)
'Liste der PLC-Variablen initialisieren
Call InitListe(Tags)
'====================================================
PLCCon1.ReadValues(Tags)
'====================================================
Dim N As Integer
Dim T(Tags.Count + 1) As String
For N = 0 To Tags.Count - 1
Me.dgv_Liste.Rows(N).Cells(0).Value = Trim(Str(N))
Me.dgv_Liste.Rows(N).Cells(1).Value = Tags(N).S7FormatAddress
Me.dgv_Liste.Rows(N).Cells(2).Value = Tags(N).LibNoDaveDataType.ToString
Me.dgv_Liste.Rows(N).Cells(3).Value = Tags(N).Value
Next
Tags = Nothing
Else
MsgBox("Erst Verbindung herstellen !", MsgBoxStyle.Information, "Hinweis !")
End If

End Sub

Das Ergebnis des zeigt im Anhang enthaltene Bild "Liste lesen".
Es ist zu erkennen, das die Variableneigenschaften richtig angezeigt, aber die Werte nicht aus der SPS geladen wurden.

Die Routine zum Schreiben der Variablen in die SPS lautet „ListeSchreiben“
Leider funktioniert auch diese Routine nicht.


Sub ListeSchreiben()
If Con1_Verbunden = True Then
MsgBox("Start Liste einlesen !")
Dim Tags As New List(Of PLCTag)
'Liste der PLC-Variablen initialisieren
Call InitListe(Tags)
MsgBox("Liste initialisiert !")
Dim N As Integer
Dim T(20) As String
Dim Value As String

For N = 0 To 3
N = Val(Me.dgv_Liste.Rows(N).Cells(0).Value)
Value = Me.dgv_Liste.Rows(N).Cells(3).Value
Tags(N).ParseControlValueFromString(Value)
Next
MsgBox("Parsen abgeschlossen !")
'====================================================
PLCCon1.WriteValues(Tags)
MsgBox("Schreiben beendet !")
Tags = Nothing
Else
MsgBox("Erst Verbindung herstellen !", MsgBoxStyle.Information, "Hinweis !")
End If
End Sub

Was mache ich hier falsch ?
Ich bin dankbar für Hilfe - hanjo
 

Anhänge

  • Ergebnis.jpg
    Ergebnis.jpg
    170,4 KB · Aufrufe: 82
  • ListeLesen.jpg
    ListeLesen.jpg
    73,3 KB · Aufrufe: 64
Quellcode...

Mhmm...

Kannst mir mal deinen Quellcode zuschicken? Normal sollte das lesen gehen, so wie du es gemacht hast, mir ist beim Überfliegen jetzt kein Fehler aufgefallen.

Danke auch für das Prüfen der verschiedenen Formate, Ich werd mich gleich ans BugFixing machen...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Bugfixes...

So hab mal ein paar Bugfixes gemacht...

- SByte -> geht nun.
- BCDWord -> geht, Frage mich nur ob man bei den BCD Typen ein vorzeichen unterstützen muss. Wenn, dann muss Ich das noch einbauen!
- BCDDWord -> geht nun.
- TIME -> Nur negative Werte gingen nicht, gehen nun!
- TIMEOFDAY -> Hab die Miliseconds Property statts der TotalMillisecondes verwendet... gefixt!
-----

-S5Time -> Geht bei mir, welchen Wert willst du den lesen oder schreiben? Hab da keinen Fehler gefunden
- DateTime -> Die Milisekunden werden mitgelesen, doch die ToString methode eines DateTime datentyps zeigt die MS nicht mit an !
- String: Ja man muss zuerst die Länge angeben! Sonst müsste Ich aber auch vor jedem schreiben Zwingend ein Lesen starten. Ist ja z.B. in Flexible auch so, das man die Länge angeben muss!

Nochwas:
So wie mirs scheint willst du dir ja sowas wie ne Variablentabelle bauen. Dann schau dir mal noch die Funktion SelectProjectPart.SelectTAG an, dann kannst du die PLCTags aus einem Step7 Projekt auswählen!
 
Anbei das VB-Projekt

Hallo Jochen

1. Testprojekt
Ursprung des Testprojektes ist aus deiner Lib – VB.
Deshalb sind auch noch Überreste (Button 1 und Button 2 enthalten).
Ich habe das Testprojekt, das nur den Kommunikationstest enthält, im Anhang beigelegt.

2. BCD-Werte
BCD-Werte haben keine Vorzeichen :
WORD-BCD : 0000 … 9999
DWORD-BCD : 00000000 … 99999999

3. Hier nun das Ziel des Projektes :
Es ist schon richtig – ich möchte eine Art Protokoller gestalten.
Er unterscheidet sich von deinem etwas.

Beschreibung:
In der SPS werden Protokolldaten in einem Datenbaustein zusammengestellt.
Nach der Zusammenstellung werden die Daten von der SPS nicht mehr verändert.
Die SPS setzt ein Bit und zeigt dem PC an, in dem die Anwendung „Protokoller“ läuft, das die Daten zur Abholung bereitstehen.
Der „Protokoller“ prüft also zyklisch ob das Protokollbit gesetzt ist, holt die Daten wenn dies der Fall ist und löscht anschließend das Protokollbit.
In der SPS existiert ein Umlaufspeicher für Protokolldaten – immer wenn der „Protokoller“ Protokolldaten gelesen hat, stellt die SPS die nächsten zusammen.

Dieses Prinzip habe ich bereits mit dem alten INAT- Treiber realisiert.
 

Anhänge

  • Test.zip
    1,6 MB · Aufrufe: 44
Zuviel Werbung?
-> Hier kostenlos registrieren
Anbei das VB-Projekt

Hallo Jochen
Im Anhang habe ich das Testprojekt verpackt.
Ursprung des Testprojektes ist aus deiner Lib – VB.
Deshalb sind auch noch Überreste (Button 1 und Button 2 enthalten).


BCD-Werte haben keine Vorzeichen :
WORD-BCD : 0000 … 9999
DWORD-BCD : 00000000 … 99999999

Hier nun das Ziel des Projektes :
Es ist schon richtig – ich möchte eine Art Protokoller gestalten.
Er unterscheidet sich von deinem etwas.
Beschreibung:
In der SPS werden Protokolldaten in einem Datenbaustein zusammengestellt.
Nach der Zusammenstellung werden die Daten von der SPS nicht mehr verändert.
Die SPS setzt ein Bit und zeigt dem PC an, in dem die Anwendung „Protokoller“ läuft, das die Daten zur Abholung bereitstehen.
Der „Protokoller“ prüft also zyklisch ob das Protokollbit gesetzt ist, holt die Daten wenn dies der Fall ist und löscht anschließend das Protokollbit.
In der SPS existiert ein Umlaufspeicher für Protokolldaten – immer wenn der „Protokoller“ Protokolldaten gelesen hat, stellt die SPS die nächsten zusammen.

Dieses Prinzip habe ich bereits mit dem alten INAT- Treiber realisiert.
 
Hallo erst mal.

Das lesen funzt nicht da du die Funktion ReadValuesFromByteArray(aVar, Bytearray, 0) verwendest. Diese Funktion ist dazu da um den Tag mit Werten aus einem ByteArray zu befüllen das du z.B. per TCP direkt auf den PC schickst.

du kannst den Tag einfach mit
PLCCon1.ReadValue(aVar)
einlesen.

Da du aber Verschiedene Variablen willst, würde Ich das ganz anderst angehen.

Du legst dir eine Liste mit verschiedenen PLCTags an, und liest diese mit PLCCon1.ReadValues ein.

An meiner lib soll ja der Vorteil sein, das du dieses zerlegen eines ByteStreams in die einzelnen Variablen nicht mehr machen musst!

Beispielcode:

Code:
 Dim Tags As New List(Of PLCTag)

        Dim val1 As New Communication.PLCTag("MB500")
        val1.LibNoDaveDataType = TagDataType.Byte
        Tags.Add(val1)

        Dim val2 As New Communication.PLCTag("MW501")
        val1.LibNoDaveDataType = TagDataType.Int
        Tags.Add(val2)

        Dim val3 As New Communication.PLCTag("MD503")
        val1.LibNoDaveDataType = TagDataType.Dint
        Tags.Add(val3)

        Dim val1 As New Communication.PLCTag("MD507")
        val1.LibNoDaveDataType = TagDataType.Float
        Tags.Add(val4)
        PLCCon1.ReadValues(Tags)

Liest du die Variablen einzeln aus oder optimiert die Lib das Lesen der List ?
 
S7: Beim Umwandeln einer BCD-Zahl in eine Ganzzahl wird nur das höchstwertige Bit als Vorzeichen ausgewertet, die anderen 3 Bits in der Vorzeichen-Tetrade werden ignoriert (dürfen also durchaus auch 0 sein).

Harald
 
1. Danke für den Test meines Testprogrammes

Ich werde es am Montag nochmals ausprobieren.

2. BCD-Zahlen

Ich habe nur quer Beet alle Varianten deiner DLL erprobt.
Selber hab ich sie noch nicht benötigt - also lass es so wie es ist.


3. Und nun doch noch eine Frage

Wie due in meinem Testprogramm vieleicht bemerkt hast, habe ich den Aufruf und das Einlesen einer Symboldatei mittels deiner DLL bereits integriert.
Funktioniert wunderbar.
Nun meine Frage:
Die Rückgabe eines BlockTags ist mir auch gelungen.
Ist es möglich die Auflistung der in einem Datenbaustein (Block) enthaltenen Tags heranzukommen?
Bis jetzt ist es mir immer nur gelungen einen TAG des Blocks zu lesen.

Vielen Dank für Bemühungen hanjo
 
Zurück
Oben