Snap7 - Bitänderung soll Ereignis auslösen

AlexTh

Level-2
Beiträge
110
Reaktionspunkte
2
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute,

ich hatte vor einigen Tagen damit angefangen mich mit Snap7 zu beschäftigen.
Aktuell sieht es so aus, dass ich problemfrei Werte lesen und schreiben kann.
Ich habe auch schon die Bits eines Bytes in einen String umgewandelt und ausgegeben.

https://www.sps-forum.de/simatic/85169-verbindung-mit-pc-4.html


Nun möchte ich, dass bei Änderung eines einzelnen Bits in der SPS eine Aktion in meinem Programm gestartet wird.
Ich hatte dazu schon folgende Beiträge im WWW gefunden, aber weiß nicht so richtig, wie ich es umsetzen kann. Könnt ihr mir auf die Sprünge helfen?

https://saschawald.wordpress.com/2012/01/20/einfachevariablen_event/
https://msdn.microsoft.com/de-de/library/wkzf914z(v=vs.110).aspx
https://msdn.microsoft.com/de-de/library/edzehd2t(v=vs.110).aspx
 
... das ist mir persönlich jetzt "ein bißchen" sehr vage ... Ich schreib aber mal, wie ich es machen würde :

Du erschaffst dir eine Hintergrund-Methode, die die für dich relevanten Daten zyklisch (also z.B. jede Sekunde) von der SPS einliest.
Von jeder Variablen "merkst" du dir den Wert, den sie vor dem neuen Einlesen hatte, liest sie neu ein und schaust dann, ob sich deren Wert geändert hat (Vergleich letzter Wert mit aktuellem Wert). Bei einer Single-Variablen baust du ggf. eine gewisse "Unschärfe" mit ein. Hat sich der Wert geändert so könntest du ein Event auslösen. Dieses Event greifst du dann in einem Script auf und weißt dem Anzeige-Control (z.B. einer TextBox) den neuen Wert zu.

Du könntest aber auch eine Klasse erzeugen, die das innen drin alles selber macht.
Wenn man das dann weiter treibt dann könnte man diese Klasse sogar über eine Property mit einem überarbeiteten Control koppeln und dann würde dieses Control das Notwendige innen drin vollkommen selbständig erledigen.

Vielleicht schreibst du einfach mal, was du dir vorgestellt hast und wie weit du im Bereich .Net gehen möchtest.

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Theoretisch wollte ich das ganze über Property lösen, aber ich kenne mich nicht wirklich damit aus.
Ich hatte mir das Ganze in mehreren Beispielen angeschaut, dennoch kann ich es nicht umsetzen.
Meist werden Properties nur dafür genutzt, um irgendwelche Grids zu befüllen...
 
Dann versuch doch zunächst erstmal das :
Du erschaffst dir eine Hintergrund-Methode, die die für dich relevanten Daten zyklisch (also z.B. jede Sekunde) von der SPS einliest.
Von jeder Variablen "merkst" du dir den Wert, den sie vor dem neuen Einlesen hatte, liest sie neu ein und schaust dann, ob sich deren Wert geändert hat (Vergleich letzter Wert mit aktuellem Wert). Bei einer Single-Variablen baust du ggf. eine gewisse "Unschärfe" mit ein. Hat sich der Wert geändert so könntest du ein Event auslösen. Dieses Event greifst du dann in einem Script auf und weißt dem Anzeige-Control (z.B. einer TextBox) den neuen Wert zu.

Die einfachste Art eine solche Hintergrund-Methode an den Start zu bekommen wäre ein Timer (also ein Control, dass du an deine Form binden könntest).
Versuch doch erstmal das umzusetzen. Dann tasten wir uns schrittweise weiter ... es gibt dazu sehr viel bei Google zu finden ...

Gruß
Larry
 
Ich habe das Ganze einfach mal ohne Properties simuliert. Ich habe es mit einem Timer und der Stopwatch realisiert und wollte den Unterschied der beiden sehen, aber er ist nicht gravierend.
Ich wollte nun einmal die Zeiten addieren, um zu sehen, wie lange ein Signal insgesamt auf TRUE war, aber dies funktioniert absolut nicht.

Mittlerweile denke ich, dass es besser wäre ein Byte auf Veränderung zu überwachen als ein einziges Bit. Das werde ich dann mal probieren.


Code:
Option Strict On
Imports System.Diagnostics
Public Class Form1
    'Timer erstellen
    Private WithEvents T0 As New Timer With {.Interval = 100}
    Private Startzeit As Date
    Dim counter As Integer
    Dim watch As New Stopwatch()
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        'Buttonclicks hochzählen
        counter = counter + 1
        TextBox1.Text = counter.ToString
        'wenn Checkbox = 1 > ausschalten / wenn Checkbox = 0 > einschalten
        If CheckBox1.Checked = True Then
            CheckBox1.Checked = False
        Else
            CheckBox1.Checked = True
            'bei True die Zeitaufnahme starten
            Startzeit = Now
            T0.Start()
            watch.Start()
        End If
    End Sub
    Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
        Dim Zeitvergangen As New TimeSpan
        Dim Gesamtzeit As New Double
        Dim Zeitwert As Double
        'wenn Checkbox = 0, Zeitaufnahme stoppen
        If CheckBox1.Checked = False Then
            Zeitvergangen = Now.Subtract(Startzeit)
            Label1.Text = Zeitvergangen.TotalSeconds.ToString() & "s"
            T0.Stop()
            watch.Stop()
            Zeitwert = watch.ElapsedMilliseconds / 1000
            Gesamtzeit = Gesamtzeit + Zeitwert
            Label2.Text = Zeitwert.ToString
            Label3.Text = Gesamtzeit.ToString
            watch.Reset()
        End If
    End Sub
