TIA Trace kontinuirt. Was mache ich falsch ?

Zuviel Werbung?
-> Hier kostenlos registrieren
Leider kann ich eine Pre-Trigger auch nicht konfigurieren da ich zu diesen Zeitpunkt keine konkrete Idée habe auf was ich aufmerksam sein muss.
Könntest du den Pre-Trigger auf einen Wert stellen der fast der max. Aufzeichnungsdauer entspricht und einen Trigger, wie du schon probiert hattest, auf ein Bit das du dann manuell im Fehlerfall setzt? Oder der Kunde vom Panel aus.

Der Ablauf wäre dann so, Trace Konfig übertragen, Aufnahme starten und dann müsste oben rechts angezeigt werden das er auf den Trigger wartet und das sollte im Hintergrund puffern bis der Trigger ausgelöst wird.
 
Könntest du den Pre-Trigger auf einen Wert stellen der fast der max. Aufzeichnungsdauer entspricht und einen Trigger, wie du schon probiert hattest, auf ein Bit das du dann manuell im Fehlerfall setzt? Oder der Kunde vom Panel aus.
Das wäre eine Möglichkeit.
Das Problem ist eher, dass ich die Einrichtung unklar finde und mir nicht 100% sicher bin, ob es funktioniert wie erwartet.
Ich kann nicht in die Kunden Maschine experimentieren. Ich müsste sie jetzt implementieren und sicherstellen, dass sie funktioniert.

Dieses Mal werde ich meine eigene Trace-Funktion erstellen.
Ein anderes Mal würde ich einige Tests mit die integrierte Trace in einer SPS durchführen, die nicht an einer realen Maschine verwendet wird. Und wenn das funktioniert, würde ich es in einer laufenden Maschine implementieren.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe das mit Python und Snap7 gelöst. Die gewüschten Daten kontinierlich in eine SQLite3-Datenbank geschrieben. Dazu muß natürlich ein Laptop an der Steuerung hängen. Snap7 für Python muß man aus dem Netz suchen und installieren. Die Daten schreibt man der EInfachheit halber in einen eigenen DB, aus dem man die dann immer ausliest. Achtung, der DB darf nicht optimiert sein!

Code:
#pylint: disable=no-member

import snap7
import snap7.client
from snap7.snap7types import *
from snap7.util import *

import sqlite3
from sqlite3 import Error

from datetime import datetime as DateTime

class DBObject(object):
    pass
   
offsets = {
    "Bool"  : 2,
    "Int"   : 2,
    "Real"  : 4,
    "DWord" : 4,
    "String": 256
    }

db=\
"""
Count\tDWord\t0.0
Temperature\tReal\t4.0
DistanceOverAll\tReal\t8.0
CyclesOverAll\tDWord\t12.0
MotorCurrent\tReal\t16.0
DB_String\tString\t20.0
"""

def DBRead(plc,db_num,length,dbitems):
    data = plc.read_area(areas['DB'],db_num,0,length)  
    obj = DBObject()
    for item in dbitems:
        value = None
        offset = int(item['bytebit'].split('.')[0])

        if item['datatype']=='Real':
            value = get_real(data,offset)

        if item['datatype']=='Bool':
            bit =int(item['bytebit'].split('.')[1])
            value = get_bool(data,offset,bit)

        if item['datatype']=='DWord':
            value = get_dword(data, offset)

        if item['datatype']=='String':
            value = get_string(data, offset)
       
        obj.__setattr__(item['name'], value)
 
    return obj

#function changed 18.06.2024, old function don't worked correctly
def get_db_size(array,bytekey,datatypekey):
    seq,length = [x[bytekey] for x in array],[x[datatypekey] for x in array]
    lastByte = 0
    for idx in length:
        lastByte = lastByte + int(offsets.get(idx))
    return lastByte

###########################################################
#   sql database
###########################################################
def create_connection(db_file):
    """ create a database connection to a SQLite database
        specified by db_file
        :param db_file: database file
        :return: Connection object or None
    """
    conn = None
    try:
        conn = sqlite3.connect(db_file, check_same_thread=False)
        return conn
    except Error as e:
        print('sqlite3 error: ', e)
    return conn

def create_table(conn, create_table_sql):
    """ create a table from the create_table_sql statement
    :param conn: Connection object
    :param create_table_sql: a CREATE TABLE statement
    :return:
    """
    try:
        c = conn.cursor()
        c.execute(create_table_sql)
    except Error as e:
        print('table create error: ', e)

database = r"pythonsqlite_Vertikalachse.db"
def create_database(database):

    sql_create_projects_table = """ CREATE TABLE IF NOT EXISTS projects (
                                        id integer PRIMARY KEY,
                                        name text NOT NULL,
                                        time text,
                                        Count integer,
                                        Temperature real,
                                        DistanceOverAll real,
                                        CyclesOverAll integer,
                                        MotorCurrent real,
                                        DB_String text
                                    ); """

    # create a database connection
    conn = create_connection(database)

    # create tables
    if conn is not None:
        # create projects table
        create_table(conn, sql_create_projects_table)      
        conn.close()
    else:
        print("Error! cannot create the database connection.")

