CP 340 - Messwerte empfangen

Zuviel Werbung?
-> Hier kostenlos registrieren
Oh mann!

Da hab ich mich jetzt wohl zu früh gefreut oder wie?

Mein (haupt-) Problem hast du aber ja schon erkannt:

Der Kunde hat bereits jahrelang eine solche Kopplung laufen die eben mit dem CP340 so gemacht wurde und ich soll jetzt kommen und sagen daß das Kacke ist. Der wird natürlich sagen: "Da funktioniert es doch auch, warum also bei Ihnen nicht"?

Es wäre, wie ich das so sehe, generell möglich mit Folgetelegrammen zu operieren - bzw. durch entsprechende Verriegelungen der S/R FB´s mit jeweils anderen Parametern zu Arbeiten. Diese Arbeit wollte ich mir natürlich zunächst ersparen.

Momentaner Stand:

Ein DB welcher die 10byte mit den Sendedaten beinhaltet wird an den P_SEND übergeben. Dessen Enable-Bit wird vom Done-Bit des P_RCV zurückgesetzt und im nächsten Zyklus wieder automatisch gesetzt. Durch diesen Flankenwechsel geht das Spiel von neuem los. Das Enable-Bit des P_RCV bleibt statisch True.
Die so empfangenen Daten werden in einen separaten DB mit 4byte "Kopf" und einem ausreichend großen Array für die Nutzdaten reingeschrieben.
Die bislang empfangenen Nutzdaten sahen bis jetzt zumindest sehr vielversprechend aus - daher glaubte ich quasi schon am Ziel zu sein.
Das einzige was jetzt noch fehlt ist der endgültige Abgleich zwischen Quelle und Ziel um wirklich auf nummer sicher gehen zu können. Ein paar "markante Einzelwerte" konnte ich bereits als "richtig empfangen" zuordnen, daher war ich eben noch guter Hoffnung.

Falls das jetzt je so geht lasse ich das auch so - eben weil ich jetzt keinen Ärger will und es wohl die "letzte Kopplung dieser Art" sein wird (bei diesem Kunden zumindest...). Wenn ich das wo anders mal brauchen sollte kläre ich das natürlich ab daß ein CP341 zum Einsatz kommen MUSS.

Wenn nicht muss ich irgendwie belegen können daß die alte Kopplung auch schon fehlerhaft ist, aber die kam ja nicht von mir.

Schwierig, schwierig...
 
Stell doch mal Dein 10-Byte-Befehlstelegramm hier rein,
und gib an, auf welche Daten-Nummern in B&R Du zugreifen
musst. Vielleicht hat sich dann alles ganz schnell erledigt.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Stell doch mal Dein 10-Byte-Befehlstelegramm hier rein,
und gib an, auf welche Daten-Nummern in B&R Du zugreifen
musst. Vielleicht hat sich dann alles ganz schnell erledigt.

Das funktioniert ja schon...

Es geht jetzt ja nur noch um die max. Länge die mit einem Mal übertragen werden kann.
 
Lt. RK512 sind das max. 128Bytes, habe ich ja weiter oben
schon geschrieben. Allerdings gibt es in dem 10-Byte-Befehlstelegramm
auch einen Offset; der ist in Deinem Fall wohl 0.
Diesen Wert kannst Du erhöhen; musst aber beachten, dass er
max. 255 sein kann.
Und da lauert die nächste Falle: es hängt vom Datentyp auf den
zugegriffen wird ab, ob der Offset als Byte oder als Word gerechnet wird.
Gilt auch für die Anzahl.
(Nur deshalb wollte ich Deine Befehlssequenz sehen).

Nachtrag: die 128 Bytes verstehen sich ohne Folgetelegramme;
aber die willst Du ja gerade vermeinden!
 
Zuletzt bearbeitet:
Als Anmerkung beim Telegrammkopf steht:

Die RK512-Adressierung beschreibt Datenquelle und -ziel mit Wortgrenzen. Die Umrechnung auf Byteadressen in SIMATIC S7 erfolgt automatisch.

