Merker lesen mit Libnodave

Zuviel Werbung?
-> Hier kostenlos registrieren
Dat jeht soo ...

Hallo,

Snoopy123123 schrieb:
Das bedeutet aber das man ganz schöne klimmzüge machen muss wenn man aus verschiedenen bereichen DaveDB oder DaveFlags oder directe PEW lesen muss, will !!

Wie bewerkstelligt man das am besten.

Am besten alles in der SPS in einen DB (möglichst zusammenhängend) rangieren und den DB mit LibohneDave in einem Rutsch auslesen. Unn fettisch ..

Gruß

Question_mark
 
Möglicherweise sollte ich mich aus jeder Delphi-Diskussion raushalten...
Sehe gerade, daß TNoDave.GetFloat() intern daveGetFloatFrom() verwendet. Es wird daher kein Zeiger hochgezählt...

Um zu wissen, was die Adresse eigentlich bewirkt müßte ich erst die Funktion BufferAt verstehen...


Wieso schreibst du, daß es funktioniert?
Und dann wieder doch nicht?

Sorry meinte das es mit "Gauge1.Value:= NoDave1.GetFloat(132); " funktionert, aber ohne positionsangabe meckert Delphi und lässt mich nicht compilieren.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Com Library vs OPC-Server

Hallo,

Zottel schrieb:
und bei jedem OPC-Server so, auch wenn einige OPC-Server was anderes vermuten lassen: Obwohl man für jede einzelne Variable einige Millisekunden als Aktualisierungsintervall einstellen kann, kann das am Ende nicht einmal annähernd eingehalten werden.

Du kannst aber eine Kommunikationsbibliothek wie LibOhneDave oder AGLink nicht mit einem OPC-Server vergleichen. Das sind ganz unterschiedliche Ansätze ...
Bitte nicht Äpfel mit Birnen vergleichen. LibOhneDave oder AGLink machen Lese/Schreibzugriffe auf die SPS nur bei impliziten Funktionsaufrufen der Kommunikationsbibliothek durch den Anwender. Ein OPC-Server aktualisiert die OPC-Items in der vorgegebenen Aktualisierungsrate und hält die Daten in einem eigenen Cachespeicher. Dem OPC-Server kann ich eine Aktualisierungsrate vorschlagen. Und wenn diese erreicht werden kann, akzeptiert der OPC_Server meinen Vorschlag. Und antwortet anderenfalls auf meine Anfrage mit der bestmöglichen Aktualisierungsrate, die der OPC-Server seiner Meinung nach erreichen kann.
Also da gibt es eigentlich zwei unterschiedliche Cycle times :

1) Die Zeit für das Auslesen der OPC-Items von der SPS in den Cache des OPC-Servers
2) Das Zeitraster, mit dem der OPC-Server die Daten meinem OPC_Client zur Verfügung stellt.

Gruß

Question_mark
 
Du kannst aber eine Kommunikationsbibliothek wie LibOhneDave oder AGLink nicht mit einem OPC-Server vergleichen.
Doch, insofern, daß der OPC-Server eben so eine Kommunikationsbibliothek (oder vergleichbare integrierte Funktionen) benötigt, um mit der Steuerung zu kommunizieren. Dabei sendet er dann genau dieselben Requests ab und wartet genauso lange auf die Antworten.
Der Hersteller des OPC-Servers mag Gehirnschmalz in die geschickte Zusammanfassung von Variablen investieren. Da hat er bei Siemens 2 Möglichkeiten:
1. Er kann Variablen in einem read request zusammenfassen.
2. Er kann, wenn MW 10 und MW24 benotigt werden, 16 Bytes ab MW10 lesen und die Variablen daraus extrahieren.

Aber wenn ich 40 Variablen aus 40 verschiedenen DBs angebe und 10ms Atualisierungszyklus einstelle, kann er das nicht im Traum einhalten.
Er kann nur dieselben Daten aus dem Cache öfter an den Client senden, aber der Cache ist halt veraltet.

Es sind eben KEINE verschiedenen Ansätze. Der OPC-Server setzt sich sozusagen aus Kommunikationsbibliothek, Thread zur Aktualisierung, Cache
und OPC-Schnittstelle zusammen (ob diese Funktionen in einem Programm ohne sichtbare Schnittstellen integriert sind, spielt keine Rolle).
 
