Merkerwörter mit C# und Libnodave aus SPS lesen und schreiben

Red-Sh4nks

Level-1
Beiträge
42
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo wieder mal.

Ich versuche schon seit geraumer Zeit einen eigenen
OPC-Server zu programmieren, welcher MW, Datenblöcke, Eingänge und Ausgänge lesen und schreiben kann.

Die SPS (S7-300 CPU 315) kann ich mit Hilfe des eingebetteten
S7online codes tadellos in Run und Stop befördern.

Beim lesen der MW und DB bin ich aber auf ein Hinderniss gestoßen!
Laut der beigelegten Doku von Libnodave unter "area" werden MW
wie folgt definiert: z.B. MW4:
daveReadBytes(dc,daveFlags,0,4,2,null)

In meinem Programm ist der Befehl "daveReadBytes" aber nicht vorhanden.
Habe die libnodave.net.dll aber eingebunden.

Es gibt aber eine ähnliche Funktion mit anderen Parametern:
dc.readBytes(int area, int DBnumber, int Start, int len, byte[]buffer)
(dc = libnodave.daveconnection)

1. Wurde die Funktion daveReadBytes durch Readbytes ersetzt und ist die in der Doku beschriebene Funktion lediglich veraltet? (Version 0.8.1)
2. Oder muss ich die andere Libnodave.dll auch einbinden um an diese funktion zu gelangen? Wenn ja. Wie?

Ich hab mal mit dem dc.readbytes gearbeitet und folgendes programmiert:
Angenommen ich will den MW10 lesen

int MWnr = 10;
dc.readBytes(libnodave.daveFlags, 0, MWnr, 2, null); //gibt 0 zurück
int erg = dc.getU32();
txt_ausgabe.text = erg.tostring();

Bekomme abnormale Ergebnisse raus:
bei MWnr = 50, erg = 6553610
bei MWnr = 10, erg = 84541450
bei MWnr = 100, erg = 10

werde daraus nicht wirklich schlau...

3. Könnt ihr mir bitte helfen meinen Fehler zu finden?

Ich hoffe ihr könnt mir helfen! :)

lg Marco*
 
1. Wurde die Funktion daveReadBytes durch Readbytes ersetzt und ist die in der Doku beschriebene Funktion lediglich veraltet? (Version 0.8.1)
Die Funktion ist die gleiche. Du hast wahrscheinlich in der Dokumentation des C-Codes nachgesehen.
Da es in C keine Klassen und Namespaces gibt, gibt man den Funktionen entsprechende eindeutige Namen. Da in C# alle Methoden zur libnodave-Klasse gehören, kann man sich den "dave"-Prefix schenken.

2. Oder muss ich die andere Libnodave.dll auch einbinden um an diese funktion zu gelangen? Wenn ja. Wie?
S.O.
Wirf mal einen Blick in die libnodave.net.cs Datei, denn in der wird die eigentliche C-dll eingebunden. Dort kann man sehen wie die Namen der Methoden umgesetzt werden.

Ich hab mal mit dem dc.readbytes gearbeitet und folgendes programmiert:
Angenommen ich will den MW10 lesen

int MWnr = 10;
dc.readBytes(libnodave.daveFlags, 0, MWnr, 2, null); //gibt 0 zurück
int erg = dc.getU32();
txt_ausgabe.text = erg.tostring();

Bekomme abnormale Ergebnisse raus:
bei MWnr = 50, erg = 6553610
bei MWnr = 10, erg = 84541450
bei MWnr = 100, erg = 10
Ein Merkerwort hat 2 Bytes. Du liest auch nur 2 Bytes aus der SPS aus. Mit getU32() liest du aber 4 Bytes aus dem Empfangspuffer. Dort stehen dann undefinierte Werte drin (oder welche aus dem letzten Telegramm). Wenn du dir die Hex-Darstellung deiner abnormalen Ergebnisse ansiehst kannst du an den Bitmustern feststellen, dass sich die 50 und die 10 auch dort finden lässt.
Ergo: Wenn du nur 2 Bytes aus der SPS liest, darfst du auch nur 2 Bytes aus dem Puffer lesen (getS16 oder getU16).
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Herzlichen Dank für die schnelle und vor allem eminent
hilfreiche Antwort Thomas! :)

Mit GetU16() bekomme ich die gewünschten Werte.
Ich bin auch in der Lage Eingänge und Ausgänge zu
lesen. Beim E und A setzen bin ich aber wieder auf
eine Hürde gestoßen.

Angenommen ich will auf Eingang 3 "1" setzen.
Dann wende ich die Funktion dc.writeBytes an.

geforderte Parameter:
dc.writeBytes(int area, int DBnumber, int start, int len, byte[] buffer)

mit eingesetzen Parametern:
dc.writeBytes(libnodave.daveinputs,0, 3,1,null);

Jedoch wird hier kein Wert mitgegeben, was überhaupt
in den Eingang reingeschrieben werden soll (in diesem
Fall eine 1) Wo kann ich diesen Wert mitgeben, oder
habe ich in der Parameterübergabe einen Fehler?

Mein obriger Befehl wird garnicht ausgeführt:
"Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben."