D.h. ich gebe im Byte5 die DB Nr. an und im Byte6 die Wort(DW)-Nr. an.
Hier habe ich momentan 0, richtig...

Ich habe den Telegrammkopf Byte für Byte im DB deklariert, ausser die letzten 2 - da habe ich ein Wort mit FFFF genommen (kein Koppelmerker).

Mein Aufbau:

01: B#16#0
02: B#16#0
03: B#16#45h // Fetch-Auftrag
04: B#16#44h // Quelltyp = DB
05: B#16#D //QuellDB = DB13
06: B#16#0 //QuellDBW=0
07: B#16#0 // Länge in Byte = 0 weil in 08 in Wort angegeben!
08: B#16#96h // Länge in Worten = 150 (geht aber nicht)
09: W#16#FFFF // Kein Koppelmerker

Ich werde es nun wohl so machen müssen:

Um die Länge nicht zu überschreiten brauche ich einen koordinierten Sende-/Empfangsablauf -> Ich hänge also für jeden Teil (max64Wort) einen Telegrammkopf hinten an den Kopf-DB. Je nach dem welcher Teil gerade dran ist schicke ich einen der "Köpfe".
In meinem Ziel-DB richte ich analog dazu weitere Empfangsfächer ein, da ja jedes mal ein Header mit übertragen wird - also einen neuen Header plus ein neues (Teil-)Array.

Jetzt muss ich nur noch dafür sorgen daß bei der Koordination nichts schief geht -> Die P_Send/P_RCV Bausteine dürfen ja nur einmal da sein ebenfalls der IDB (bezogen pro CP). Deshalb muss ich sie "einfach" abwechselnd mit anderen Telegrammköpfen und den passenden Zielbereichen aufrufen.

Hierzu sind natürlich Anregungen erwünscht, bin aber quasi schon dran...

Edit: Noch mal wegen der Byte/Wort Deklaration -> Oder ist das so gemeint daß wenn im Kopf das Byte07 ODER 08 verwendet wird auch im Byte06 das auf Byte/Wort angepasst sein muss ?
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Aha, DB-Zugriff also!
Nun, der ist immer wortweise; d.h. auch die Länge ist in Worten.
Mehr als 64 Worte benötigen die Folgetelegramme, aber bis 64
Worte geht es ohne!

Byte 7 ist das Highbyte, 8 das Lowbyte der Länge, gerechnet in
Worten.

Aber in Byte 6 gibst Du den Bereichsanfang ein.
Ebenfalls in Worten. Auf Byte 298 & Byte 299 des DB greifst Du direkt
zu, indem Du Byte 6 auf 149 setzt und als Länge 1 angibst.

Ich hoffe das hilft Dir weiter.
 
Ja, tut es...

Nur noch mal langsam zum Mitschreiben:

Ich will aus ein und dem selben DB ab DBW0 insgesamt 300 byte holen.

Ich würde es dann in 3*100 aufteilen wollen.

Jetzt immer auf die Bytenummer des Telegrammkopfs bezogen:

Teil 1 ist also:
06: B#16#0
07: B#16#0
08: B#16#32h // 50 Worte (ab DW0)

Teil 2:
06: B#16#32h // ab Wort 50 (= Byte100)
07: B#16#0
08: B#16#32h // 50 Worte (ab DW50)

Teil 3:
06: B#16#64h // ab Wort 100 (= Byte200)
07: B#16#0
08: B#16#32h // 50 Worte (ab DW100)

Ich dachte bisher dass die Bytes 07 und 08 wahlweise anzugeben sind - also entweder in Bytes oder in Worten - oder ist das falsch?
 
Ja, tut es...

Nur noch mal langsam zum Mitschreiben:

Ich will aus ein und dem selben DB ab DBW0 insgesamt 300 byte holen.

Ich würde es dann in 3*100 aufteilen wollen.

