Merker lesen mit Libnodave

Snoopy123123

Level-1
Beiträge
125
Reaktionspunkte
2
Zuviel Werbung?
-> Hier kostenlos registrieren
Habe folgendes problem: Ich möchte MD132 (Realwert) aus einer 3152dp lesen. SPS hängt via cp343 am ethernet. Die Verbindung via Libnodave steht auch. Ich kann auch werte aus DB's lesen jedoch nicht aus dem Merkerbereich.

Ich nutze Folgende Libnodave einstellungen.

DaveFlags
DaveDB ist 0
daveProtoISOTCP

Dazu folgender Delphi7 Code

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;

Wenn ich "nodave1.ReadBytes(DaveFlags,0,132,4);" auskommentiere dann startet die exe und edit2 wird sauber angezeigt. Nehm ich Read Bytes wieder in den Code dann hängt sich die Anwendung beim starten auf.

Weiss jemand was ich hier falsch mache ?!
 
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;

Delphi ist nicht gerade mein Fall, aber schreib mal bei
Code:
Gauge1.Value:= NoDave1.GetFloat(132);
stat der 132 eine 0 rein.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Nein dann funktioniert es auch nicht !

Sobal nodave1.ReadBytes(DaveFlags,0,132,4); drinsteht startet die anwendung nicht mehr. in Dave Read Bytes sollte ja ( Dave Area, DB, Start, Size) drinnstehen. Ich hab irgednwo gelesen das wenn auf den Merkerbereich zugegriffen wird in DB ein "0" drinstehen muss. Wenn ich DaveRead mit einem DaveDB aufrufe funktioniert es einwandfrei.

Ich bin Ratlos ?!?
 
procedure TNoDave.DoReadBytes(Area: TNoDaveArea; DB, Start, Size: Integer; Buffer: Pointer);

wenn du den internen Buffer nutz dann ist buffer = null wenn nciht da deinen Puffer angeben in den geschrieben werden soll. Evtl. liegt es daran.

P.S.: kein plan von Delphi ;)
und DaveFlags muss 0x83 entsprechen.

Gruß Key
 
Zuletzt bearbeitet:
Ich nutze den internen Buffer. Bei delphi kann mann die Angabe weglassen, dann ist der automatisch null [optionale uebergabevariable].

also daran liegts nicht.

noch jemand ne idee ???
 
hallo,

blöde frage, wenn es mit dem db klappt, warum machst du auf der sps nicht
einen transferbefehl von md132 in einen datenbausteinbereich?

mfg
 
Hi,

ich kann pm nur zustimmen.

Für eine Kommunikation SPS<->HMI würde ich mir sowieso immer einen DB dafür anlegen.
Das ist übersichtlicher (auch in der selbstgeschriebenen Visu)!
Denn dann hast du alles, was du für die Visu brauchst, in einem DB, den du abfragen kannst. Aber auch in diesen DB kannst du Werte von der Visu schreiben und im SPS-Programm verwenden.

Gruß,
poppycock
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Es geht mir hier weniger darum wie finde ich einen Weg damit mein Programm läuft. Den habe ich schon lange gefunden.

Ich wüsste gerne was ich mit Libnodave falsch mache und weshalb das mit dem Merkerbereich nicht funktioniert.

Ausserdem gibts auch fälle ich denen man das SPS Programm nicht anfassen darf weils schon en alter schinken ist und es ja ach so gut läuft :)
 
Ja den hatte ich schon gelesen.

Ich habe auch meine Codeschnippsel so wie afk geschrieben hat bei DB eine Null reingeschrieben, aber Libnodave mag meine MErker trotzdem nicht lesen :-(
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
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;

Wenn ich "nodave1.ReadBytes(DaveFlags,0,132,4);" auskommentiere dann startet die exe und edit2 wird sauber angezeigt. Nehm ich Read Bytes wieder in den Code dann hängt sich die Anwendung beim starten auf.

Naja, hört sich für mich ganz logisch an!
Das OnRead-Ereignis wird bei jedem Lesen aus der SPS ausgelöst. Also es wird zirkulierend aufgerufen, deswegen hägt sich dein Programm auf! ;)
 