def create_project(conn, project):
    """
    Create a new project into the projects table
    :param conn:
    :param project:
    :return: project id
    """
    sql = ''' INSERT INTO projects(name,time,Count,Temperature,DistanceOverAll,MotorCurrent,CyclesOverAll,DB_String)
              VALUES(?,?,?,?,?,?,?,?) '''

    cur = conn.cursor()
    cur.execute(sql, project)
    conn.commit()
    return cur.lastrowid

###########################################################
#   main routine
###########################################################

if __name__ == "__main__":
    plc = snap7.client.Client()
    IPAdress = input("Input IP-Adress and press enter to start operations...")
    if IPAdress == '':
        IPAdress = "10.204.5.11"
    print('connect to ' + IPAdress)
    plc.connect(IPAdress,0,0)
    itemlist = filter(lambda a: a!='',db.split('\n'))
    deliminator='\t'
    items = [
        {
            "name":x.split(deliminator)[0],
            "datatype":x.split(deliminator)[1],
            "bytebit":x.split(deliminator)[2]
         } for x in itemlist
    ]
    #get length of datablock
    DBlength = get_db_size(items,'bytebit','datatype')

    #main loop
    create_database(database)
    conn = create_connection(database)
    if conn is not None:
        print('conn opened: ', format(DateTime.now(), '%Y-%m-%d %H:%M:%S'))
        cursor = conn.cursor()

    OldCount = 0
    Start = True
    i = 1
 
    while Start:

        meh = DBRead(plc,30,DBlength,items)
       
        if meh.Count > OldCount:
            print('Abfrage Nr\t:', i)
            print('Count\t\t:',  meh.Count)
            print('Temperature\t:', "{:.1f}".format(meh.Temperature))
            print('DistanceOverAll\t:', "{:.1f}".format(meh.DistanceOverAll))
            print('CyclesOverAll\t:', meh.CyclesOverAll)
            print('MotorCurrent\t:', "{:.3f}".format(meh.MotorCurrent))
            print('DB_String\t:\t', meh.DB_String)
            OldCount = meh.Count
            i = i + 1

            project = (i, format(DateTime.now(), '%Y-%m-%d %H:%M:%S'), meh.Count, "{:10.1f}".format(meh.Temperature), "{:10.1f}".format(meh.DistanceOverAll), meh.CyclesOverAll, "{:2.3f}".format(meh.MotorCurrent), meh.DB_String)
            project_id = create_project(conn, project)      

    conn.close()
    print('conn closed: ', format(DateTime.now(), '%Y-%m-%d %H:%M:%S'))
    plc.disconnect()
 
Bin jetzt so weit dass die Tracefunktion läuft.

Mein Plan war einfach wenn die Kunde meldet es hat estwas passiert, und die Trace gestoppt, dann online zu gehen und die Daten durchblättern um zu sehen wo was verdächtiges passiert.
Aber jetzt habe ich das Problem dass TIA kein Offline oder Online Sicht hat für Arrays.
Beobachtungstabellen für tausender von Arrayvariabeln will ich nicht gerne machen.

Eine Idée wäre die Daten mittels WinCC Advanced in ein CSV zu schreiben.
Aber Ich habe Arrays mit 32000 Werte. Bei 50 ms Traceaktualisierungszeit gibt es mir ein Trace Fenster von 25 Minuten.
Wenn ich diese Arrays mit WinCC Advanced Zeile für Zeile in ein CSV schreiben wurde, dann wurde es Stunden dauern.
Ein Array komplett einzulesen und auf einmal in die CSV schreiben geht nicht, weil WinCC erlaubt nur Arrays mit max 1000 Werte.

Hat jemand Idéen wie man diese Problem lösen kann ?
 
Deine Datenpunkte generell an eine time series data base schicken, zb Influxdb.. dann musst du nix exportieren und kannst dir die Daten dann für Zeitraum X anfragen.. oder hängst die direkt Grafana etc dran.. oder ein python script..
Danke, mit Influxdb und Grafana bin ich schon von meine Kompetenzen weck. Sicherlich ganz einfach wenn man weis wie. Wie immer.

Ich überlege jetzt diese Lösung mit die vorhandene 'Bordmitteln'.
Die Trace auf 1000 Werte pro Variabel begrenzen. Mit 50 ms Aktualisierungszeit gibt es mir 50 Sekunden Trace Fenster.
Dann kann ich es Einfach in ein gepufferte Trendanzeige in WinCC Advanced darstellen. Die Kunde kann das selber anschauen ohne dass ich online gehen muss.
Die Nachteil ist, man muss relativ schnell reagieren um die Trace zu stoppen.
 
Durch Experimentieren habe ich herausgefunden, dass die Grenze für die Anzeige einzelner Array-Werte bei 10.000 liegt.
Das gibt mir 500 Sekunden was viel akseptabler ist als nur 50 Sekunden.
Die Idée mit die WinCC gepufferte Trendanzeige probiere ich eventuell auch. Möglicherweise mit einer Funktion zum Vor- und Zurückblättern in den getracete Daten.
 
Zurück
Oben