Jetzt immer auf die Bytenummer des Telegrammkopfs bezogen:

Teil 1 ist also:
06: B#16#0
07: B#16#0
08: B#16#32h // 50 Worte (ab DW0)

Teil 2:
06: B#16#32h // ab Wort 50 (= Byte100)
07: B#16#0
08: B#16#32h // 50 Worte (ab DW50)

Teil 3:
06: B#16#64h // ab Wort 100 (= Byte200)
07: B#16#0
08: B#16#32h // 50 Worte (ab DW100)

Ich dachte bisher dass die Bytes 07 und 08 wahlweise anzugeben sind - also entweder in Bytes oder in Worten - oder ist das falsch?


Das mit dem wahlweise ist falsch, denn Byte 7 und 8 bilden einen Wortwert.
Die drei Teile 1,2 und 3 sollten so richtig sein.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke.

Ich bin etwas irritiert von der Formulierung im Handbuch. Da steht:
07: Länge High-Byte Länge der zu übertragenden Daten je nach Typ in Byte oder
08: Länge Low-Byte Wörtern
(genau so steht´s da...)

Für Teil1 muss aber schon beim Beginn die 0 angegeben werden - oder die 1? (ich meine aber schon 0)
 
Byte 7 und 8 definieren die Anzahl der zu übertragenden Datenworte,
wenn es um DB geht, aber Datenbytes wenn es zB um Merker geht.

Dh. die Vielfachheit hängt nur vom Datentyp ab.

Byte 7 = 1 heißt Anzahl >= 256
 
Hallo, ich sitze jetzt schon seit heute morgen vor dem Elend und versuche das mit der Koordination des 3-teiligen Empfangs auf die Reihe zu kriegen -> Katastrophe!

Es ging mal so halbwegs, aber dann kam es immer wieder vor daß aus dem Puffer der CP noch was "altes" in den nächsten Bereich geschrieben wurde.

Bislang habe ich es noch so probiert an P_RCV und P_SEND den selben Instazdatenbaustein zu lassen, einen Versuch noch und dann stelle ich um.

Falls wer noch spontan einen Einfall dazu hat - ich schaue regelmäßig hier vorbei, und danke schon mal (wollte eigentlich heute fertig werden...)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Katastrophe !

Es ging mal so halbwegs, aber dann kam es immer wieder vor daß aus dem Puffer der CP noch was "altes" in den nächsten Bereich geschrieben wurde ...

? ... wie soll das gehen, dann hättest du ja eine Durch-Mischung der drei Teil-Aufträge.
Du fragst doch w50..99 erst an, wenn du w00..49 erhalten hast ... oder ?

Gruß
LL
 
Ja, theoretisch schon...

Ich wollte es so machen daß ich über eine Zeit die im Hintergrund läuft 3 Zonen baue von der jeweils nur eine scharf ist.

In diesen Zonen habe ich dann die Freigabe gemacht und die Parameter "DBB_NO" (Quell-DB mit Telegrammkopf und Ziel-DB Bereich) geändert.

Wenn sich aber der Wechsel mit einem laufenden Auftag überschnitt kam das zu stande.

Ich habe mich dann mit S/R Verriegelungen so überschlagen daß ich irgendwann selbst nicht mehr durchblickte. Es fehlt eben auch noch am prinzipiellen Verständnis wie die Sende- und Empfangs-FB´s auf einander abgestimmt sein müssen.

Bei meinem ersten Versuch mit Recieve_Enable = statisch TRUE und Empfang_beendet_ohne_Fehler hat Send_Enable getriggert hat es funktioniert - allerdings nicht mit ausreichender Länge -> daher jetzt das.

Nun habe ich mal pro Aufruf eine separate instanz genommen und alles wieder in die Zonen verpackt (vielleicht liegt hier ja schon der Denkfehler).

Vielleicht sollte ich das hintereinander laufen lassen und nur die Bits in den Zonen verriegeln?

1000 Möglichkeiten irgendwie aber die richtige finden...
 