lg Marco*
 
Der Code sieht wie folgt aus:

int eingangsnr = 0;
int zusetzenderwert = 1;
int test;
int a = 0x01

byte[] b;
b = new byte[1];
b[0] = zusetzenderwert;

test = dc.writeBytes(libnodave.daveInputs, 0, eingangsnr, 1, b)


die Variable test erhält jedesmal den Wert 0. Also wird
alles schonmal korrekt ausgeführt. Bei den Eingängen verändert
sich jedoch nichts. Hab alles mit dem Byte so gemacht wie du gesagt
hast Rainer.

Außerdem hab ich noch die im Testprogramm angegebene
Zeile ausprobiert und statt dem byte[] b

BitConverter.GetBytes(a)

eingesetzt. Hilft leider auch nichts...

lg Marco*
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Eingänge beschreiben? Könnte eher sein, das das gar nicht geht, denn die Eingänge werden ja nach dem "beschreiben" durch den PC von der SPS aktualisiert und demzufolge mit den echten Eingangswerten versorgt.
 
Eingäge beschreiben geht bei der 300er, wenn keine physikalische Hardware vorhanden ist. Ansonsten werden die gerade geschriebenen Werte beim nächsten OB 1 Durchlauf wieder durch die SPS überschrieben.
 
Bin leider kein Profi auf dem Gebiet und kann mit
deiner Antwort wenig anfangen. Ich werde mich mal
mit meinem Professor am Dienstag unterhalten und
in Erfahrung bringen was eine Eingangskarte ist und
wie ich eine solche deaktiviere...

lg Marco*
 
Die kannst Du nicht deaktivieren (außer durch Ausbau ;-)). Du kannst dann nur andere Adressen im Funktionsaufruf verwenden.
Wie sieht denn Deine Hardwarekonfig aus? Welche Karten hast Du denn verbaut?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hat etwas gedauert deine Frage zu beantworten ^^
Ich hoffe meine Angaben sind hilfreich:

Meine Schnittstelle ist eine CP5611 und ist
mit einer CPU 315 2DB verbunden.

Sreenshot zu HW Konfig:
http://www.imagebanana.com/view/knomj0cw/hwconf.bmp.png

Tut mir leid für diese wl nicht richtige Antwort auf
deine Frage, aber ich bin nur Programmierer bei diesem
Projekt. Ich werde aber spätestens am Dienstag eine
genaue Antwort auf deine hier posten ;-)

Falls jemand Interesse an diesem OPC-Server hat, ich
werde ihn, sobald ich ihn fertiggestellt habe hier zum Download
zur Verfügung stellen.

PS:Screenshots kann ich jederzeit auf Anfrage liefern ^^

lg Marco*
 
Wie Du siehst, ist auf E0..3 eine Eingangsbaugruppe parametriert. Daraus folgt messerscharf, dass diese Eingangsbytes immer von der SPS überschrieben werden. Teste das Ganze doch mal mit EB 4 ;-).
 
Mit EB4-EBn funktioniert auch nichts...
habe jeden einzelnen durchgetestet.

Ich hab vermutlich nen kleinen Fehler im
Programm. Daher hier ein Screenshot
welcher die Funktion Eingänge setzen
und das Programm (bis jetzt) zeigt.

Screenshot:
http://www.imagebanana.com/view/57qhcaaw/Eingngesetzen.bmp.png

Die letzte Meldung "Der Vorgang wurde ausgeführt"
ist nicht zu beachten, da das ganze noch etwas schwammig
programmiert ist, denn der Vorgang zeigte kein erkenntliches
Ergebnis...

Beim Lesen der Datenblöcke bin ich auch auf
einen merkwürdigen Fehler gestoßen:

int dc.ReadBytes(libnodave.daveDB, 5,0,4,null)
gibt bei mir immer den Wert 10 zurück. Dabei sollte
sie aber 0 zurückgeben.

Hab schon alles ausprobiert:
anstatt 5: jede beliebige Zahl von 0-50
anstatt 0: jede beliebige Zahl von 0-50
anstatt der Länge 4 auch mal 2
und anstatt null ein Bytearray

Bekomme jedoch immer 10 zurück. 10 deutet
laut der Libnodave Doku auf einen Fehler
der SPS hin...

Wisst ihr wo mein Fehler liegt?

lg Marco*
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Auflösung

Ärgerlicher Fehler...

Die Rückgabewerte von den Funktionen deuten ja auf bestimmte Fehler oder korrekte Ausführung hin.

0... ausgeführt
10... Datenblock existiert wahrscheinlich nicht...

Ich habe jede DB-Nr ausprobiert und dann feststellen müssen, das
alle Datenblöcke, die sich auf der SPS befanden, gelöscht wurden, bevor
ich diese SPS zum programmieren erhielt, um meine Arbeiten nicht zu behindern *ROFL*

Lösung:
Eine Datenblocknr als Parameter mitgeben, bei der der Datenblock auch wirklich existiert. Die maximale Länge sollte dabei nicht überschritten werden, da sonst alle Ergebnisse 0 sind und der Rückgabewert der Funktion 5 ist --> außerhalb des Lesebereichs ;-)
 
Zurück
Oben