End Class
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
Ich wollte nun einmal die Zeiten addieren, um zu sehen, wie lange ein Signal insgesamt auf TRUE war, aber dies funktioniert absolut nicht.
verstehe ich gerade nicht ... aber ich sehe auch keinen Code, wo du das (wie auch immer) gemacht hast.
Prinzipiell würde ich aber immer eine Variable vom Type Date anlegen und darin Now abspeichern.
Zu einem späteren Zeitpunkt dann von diesem Wert und Now die Differenz bilden (z.B. in Millisekunden).

Mittlerweile denke ich, dass es besser wäre ein Byte auf Veränderung zu überwachen als ein einziges Bit. Das werde ich dann mal probieren.
Das Byte auf Änderung überwachen bringt hier (nach meiner Meinung) nichts. Wenn dich aber aus dem Byte mehr als ein Bit interessiert dann kannst du dir ggf. das wiederholte Einlesen ersparen - dabei wird die Zeit verbraten.

Wie sieht denn deine Timer-Methode aus ?

Gruß
Larry

Nachsatz:
Bist du übrigens sicher, dass du wirklich alle 100ms eine Aktualisierung deiner Variablen benötigst ? ich würde da mal etwas zwischen 500ms und 1s machen - schnell nur da, wo wirklich und unumgänglich schnell benötigt wird. Das ist aber bei den allerwenigsten Informationen von und zur Visu so ...
 
Zuletzt bearbeitet:
Genau so habe ich es doch gemacht?

Bei Klick auf Button 1 kommt "Startzeit = Now" und wenn sich die Checkbox ändert, dann wird subtrahiert mit "Zeitvergangen = Now.Subtract(Startzeit)"
Als Date ist das Ganze deklariert.

Nun will ich aber diese Differenzen addieren, das hatte ich folgendermaßen vor:

Code:
            Zeitwert = watch.ElapsedMilliseconds / 1000
            Gesamtzeit = Gesamtzeit + Zeitwert

Die Variable 'Zeitwert' hat theoretisch den selben Inhalt wie die Variable 'Zeitvergangen', nur dass ich den Wert hier von der Stopwatch genommen habe. Aber selbst dann, wenn ich die Variable 'Zeitvergangen' nutze ändert sich am Ergebnis nichts.

Der Timer T0 ist nicht zum Aktualisieren da, das war lediglich meine erste Idee, weil ich die Stopwatch in VB.NET noch nicht kannte. Er zählt quasi die Zeit die vergeht, bis sich ein Bit wieder ändert.
 
Ich will eigentlich immer nur das Ergebnis aus Now.Subtract(Startzeit) addieren und am Ende des Tages loggen.

Wenn das Bit nun 500x am Tag sein Signal wechselt, so möchte ich die Zeit zusammenfassen, in der das Bit beispielsweise 1 war. Dabei ist es mir egal, wie sekundengenau das Ganze ist. Minutengenau reicht aus.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Das Ergebnis von Now.Subtract() ist vom Typ TimeSpan (also Zeitspanne).
Wenn du jetzt die Minuten und/oder Sekunden davon in einem Integer aufaddieren willst so mußt du doch nur deren Unter-Elemente, die ja vom Typ Integer sind, aufaddieren :
Code:
dim [B]t as TimeSpan = Now.Subtract(Startzeit)
[/B]dim ZeitVergangen_in_Sek as integer = t.seconds + t.minutes * 60
Die Variable "ZeitVergangen_in_Sek" muss hier dann natürlich eine globale Variable sein ...

Gruß
Larry
 
Ich habe es im Double gerechnet, weil ich die Millisekunden auch mal mit darstellen möchte, um später die Latenzen und Reaktionszeiten zu sehen.

Dein Tipp hat mir sehr geholfen, ich habe es etwas anders gelöst, aber ohne deine Idee wäre ich nicht darauf gekommen. ;)

Code:
Dim rechnen As Double 'GLOBAL DEFINIERT

        Dim Zeitvergangen As TimeSpan
        Dim ZeitVergangenAdd As Double

            Zeitvergangen = Now.Subtract(Startzeit)
            ZeitVergangenAdd = Zeitvergangen.TotalMilliseconds / 1000
            rechnen = rechnen + ZeitVergangenAdd 'Gesamtzeit
            Label3.Text = rechnen.ToString
 
Zurück
Oben