Nicht doch Zottel ..

Hallo,

Question_mark schrieb:
LibOhneDave oder AGLink machen Lese/Schreibzugriffe auf die SPS nur bei impliziten Funktionsaufrufen der Kommunikationsbibliothek durch den Anwender. Ein OPC-Server aktualisiert die OPC-Items in der vorgegebenen Aktualisierungsrate und hält die Daten in einem eigenen Cachespeicher.

@Zottel

Ich zitiere mich eigentlich ungern selber, aber ausser einem gemeinsamen Kommunikationstreiber sind es doch unterschiedliche Konzepte.

Gruß

Question_mark
 
Zuviel Werbung?
-> Hier kostenlos registrieren
CycleTime

Hallo,

Zottel schrieb:
Er kann nur dieselben Daten aus dem Cache öfter an den Client senden, aber der Cache ist halt veraltet.

Immerhin kann ich beim Request an den OPC-Server angeben, ob ich Daten aus dem Cache oder immer expliziet aus der SPS lesen möchte. Und wer glaubt, für eine besch..ene Visu alle Daten der SPS im 10ms Raster anzeigen zu müssen, hat sowieso irgendetwas nicht verstanden (damit habe ich jetzt aber nicht Dich persönlich gemeint).

Gruß

Question_mark
 
Das bedeutet aber das man ganz schöne klimmzüge machen muss wenn man aus verschiedenen bereichen DaveDB oder DaveFlags oder directe PEW lesen muss, will !!

Wie bewerkstelligt man das am besten.

Mir fallen hier mehrere Möglichkeiten.

Mehrere NoDave Komponenten benutzen - nachteil belegt verbindungen zur SPS und nach ein paar (kommt auf die SPS an) ist schluss.

Ne Variable hochzählen und dave read ausführen ud dann nur die getbytes variablen ausführen die für diesen Bereich sind, aber wie stelle ich hier sicher das ich auch alle 100ms alle Datenbereiche einlese ?!?

Ich mach das mit der NoDave-Komponente immer so, dass ich das integrierte lesen normal nur dazu verwende um meine Verbindung prüfen zu lassen, das auf 1 Byte irgendwo auf der SPS ansetze und den Interval auf 500ms setze.

Damit ich dann aber doch an meine Daten komme hab ich für jede Verbindung einen seperaten Thread in dem ich die Daten auslese, aufbereite und dann an mein Hauptprogramm übergebe, was den rießengroßen Vorteil hat, dass das nicht mein Hauptprogramm stört (macht der Interval auch nicht, da der auch in einem seperaten Thread ist) und vor allem Kann ich viele Werte auf einmal aus verschiedenen Speicherbereichen auslesen. ;)
 
Ich komme mal auf den Anfang zurück, um die ursprüngliche Frage zu beantworten:

procedure TForm1.NoDave1Read(Sender: TObject);
begin
nodave1.ReadBytes(DaveFlags,0,132,4);
Gauge1.Value:= NoDave1.GetFloat(132);
edit2.Text:= intToStr(noDave1.CycleTime);
edit1.Text:= FloatToStr(NoDave1.GetFloat(132));
end;
...
Weiss jemand was ich hier falsch mache ?!
Der Fehler liegt, wie von Human schon erwähnt und wie du eigentlich bereits selbst erkannt hast, im Aufruf von DaveReadBytes innerhalb des OnRead-Events.