... ich befürchte jetzt nur, dass deine 3 I-DB's das Problem vielleicht nicht wirklich lösen. Das Problem einer Teil-Durchmischung (jetzt nur mit alten Daten) besteht doch dann ggf. immer noch - oder nicht ...?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hiermit geht es mal so lala...

// Sequenz für Sende-/Empfangsfreigabe und Parametrierung erzeugen:
UN T 9
L 300 // Gesamtlaufzeit entsprechend der Zeitbasis (Wert*Basis)
ITB
L W#16#1000 // Zeitbasis W#16#0/1000/2000/3000 = 10ms/100ms/1s/10s
OW // Bildung des Zeitwerts incl. Zeitbasis für den Timer
SV T 9
// ************************************
// Teil 1:
CLR
L T 9 // Timerstand zum Vergleichen laden
L 300 // Restzeit für Vergleich entsprechend Zeitbasis (Wert*Basis)
<=I
TAK
L 200
>I
SPBN a001 // Wenn ausserhalb Bereich -> nächster
// Empfang immer ein ausser bei Reset(OB100):
SET
UN "P_RCV_R"
= "P_RCV_EN_R"
= "P_SEND_EN_R"
// Parameter ändern:
L 0
T "P_SEND_DBB_NO"
L 0
T "P_RCV_DBB_NO"
// ************************************
// ******** Empfangen *****************
// ************************************
// Daten empfangen:
CALL "P_RCV_OLD2" , DB102
EN_R :="P_RCV_EN_R"
R :="P_RCV_R"
LADDR :=768
DB_NO :=385
DBB_NO:="P_RCV_DBB_NO"
NDR :="P_RCV_NDR"
ERROR :="P_RCV_ERROR"
LEN :="P_RCV_LEN"
STATUS:="P_RCV_STATUS"

// ************************************
// ******** Senden ********************
// ************************************
// Wenn Empfang beendet Freigabe zurücknehmen:
U "P_RCV_NDR"
R "P_SEND_EN_R"
// Parameter für Empfang senden:
CALL "P_SEND_OLD" , DB103
REQ :="P_SEND_EN_R"
R :="P_SEND_R"
LADDR :=768
DB_NO :=343
DBB_NO:="P_SEND_DBB_NO"
LEN :=10
DONE :="P_SEND_DONE"
ERROR :="P_SEND_ERROR"
STATUS:="P_SEND_STATUS"
// Restzeit Bereich zum Rücksetzen der FBs
L T 9
L 180
<=I
= "P_RCV_R"
= "P_SEND_R"
SPA a003
a001: NOP 0
// ************************************
// Teil 2:
CLR
L T 9 // Timerstand zum Vergleichen laden
L 200 // Restzeit für Vergleich entsprechend Zeitbasis (Wert*Basis)
<=I
TAK
L 100
>I
SPBN a002 // Wenn ausserhalb Bereich -> nächster
// Empfang immer ein ausser bei Reset(OB100):
SET
UN "P_RCV_R"
= "P_RCV_EN_R"
= "P_SEND_EN_R"
// Parameter ändern:
L 10
T "P_SEND_DBB_NO"
L 104
T "P_RCV_DBB_NO"
// ************************************
// ******** Empfangen *****************
// ************************************
// Daten empfangen:
CALL "P_RCV_OLD2" , DB104
EN_R :="P_RCV_EN_R"
R :="P_RCV_R"
LADDR :=768
DB_NO :=385
DBB_NO:="P_RCV_DBB_NO"
NDR :="P_RCV_NDR"
ERROR :="P_RCV_ERROR"
LEN :="P_RCV_LEN"
STATUS:="P_RCV_STATUS"

