Zählerstandserfassung/Pointer

Johannes

Level-1
Beiträge
5
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leuts,
ich bin dabei so ca. 240 Elektrozähler an ein Gebäudeleitsystem zu hängen. Zur Erfassung der einzelnen Zählerstände werden S7 Baugruppen benutzt. Über CP`s geht es dann auf FMS zum Leitrechner.
Ich muß die Zählerstände von der GLT aus überschreiben können. Außerdem muß ich Parameter ( Anzahl der Stellen des Zählers und Impulse/Kwh) in die Siemens CPU schreiben können. Diese Werte stehen in Datenbausteinen. Da die GLT - Software nicht von Siemens ist und feste Routinen zum Beschreiben von Analogwerten fordert habe ich mich mit der indirekten Adressierung befasst und auch einige FC`s gebastelt die das Handling übernehmen. (funktioniert tadellos)

Code:
      L     0
      T     #ZAEHLER
LOOP: L     #ZAEHLER
      L     64
      >=I   
      SPB   ENDE
      AUF   #STAT_DB
      L     DBW [AR1,P#0.0]
      T     #ZSP
      UN    L      1.3
      UN    L      1.2
      U     L      0.2
      S     L      1.1
      UN    L      0.2
      R     L      1.1
      U     L      0.2
      U     L      1.1
      SPB   SWIW
      SPA   PASS
SWIW: AUF   #SW_DB
      L     DBD [AR1,P#0.0]
      AUF   #IW_DB
      T     DBD [AR1,P#0.0]
PASS: L     #ZSP
      AUF   #STAT_DB
      T     DBW [AR1,P#0.0]
      L     #ZAEHLER
      L     1
      +I    
      T     #ZAEHLER
      L     P#2.0
      +AR1  
      SPA   LOOP
ENDE: NOP   0
      L     0
      LAR1

Nun tut sich folgendes Problem auf:
Die Zählimpulse werden über digitale Eingänge eingelesen (Flanken).
Um zu vermeiden für jeden der 240 Zähler einen Bausteinaufruf zu tippen müßte es doch möglich sein, einen Eingangsbereich (z.B. EW32) in den Lokaldaten eines FC (FB) zu parametrieren und abhängig vom Bit (z.B. E32.0) die weitere Verarbeitung und damit auch das Abspeichern in die richtigen Datenwörter meiner Daten bausteine zu handeln.
Für einen Zähler sieht die Verarbeitung der Zählimpulse so aus:

Der Aufruf:

Code:
 UN(   
      U     E      4.0
      FP    "FM_Z1"
      )     
      SPB   PAS1
      CALL  "ZAHL_ST"
       ND    :="IW_ND_Z".IW_ND_Z1
       FAKTOR:="IW_F_Z".IW_F_Z1
       STAND :="IW_ZS".ZS_Z1
PAS1: NOP   0

und der Baustein:

Code:
      L     #ZAEHLER
      L     1
      +I    
      T     #ZAEHLER
      L     #ZAEHLER
      L     #FAKTOR
      <>I   
      SPB   m1
      L     #STAND
      L     L#1
      +D    
      T     #STAND
m1:   L     #STAND
      L     #ND
      <D    
      SPB   m2
      L     L#0
      T     #STAND
m2:   NOP   0
      L     #ZAEHLER
      L     #FAKTOR
      >I    
      SPM   m3
      L     0
      T     #ZAEHLER
m3:   NOP   0
      NOP   0


Kann mir da wer auf "die Sprünge" helfen?

freundliche Grüße
Hannes
 
Zuletzt bearbeitet:
Ich mach mal kurz einen Lösungsvorschlag.

Du nimmst ein Eingangswort deiner Zahler und erzeugst daraus Flanken:

geklaut bei @qm :ROFLMAO:
steigende, wortweise Flankenauswertung

L MW 100 // Altwert des Eingangswert laden (Flankenmerker)
L EW 0 // Eingangswert laden
T MW100 // Aktuelle Eingangswert in Altwert (Flankenmerker) transferieren
XOW // Altwert und Eingangswert ”EXKLUSIV-ODER” verknüpfen
L EW 0 // Eingangswert laden
UW // Ergebnis mit Eingangswert ”UND” verknüpfen
T MW 102 // Ergebnis auf Impulsmerkerwort ”steigend” transferieren
Im MW102 hast du jetzt Einsen stehen, wenn der entsprechende Eingang eine Flanke gebracht hat.
Das MW schiebtst du jetzt, nach rechts, immer solange, bis eine 1 rausgeschoben wurde.

SPP NEXT //Springe zur Sprungmarke NEXT, wenn das zuletzt geschobene Bit (A1) = 1 ist.

Das Schieben zählst du.
Am Input des FC hast du auch eine Variable, das wievielte EW du untersuchst.
Daraus kannst du dir erstmal einen Grundoffset für die DB's bilden.
Mit der Zählinformation aus dem Schieben errechnest du den Offset zu dem Datenwort, daß zum Eingang gehört.
Stehen die Daten an unterschiedlichen Stellen in den DB (wegen Byte/Wort etc.) kannst du ja für jeden DB eine eigene Berechnung machen.
Den Berechneten Offset, dann in einen Pointer überführen und die Daten hochzählen, bzw. umkopieren.
Das Schieben würde ich in einer Schleife machen, da hast du dann 16 Eingänge ausgewertet, sollte aber auch mit einem Doppelwort gehen.

Hoffe das gibt dir mal eine Anregung. :rolleyes:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Ralle,
danke für die Hinweise.
Die Idee mit dem kompletten Eingangswort (Doppelwort) ist gut nur müßte ich dann im ungünstigsten Fall 16 Eingänge für einen Zähler verwenden. (z.B. Zähler 17)
Wenn ich meinen Baustein zur Zählimpulsverarbeitung so aufrufen würde:
Code:
  CALL  "ZAEHL"
       Input:=E32.0
wäre dieses Problem erledigt. So müßten die Eingänge auch nicht hintereinander liegen. Man müßte dann nur noch, abhängig vom #Input festlegen wohin die Ergebnisse sollen. Kann man das irgendwie erfassen und in einen Pointer (AR) umsetzen?

freundliche Grüße

Hannes
 
Hallo Ralle,
danke für die Hinweise.
Die Idee mit dem kompletten Eingangswort (Doppelwort) ist gut nur müßte ich dann im ungünstigsten Fall 16 Eingänge für einen Zähler verwenden.

Hallo,

was Ralle meint ist das du 16 Zähler in einem Wort hast. Also E32.0 =Z1, E32.1=Z2 usw.
Du kannst die Pointerberechnung nur (sinnvoll) einsetzen wenn die Eingänge zusammenhängend sind, oder wenigstens in Teilen zusammen sind. Also z.B. ew32, ew40, ew 48...

Wenn deine Zähleingänge wild verteilt sind kannst du das nur über eine Tabelle machen in der steht welcher Eingang zu welchen Daten in welchem DB gehören, und dann kannst du es lieber gleich einzeln machen...
Über sowas macht man sich eigentlich vor dem programmieren Gedanken. Es gäbe dann noch die Möglichkeit für z.B. jedes EW in dem ein Zähler vorkommt einen DB anzulegen und darin dann die Struktur deiner Daten. Über das Bit kannst du dann den Offset errechnen (z.B. durch schieben) aber auch das ist Murks. Schön wirds nur wenn die Zähler wenigstens in Wörtern zusammenhängen...

Torsten
 
Hallo Thorsten,
Du hast ja vollkommen Recht. Natürlich wäre es viel schöner Alles von vorne herein ordentlich zu haben nur reden wir hier leider nicht von einer neuen Anlage. Es geht um ein Gebäudeleitsystem das schon einige Jahre existent ist. Die 240 Elektrozähler sind nicht alle auf einer CPU untergebracht sondern verteilen sich auf über 30 Adressen am Bus. Auch die S7 Programme habe ich teilweise übernommen und dabei schon sehr "nette Überraschungen" erlebt.
Bis jetzt wurde für jeden Zähler ein Bausteinaufruf:
Code:
  UN(   
      U     E      4.0
      FP    "FM_Z1"
      )     
      SPB   PAS1
      CALL  "ZAHL_ST"
       ND    :="IW_ND_Z".IW_ND_Z1
       FAKTOR:="IW_F_Z".IW_F_Z1
       STAND :="IW_ZS".ZS_Z1
PAS1: NOP   0
geschrieben und das über 200 mal!
Sorry, dass ich mich da etwas unklar ausgedrückt habe.
Umgestellt wurde nur die GLT-Software. Das hat einige Probleme gebracht die ich aber lösen konnte.

freundliche Grüße

Hannes
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

das sollte ja kein Vorwurf sein. Sorry wenns so rübergekommen ist.
Vielleicht verstehe ich dein Problem ja auch nicht richtig, aber die indirekte Adressierung kannst du natürlich nur benutzen wenn es einen Zusammenhang zwischen Eingang und Daten gibt. D.h. du brauchst eine Formel mit der du von dem Eingang auf eine Adresse schliessen kannst, anders geht es nunmal nicht. Wenn du die Adresse nicht berechnen kannst, bringt das alles nichts. Sich diesen Zusammenhang nachträglich über Tabellen zu schaffen macht keinen Sinn. Eine weitere Möglichkeit um von den 200 Aufrufen wegzukommen wäre ein Aufruf mit der Übgabe von vielen Einzeleingängen. Z.B einem Baustein wo du dann 16/32/64 Eingänge als Parameter übergibst, und die Zähler im Baustein dann hintereinander nummerierst. Im Baustein selbst kannst du dann eine Schleife laufen lassen, die die Flanke prüft und ggf. zählt. Aber auch das bringt keinen richtigen Vorteil, ausser das es etwas Kompakter wird. Ausserdem geht der von aussen Sichtbare Zusammenhang zwischen Eingang und Zähler flötten.

Torsten
 
@Johannes

Ah, ich hatte deine Frage etwas anders verstanden.
In dem Fall würde ich 2 In-Variablen vorgeben, den Eingang und eine Nummer. An Hand der Nummer, würde ich dann über indirekte Adressierung auf die Datenbausteine zugreifen um die benötigten Daten zu holen, zu berechnen und abzulegen.
Es wäre auch ein DB möglich, in den du einen Code für deine Eingänge ablegst (Z.Bsp. 1Byte für die Wortadresse, 1Byte für die Bit-Adresse), den kannst du dann durchlaufen lassen und aus den hinterlegten Bytes deine Eingangsadresse berechnen und den Eingang so variabel einlesen. Mit 3 Werten (Zählernummer, Wortadresse, Bitadresse) wäre dann alles benötigte im DB hinterlegbar und du kannst den FC in einer Schleife durchlaufen lassen und die Inputs für den FC aus dem DB laden.
 
Hallo Leuts,
@ Thorsten
Manchmal ist es schwierig ein Problem richtig zu umschreiben. Ich hätte nur etwas ausführlicher sein sollen. Danke für Euer Verständnis.
@ Ralle
Vielen Dank! Das mit der Übergabe von zwei Variablen ist eine gute Lösung. Frag mich bloß warum ich da nicht drauf gekommen bin. Manchmal sieht man wirklich den Wald vor Bäumen nicht!
Ich muß dazu sagen, dass ich nur sporadisch mit der S7-Programmierung zu tun habe. (kann auch nicht sagen, dass mir das Spaß macht!)
Ich werde nun wie gesagt zwei Varablen beim FC-Aufruf übergeben. Den zugehörigen Eingang und die passende Zählernummer. Die passenden Datenwörter dann der richtigen Zählernummer zuzuweisen sollte selbst ich fertigbringen. Zwar muß ich den Aufruf x Zähleranzahl machen aber ich komme mit dem bestehenden Zustand nicht in Konflikte.

Vielen Dank für die Unterstützung,
ist ein prima Forum!

freundliche Grüße

Hannes
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ich denke auch der fc-aurfuf lässt sich über eine schleife machen.

ich denke mir das jetzt so.
du legst dir einen db an der folgendes enthält
dbb1 - ebyte -bytenummer des eingangs
dbb2 - ebit - bitnummer des eingangs
dbw2 - zaehler -zählernummer
das ganze für jeden zähler, also 240 mal

in der fc baust du dir deinen pointer auf das eingangsbit
l ebyte //32
sld3
lar 1
l ebit //1
+ar1
u e[ar1,p#0.0] //e32.1
und dann der rest
 
Zurück
Oben