Ich dachte das sei der Sinn des On Read Ereignisses. Wenn ich eine Druckanzeige habe dann will doch nicht von Hand ein ereignis triggern um den einen Wert angezeigt zu bekommen. Was mich verwirrt das das mit Area: Dave Db einwandfrei funktioniert. Auch mit eingestellten on read Trigger mit 50ms.

Mein programm sich auf weil es aus dem On Read nicht mehr herauskommt.

Nur weil ich etwas "zirkulierend" aufrufe hängt es sich doch nicht auf, dann würde es sich ja bei jedem Timerevent auch aufhängen, richtig ?
 
In der Funktion ReadBytes wird das Ereignis OnRead aufgerufen und wenn du im OnRead wieder ReadBytes ausführst wird auch wieder das Ereignis OnRead auferufen usw!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Was soll:
Code:
Gauge1.Value:= NoDave1.GetFloat(132);
edit2.Text:= intToStr(noDave1.CycleTime);
edit1.Text:= FloatToStr(NoDave1.GetFloat(132));
?
Wenn die Delphi-Unit nicht ganz anders funktioniert als der Rest der Bibliothek, sollte es heißen:
Code:
Gauge1.Value:= NoDave1.GetFloat();
edit2.Text:= intToStr(noDave1.CycleTime);
edit1.Text:= Gauge1.Value;
?
Erklärung:
GetFloat holt 4 byte aus dem Puffer und erhöht den Zeiger.
Es ist also keine Positionsangabe nötig. Sonst müßtest du mit GetFloatAt oder GetFloatFrom arbeiten.
Der Puffer enthält 4 Bytes, wenn du 4 gelesen hast.
Ein 2.Aufruf von GetFloat gibt zufällige Speicherinhalte zurück.
 
Tatsache ! Jetzt funktionierts. Vielen Dank.

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 ?!?
 
Hallo Zottel,

Verstehe ich es richtig:

"Gauge1.Value:= NoDave1.GetFloat(); " zieht 4 Byte aus dem Buffer und zählt den Zeiger hoch

"Gauge1.Value:= NoDave1.GetFloat(132); " zieht 4 Byte aus dem Buffer beginnend ab Byte 132 und zählt den Zeiger hoch
Wenn also Dave Read Byte ab Byte 0 durchgeführt wurde bekomme ich MD132
und wenn Dave Read Byte ab Byte 100 durchgeführt wurde bekomme ich MD32

Hab ich das so richtig verstanden ?!
 
Habe gerade mal
"Gauge1.Value:= NoDave1.GetFloat(); "
eingegeben aber mein Delphi Compiler benötigt die Positionsangabe.

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?
 
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 !!
Zunächst mal ist PEWs lesen keine gute Idee. Die CPU muß dann zusätzliche Buszugriffe auf die Peripherie ausführen. Ist echt langsam.
Wie bewerkstelligt man das am besten.
Lesen aus verstreuten Speicheradressen kann man bis zu einem gewissen Umfang mit:
davePrepareReadRequest
daveAddVarToReadRequest
daveExecReadRequest
in einer Abfrage zusammenfassen.
Grenzen setzen hier PDU-Länge und eventuell die CPU.
Diese Funktionen scheint die Komponente nicht zur Verfügung zu stellen...

Ansonsten ist es am günstigsten, verstreute Variablen im SPS-Programm in einen Block zu kopieren und diesen "am Stück" einzulesen.

Grundsätzlich gilt: Jeder read-request kostet Zeit, bis die CPU antwortet.

Das ist auch bei jeder anderen Kommunikationsbibliothek 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.
 
Zurück
Oben