// ************************************
// ******** Senden ********************
// ************************************
// Wenn Empfang beendet Freigabe zurücknehmen:
U "P_RCV_NDR"
R "P_SEND_EN_R"
// Parameter für Empfang senden:
CALL "P_SEND_OLD" , DB105
REQ :="P_SEND_EN_R"
R :="P_SEND_R"
LADDR :=768
DB_NO :=343
DBB_NO:="P_SEND_DBB_NO"
LEN :=10
DONE :="P_SEND_DONE"
ERROR :="P_SEND_ERROR"
STATUS:="P_SEND_STATUS"
// Restzeit Bereich zum Rücksetzen der FBs
L T 9
L 80
<=I
= "P_RCV_R"
= "P_SEND_R"
SPA a003
a002: NOP 0
// ************************************
// Teil 3:
CLR
L T 9 // Timerstand zum Vergleichen laden
L 100 // Restzeit für Vergleich entsprechend Zeitbasis (Wert*Basis)
<=I
TAK
L 20
// >I
SPBN a003 // Wenn ausserhalb Bereich -> nächster
// Empfang immer ein ausser bei Reset(OB100):
SET
UN "P_RCV_R"
= "P_RCV_EN_R"
= "P_SEND_EN_R"
// Parameter ändern:
L 20
T "P_SEND_DBB_NO"
L 208
T "P_RCV_DBB_NO"
// ************************************
// ******** Empfangen *****************
// ************************************
// Daten empfangen:
CALL "P_RCV_OLD2" , DB106
EN_R :="P_RCV_EN_R"
R :="P_RCV_R"
LADDR :=768
DB_NO :=385
DBB_NO:="P_RCV_DBB_NO"
NDR :="P_RCV_NDR"
ERROR :="P_RCV_ERROR"
LEN :="P_RCV_LEN"
STATUS:="P_RCV_STATUS"

// ************************************
// ******** Senden ********************
// ************************************
// Wenn Empfang beendet Freigabe zurücknehmen:
U "P_RCV_NDR"
R "P_SEND_EN_R"
// Parameter für Empfang senden:
CALL "P_SEND_OLD" , DB107
REQ :="P_SEND_EN_R"
R :="P_SEND_R"
LADDR :=768
DB_NO :=343
DBB_NO:="P_SEND_DBB_NO"
LEN :=10
DONE :="P_SEND_DONE"
ERROR :="P_SEND_ERROR"
STATUS:="P_SEND_STATUS"
// Restzeit Bereich zum Rücksetzen der FBs
L T 9
L 20
<=I
= "P_RCV_R"
= "P_SEND_R"
SPA a003
a003: NOP 0

Der Code wurde schon zig mal geändert, ist eben mal ein aktueller Schnappschuss...

Ich setze jetzt in den letzten 2 sekunden jeder Zone beide FBs zurück -> geht auch, nur der Knackpunkt ist wohl noch daß da wiederum das Ende vorher abgewartet werden sollte?

Na ja egal, schaut´s euch halt mal an...
 
Hallo RS,
ich habe da gerade mal meinen Fundus durchsucht. Da gibt es ein zwar nicht von mir geschriebenes aber funktionsfähiges CP340-Programm. Nicht so schön wie deins (vor allem nicht so anspruchsvoll), aber ...

Beim Senden wir dort als Weiterschalt-Bedingung das DONE-Bit abgefragt und beim Empfangen das NDR-Bit und die Rcv_Len. Letztere wurde vorher zurückgesetzt (weiß nichtt ob das was bringt).

Senden war erledigt wenn DONE, dann gings zum Empfangen. Dies dann wenn NDR und LEN = erwartete Länge. Wieder Senden ...
Keine Zeit-Steuerung - nur ein Timeout. Wenn Timeout, dann hat es nicht geklappt und Fehler und neuer Versuch (? nach weiterer Zeit ?).

Das Listing hier einstellen bringt nicht, weil 1. in SCL und 2. unübersichtlich (das geht auch in SCL). Vielleicht hilft es dir trotzdem weiter ...

Gruß
LL
 
Diese Lösung die ich gepostet habe ist schon wieder gelöscht...