Es gibt 2 Anwendungsvarianten der Komponente:

  1. Die "quick and dirty" Variante für Anfänger und den schnellen Tests:
    In diesem Fall muß in den Properties Area, BufLen, BufOffs und ggf. DBNumber der Komponente eingestellt werden, was aus der SPS ausgelesen werden soll, und im Property Interval wird das Leseintervall in Millisekunden bestimmt. Die Komponente erzeugt dann einen eigenen Thread, der das zyklische Lesen aus der SPS durchführt und nach jedem erfolgreichen Lesen den OnRead-Event auslöst. Im Event darf dann logischerweise nicht noch mal von der SPS, sondern nur noch aus dem internen Puffer der Komponente gelesen werden (mit den Get..._Methoden). Diese Methode funktioniert sogar innerhalb der Delphi-IDE, ohne daß das Programm schon laufen muß (daher "quick and dirty"), daher kann man so im Objektionspektor überprüfen, ob die Kommunikation mit den Einstellungen der Properties überhaupt funktioniert (der aktualisiert allerdings nicht zyklisch, sondern immer nur einmalig jeweils beim Selektieren der Komponente).

  2. Die "professionelle" Variante für richtige Anwendungen:
    Bei dieser Variante wird das Property Interval auf 0 gesetzt, und die Properties Area, BufLen, BufOffs und DBNumber brauchen nicht eingestellt werden. Die Komponente erzeugt dann keinen Thread, der das zyklische Lesen aus der SPS übernimmt, die Komponente baut dann eigentlich "nur" noch die Verbindung zur SPS auf, sobald das Property Active auf True gesetzt wird. Das zyklische Lesen von der SPS muß dann aus dem Programm heraus durch Aufruf der Methode ReadBytes(Area, DB, Start, Size[, Buffer]) ausgeführt werden (z.B. per Timer oder Thread). Ob dabei mit dem internen Buffer der Komponente oder mit Buffern gearbeitet wird, die vom Programm bereitgestellt werden, hängt vom Anwendungsfall (und vom Programmierer) ab. Der Vorteil dieser Variante ist, daß man sämtliche Freiheiten hat zu bestimmen, aus welchem Adressbereich der SPS gelesen werden soll, da man diese Information ja mit jedem Aufruf von ReadBytes mitgibt.

In meinen eigenen Programmen (z.B. ein OPC-Server, soviel zum Thema "das sind zwei völlig unterschiedliche Konzepte" ;)) nutze ich ausschließlich die zweite Variante.


Gruß Axel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich zitiere mich eigentlich ungern selber, aber ausser einem gemeinsamen Kommunikationstreiber sind es doch unterschiedliche Konzepte.
Es sind unterschiedliche Konzepte im Hinblick wie die Daten dem Client/der Anwendung übergeben werden.

Der Hauptzweck des Caches ist, daß mehrere Clients Daten erhalten können und diese dazu nur einmal von der Steuerung geholt werden.

Aber bei der Kommunikation mit der Steuerung ist es dieselbe Scheiße mit denselben Beschränkungen der Bandbreite (=Datenvolumen/Zeit).
Ich bestehe auf dieser Klarstellung, weil ich hin und wieder Anfragen von Usern bekomme, die mir erzählen, daß sie an einem OPC-Server geile Aktualisierungsraten einstellen können und das für beliebig viele Variablen und dann müsse das Ding doch soviel leistungsfähiger sein als Libnodave. Das ist wie den Tempomat auf 1000 stellen können, aber die Karre macht nun mal nicht mehr als 90.

Unter "unterschiedlichen Konzepten" würde ich im Hinblick auf die Kommunikation mit der Steuerung etwas verstehen wie:
Der OPC-Server bezöge seine Daten aus einem mit der CPU geteilten "shared memory" (Denkbar bei Soft-SPS oder wenn ein Wkindows-Rechner als Koprozessor in einer S7 liefe und mit dieser dual ported RAM teilte).
 
Ich mach das mit der NoDave-Komponente immer so, dass ich das integrierte lesen normal nur dazu verwende um meine Verbindung prüfen zu lassen, das auf 1 Byte irgendwo auf der SPS ansetze und den Interval auf 500ms setze.

Damit ich dann aber doch an meine Daten komme hab ich für jede Verbindung einen seperaten Thread in dem ich die Daten auslese, aufbereite und dann an mein Hauptprogramm übergebe, was den rießengroßen Vorteil hat, dass das nicht mein Hauptprogramm stört (macht der Interval auch nicht, da der auch in einem seperaten Thread ist) und vor allem Kann ich viele Werte auf einmal aus verschiedenen Speicherbereichen auslesen. ;)

Super, vielen Dank ! Dieser hinweis hat mein Problem gelöst. Ich hab mich fälschlicherweise daran festgebissen das OnRead ereignis der Komponente benutzen zu müssen. Dachte das müsste so sein. Die Sache mit dem eigenen Tread funktioniert nun wunderbar ich ich kann in allen bereichen lesen und schreiben.

Was ich noch nicht so ganz verstehe wie du das mit dem Verbindung prüfen machst. Kannst du das mal genauer erklären ? Oder gibt es in der Komponente schon eine art Watchdog ?
 
Zurück
Oben