Es muss machbar sein das in einem Bruchteil von Zeilen zu lösen -> nur dann geht´s auch, meistens.


Dein Hinweis zu dem Programm nehme ich gerne entgegen, was hat es denn gemacht? "Nur" einen (immer den selben) Bereich empfangen?

Die vorgehensweise erst wenn das Senden Fertig ist zu empfangen verwirrt mich ein wenig - auf grund des Telefonats mit Siemens neulich, daher ging ich immer davon aus dass gleichzeitig gesendet und empfangen werden muss?? Schon komisch, daß sich da alle so uneinig sind - für mich war das ganze bis jetzt ein riesen Griff ins Klo.

Ich habe schon einen neuen Weg in Arbeit - ohne Zonen, nur mit Bits zum sperren/freigeben eventuell kann ich von deinem Hinweis was verwerten.

Zwischendurch könnte ich manchmal an der glatten Wand hoch, grr! (aber es hilft ja auch nix)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo RS,
ich habe dir nur eine Interpretation von dem geschrieben, was "mein" Programm macht. Diese liest 2x und schreibt 2x. Empfangen werden 16 Bytes, gesendet so wie bei dir.
Das mit dem Senden und Empfangen nacheinander ist bei mir so gemacht. Müßte aber nach der Beschreibung deiner Aufgabenstellung bei dir ähnlich sein, da du ja auch erst sagst, was du haben willst und das dann in der Zustellung erwartest - das ist für mich nicht gleichzeitig ...

Ach ja, ich wollte dich nicht ärgern und auch nicht, dass du dich ärgern mußt. Tut mir leid, dass dieser Job Scheiße ist. Ich persönlich mag so etwas auch nicht und bin (bis jetzt) um so etwas auf SPS-Basis auch immer herumgekommen. Aber das hilft dir ja wenig.

Gruß
LL
 
Im Prinzip kannst Du den Empfang immer erlauben.
Du solltest das auch tun, um Fehlerzustände zu erkennen.

Wenn Du eine Anforderung sendest, prüfe ob was im Empfangspuffer steht
und schmeiß das weg. Solange der Sendevorgang andauert, darf
eigentlich nichts empfangen werden, es sei denn, die 3964(R) Priorität
ist falsch eingestellt und/oder es sind Übertragungsfehler aufgetreten.
Das ist dann auch ein Fehler: warte ein Weilchen und beginne von vorn...

Die Daten aus dem selben Block in drei Happen lesen bringt
erstmal niemand durcheinander. Erst wenn sich die Daten in der
Zwischenzeit ändern wird es interessant. Für diese Fälle
gibt es Verfahren, um Inkonsistenzen zu vermeiden.

Eines verwendet zB ein Freigabe-Bit/Byte/Word, das der Partner
bei Lesen fertig zurücksetzt.

Ein anderes liest die Daten einfach mehrmals und erkennt sie als gültig,
wenn sie sich zwischenzeitlich nicht geändert haben....
 
Empfang immer erlauben?

Aber wie soll ich das jetzt unter einen Hut kreigen da ich ja drei verschiedene Ziele angeben muss?

So langsam verstehe ich gar nichts mehr...

Ich bin heute auch ziemlich enttäuscht da einfach nichts ging (war den ganzen Tag vor dem Schrank gesessen und hab alles mögliche probiert)

@Larry: Ich habe mal probiert nur den Kopf zu senden - sonst gar nichts, da kam nicht ein mal ein Lebenszeichen (TX/RX Led)...
Auch anschliessend zu empfangen war nichts.
[\Larry]

Ich habe auch noch mal die Handbücher studiert, da wird dringend abgeraten verschiedene IDBs zu verwenden (für die selbe CP) - auch noch so ein Punkt wo ich vielleicht in der Sackgasse bin.

Wo ist denn jetzt der wirkliche Unterschied zur Vorgehensweise mit der CP341?

@ARGV: Du scheinst die Lösung zu kennen, willst sie mir aber nicht verraten?
 
Zurück
Oben