# Mittelwertbildung



## pinolino (23 Januar 2010)

Hallo Zusammen,
ich habe im Forum nach einer Art Anleitung gesucht, um eine Mittelwertberechnung durchzuführen. Dabei bin ich auf Folgendes (von *vierlagig*!) gestoßen:


```
[LEFT]L 8                                //Startadresse des Arrays
SLD 3                              //Pointererzeugen
LAR1                               //und ins Adressregister laden
L 7                                //Anzahl der Schiebevorgänge laden
nex1: T #iLoopCounter
L DID [AR1,P#4.0]                  //Startadresse + 1 DW
T DID [AR1,P#0.0]                  //in Startadresse schreiben
+AR1 P#4.0                         //und das AR1 um 4.0 erhöhen = neue Startadresse
L #iLoopCounter                    //Schleifenzähler laden
LOOP nex1                          //um ihn zu dekrementieren und zurückzuspringen[/LEFT]
 
[LEFT]L #rInput                          //und den aktuellen Wert
T #aRealArray[7]                   //ins Real-ARRAY schubsen[/LEFT]
```
 

So, nun sind beim Durcharbeiten leider schon die ersten Fragen aufgetaucht – es wäre super, wenn ihr mir etwas helfen könntet, damit ich den Aufbau richtig verstehe… 


1) Im AR1 steht ja zu Beginn: P#8.0

Es soll doch als erste Adresse die *Anfangsadresse* im Array „beschrieben“ werden – und diese erste Adresse ist doch *1* und nicht 8, oder?


2) L DID[AR1, P#4.0] ruft ja die Startadresse *+* 1 Doppelwort auf.

Warum ist es nötig, zusätzlich zur Startadresse noch ein Doppelwort zu laden?
Zu Beginn (also beim *ersten* Durchlauf der Schleife) muss doch der Zeiger auf die „Ursprungsadresse“ (in diesem Fall auf Adresse 8 im Array) zeigen…

3) „#rInput“ soll ja den aktuell anstehenden Wert, z.B. einen Messwert darstellen.

*Was *aber ist beim Aufruf des Bausteins für „#aRealArray[7]“ zu übergeben?


So, das wären zunächst einmal die ersten Fragen zu diesem Thema… wenn ich das verstanden habe, dann „forsche“ ich weiter… 

Vielen Dank schon mal bis hierhin für eure Hilfe!

Grüße

pinolino


----------



## spezy (23 Januar 2010)

Das Programm ist keine Mittelwertbildung, sondern ein Schieberegister.
Der erste Wert wird gelöscht. 
Die 2. bis 8. Werte werden an Stelle 1 - 7 verschoben 
und der neue Wert (#rInput) wie an die 8. Stelle geschrieben.

Beim Schieben müssen die Real-Werte noch addiert und durch 8 dividiert werden!


----------



## dalbi (24 Januar 2010)

Hallo,

schau mal hier http://www.sps-forum.de/showpost.php?p=119642&postcount=10

Gruss Daniel


----------



## pinolino (25 Januar 2010)

Danke für die Antworten,

aber so ganz hab ich es noch nicht verstanden...


Das Schieberegister soll doch *acht* Speicherplätze besitzen. Es werden aber nur *7* Schleifendurchläufe programmiert.

Und warum wird als Startadresse nicht "L DID [AR1, P#*0*.0]" sondern "L DID [AR1, P#*4*.0]", also genau 1DW höher gewählt? 

Danke, pinolino


----------



## Paule (25 Januar 2010)

pinolino schrieb:


> Das Schieberegister soll doch *acht* Speicherplätze besitzen. Es werden aber nur *7* Schleifendurchläufe programmiert.
> 
> Und warum wird als Startadresse nicht "
> 
> ...


Es werden 7 alte Werte verschoben, der 8.Wert ist ja der neue, der wird direkt rein geschrieben.

L DID [AR1, P#4.0] // Der zweite Wert
L DID [AR1, P#0.0] // wird auf den ersten geschrieben

Nach der 1.Schleife schaut es dann so aus.
Der Pointerversatz bleibt ja gleich aber das AR1 wird um 4 erhöht

L DID [AR1+4, P#4.0] // Der dritte Wert
L DID [AR1+4, P#0.0] // wird auf den zweiten geschrieben


----------



## pinolino (25 Januar 2010)

Paule schrieb:


> Es werden 7 alte Werte verschoben, der 8.Wert ist ja der neue, der wird direkt rein geschrieben.
> 
> L DID [AR1, P#4.0] // Der zweite Wert
> L DID [AR1, P#0.0] // wird auf den ersten geschrieben
> ...


 
Danke für deine Erläuterung, Paule!

Ich nehme an in den jeweils beiden unteren Zeilen muss statt dem L ein T stehen - für Transferieren?


Mein Problem - irgendwie komme ich mit dem Ablauf noch nicht zurecht:

Soweit ich es verstanden habe, wird das Array von *hinten nach vorne* ( Platz 8 bis Platz 1) aufgefüllt.

1) Beim *ersten* Durchlauf des Programms steht doch für die Anweisung ( Zeile 6 bis Zeile 8 ) noch gar *kein* Wert zur Verfügung. Der erste Wert wird doch erst in der *letzten *Anweisungszeile geladen und in das Array geschrieben.

2) Sehe ich es richtig, dass der 8. Wert (also der jeweils neue) direkt in das *7.* Feld des Arrays (T #aRealArray[*7*]) geschrieben wird?

3) Ist das Array dann wie folgt deklariert:

ARRAY [0..7] ?

Grüße
pinolino


----------



## vecoplaner (25 Januar 2010)

Hier mal ein Baustein wie ich ihn verwende.


```
FUNCTION_BLOCK "FB_Mittelwertbildung"
TITLE =Mittelwertberechnung/ Integrationsbaustein
AUTHOR : 'F.J.'
VERSION : 1.0


VAR_INPUT
  Eingangswert : REAL ;    //Zu Glätender Istwert
  Speichertakt : BOOL ;    //Abfragetakt des Eingangswert
  SPS_Start : BOOL ;    //Start der Berechnung
  Zyklen : INT ;    //Ringspeichergröße (Zyklen x Speichertakt = Integrationszeit)
END_VAR
VAR_OUTPUT
  Zeigernummer : WORD  := W#16#10;    
  Endwert : REAL ;    //Geglaeteter Wert
END_VAR
VAR
  Messwert_500 : REAL ;    
  .
  .
  .
  .   
  Messwert_1 : REAL ;    
  Store_Mitteln : INT ;    
  Store_Mitteln_1 : REAL ;    
  Store_Nullen : INT ;    
  DB_wurde_Genullt : BOOL ;    
  Mittelwert : BOOL ;    
  FP_Takt : BOOL ;    
END_VAR
VAR_TEMP
  Impuls_Takt : BOOL ;    
  Zeiger_Speichern : DWORD ;    
  Zeiger_Mitteln : DWORD ;    
  Zeiger_Nullen : DWORD ;    
  Loops_Nullen : INT ;    
  Loops_Mitteln : INT ;    
END_VAR
BEGIN
NETWORK
TITLE =Reseten

      U     #SPS_Start; 
      SPB   strt; 

      L     0.000000e+000; 
      T     #Endwert; 

      L     16; 
      T     #Store_Mitteln; 
      T     #Store_Nullen; 
      T     #Zeigernummer; 
NETWORK
TITLE =DB Werte Nullen wenn keine abfrage

      U     #DB_wurde_Genullt; 
      BEB   ; 

      L     #Zyklen; 
NEXT: T     #Loops_Nullen; 
      L     #Store_Nullen; 
      L     4; 
      +I    ; 
      T     #Store_Nullen; 

      L     #Store_Nullen; 
      SLW   3; 
      T     #Zeiger_Nullen; 

      L     0.000000e+000; 
      T     DID [#Zeiger_Nullen]; 

      L     #Loops_Nullen; 
      LOOP  NEXT; 
      S     #DB_wurde_Genullt; 
      BE    ; 

strt: NOP   0; 
      R     #DB_wurde_Genullt; 
NETWORK
TITLE =Abtasttakt
//im zeitintervall von x sekunden (arbeitstakt) wird ein neuer wert aufgenommen.
      U     #Speichertakt; 
      UN    #FP_Takt; 
      =     #Impuls_Takt; 

      U     #Speichertakt; 
      =     #FP_Takt; 

      U     #Impuls_Takt; 
      R     #Mittelwert; 
      SPBN  arbt; 
NETWORK
TITLE =Speicherzeiger prüfen wenn Speicherende erreicht
//wenn speicherzeiger grösser als 2012 (500 Messwerte) dann auf 16 
//setzen (zeiger für messwertNr.1) 
      L     #Zeigernummer; 
      L     4; 
      +I    ; 
      T     #Zeigernummer; 

      L     #Zyklen; 
      L     4; 
      *I    ; 
      L     12; 
      +I    ; 
      L     #Zeigernummer; 
      TAK   ; 
      >I    ; 
      SPBN  NULL; 

      L     16; 
      T     #Zeigernummer; 

NULL: NOP   0; 

NETWORK
TITLE =Eingangswert abspeichern

      L     #Zeigernummer; 
      SLW   3; 
      T     #Zeiger_Speichern; 
      L     #Eingangswert; 
      T     DID [#Zeiger_Speichern]; 

NETWORK
TITLE =Mittelwert aus DB errechnen

arbt: NOP   0; 
      U     #Mittelwert; 
      SPB   aus; 

      L     0.000000e+000; 
      T     #Store_Mitteln_1; 

      L     16; 
      T     #Store_Mitteln; 


      L     #Zyklen; 
Next: T     #Loops_Mitteln; 

      L     #Store_Mitteln; 
      L     4; 
      +I    ; 
      T     #Store_Mitteln; 

      L     #Store_Mitteln; 
      SLW   3; 
      T     #Zeiger_Mitteln; 
      L     DID [#Zeiger_Mitteln]; 
      L     #Store_Mitteln_1; 
      +R    ; 
      T     #Store_Mitteln_1; 

      L     #Loops_Mitteln; 
      LOOP  Next; 

      L     #Zyklen; 
      ITD   ; 
      DTR   ; 
      L     #Store_Mitteln_1; 
      TAK   ; 
      /R    ; 
      T     #Endwert; 

      S     #Mittelwert; 
aus:  NOP   0; 
      BE    ; 
END_FUNCTION_BLOCK
```

Cheers Flo


----------



## pinolino (25 Januar 2010)

Danke vecoplaner,

allerdings übersteigt dieser Baustein meine (derzeitigen) Kenntnisse!


Insofern wäre ich für eine Beantwortung meiner vorhergehenden Fragen sehr dankbar:

Mein Problem - irgendwie komme ich mit dem Ablauf noch nicht zurecht:

Soweit ich es verstanden habe, wird das Array von *hinten nach vorne* ( Platz 8 bis Platz 1) aufgefüllt.

1) Beim *ersten* Durchlauf des Programms steht doch für die Anweisung ( Zeile 6 bis Zeile 8 ) noch gar *kein* Wert zur Verfügung. Der erste Wert wird doch erst in der *letzten *Anweisungszeile geladen und in das Array geschrieben.

2) Sehe ich es richtig, dass der 8. Wert (also der jeweils neue) direkt in das *7.* Feld des Arrays (T #aRealArray[*7*]) geschrieben wird?

3) Ist das Array wie folgt zu deklarieren:

ARRAY [0..7] ?

Grüße
pinolino


----------



## vecoplaner (25 Januar 2010)

Achso, du möchtest mit einem Array arbeiten (hab den fred wohl zu sehr 
überflogen), der von mir gepostete Baustein bearbeitet einfach einen 
Realwert, speichert ihn und berechnet danach den Mittelwert. 
Also nicht das was du benötigst.


Gruß


----------



## pinolino (25 Januar 2010)

Ja, genau - ich wollte mich gerne an das Beispiel aus meinem 1. Thread halten und es durcharbeiten...


Allerdings ist mir aber der Ablauf noch immer nicht ganz klar; könnte hier bitte nochmals jemand helfen?


Soweit ich es verstanden habe, wird das Array von *hinten nach vorne* ( Platz 8 bis Platz 1) aufgefüllt.

1) Beim *ersten* Durchlauf des Programms steht doch für die Anweisung ( Zeile 6 bis Zeile 8 ) noch gar *kein* Wert zur Verfügung. Der erste Wert wird doch erst in der *letzten *Anweisungszeile geladen und in das Array geschrieben. Was passiert denn dann an dieser Stelle?

2) Sehe ich es richtig, dass der 8. Wert (also der jeweils neue) direkt in das *7.* Feld des Arrays (T #aRealArray[*7*]) geschrieben wird?

3) Ist das Array wie folgt zu deklarieren:

ARRAY [0..7] ?

Grüße
pinolino


----------



## Paule (25 Januar 2010)

pinolino schrieb:


> Soweit ich es verstanden habe, wird das Array von *hinten nach vorne* ( Platz 8 bis Platz 1) aufgefüllt.


Korrekt!


pinolino schrieb:


> Beim *ersten* Durchlauf des Programms steht doch für die Anweisung ( Zeile 6 bis Zeile 8 ) noch gar *kein* Wert zur Verfügung. Der erste Wert wird doch erst in der *letzten *Anweisungszeile geladen und in das Array geschrieben.


Ja, macht ja nix dann werden halt die Nullwerte rausgeschoben.


pinolino schrieb:


> Sehe ich es richtig, dass der 8. Wert (also der jeweils neue) direkt in das *7.* Feld des Arrays (T #aRealArray[*7*]) geschrieben wird?
> 3) Ist das Array dann wie folgt deklariert:
> ARRAY [0..7] ?


Ganz genau, Du könntest natürlich die Array Felder mit 1..8 benennen dann wäre es leichter lesbar.

Die erste 8 ist klar?
Da sich das Ganze in einem Instanz DB abspielt wurde ja im Deklarationsteil das Array gesetzt. Und diese Startadresse ist in dem Beispiel die Adresse 8


----------



## vierlagig (25 Januar 2010)

Paule schrieb:


> Die erste 8 ist klar?
> Da sich das Ganze in einem Instanz DB abspielt wurde ja im Deklarationsteil das Array gesetzt. Und diese Startadresse ist in dem Beispiel die Adresse 8



habe es mittlerweile in besagtem beispiel angepasst, da lautet es jetzt


```
*
      LAR1  P##aRealArray               //Startadresse des Arrays ins Adressregister laden
```
was die funktion besser beschreibt und sachlich richtiger ist ... danke für den hinweis pinolino

ansonsten, ja, das ist ein array[0..7] ... ich programmiere! da fängt die welt mit 0 an! for i=*0* to 7... U  M100.*0* usw.


----------



## pinolino (25 Januar 2010)

Vielen Dank für deine Hilfe, Paule!



Paule schrieb:


> Die erste 8 ist klar?
> Da sich das Ganze in einem Instanz DB abspielt wurde ja im Deklarationsteil das Array gesetzt. Und diese Startadresse ist in dem Beispiel die Adresse 8


 
Ja, denke diese erste 8 ist klar... somit könnte man für dieses Beispiel sagen, dass das Daten-Instanz-Doppelwort *8* des Instanz-DB´s die Startadresse angibt.

Nur, wo ist denn definiert, dass diese Startadresse ( also das DID8 ) dem Array-Feld* 7* zugeordnet ist? Wo ist der Bezug zwischen Startadresse und Array-Feld?

Danke
pinolino


----------



## Paule (26 Januar 2010)

pinolino schrieb:


> Nur, wo ist denn definiert, dass diese Startadresse ( also das DID8 ) dem Array-Feld* 7* zugeordnet ist? Wo ist der Bezug zwischen Startadresse und Array-Feld?


 Die Startadresse ist ja nicht dem Array-Feld 7 zu geordnet sondern dem Feld 1
Auf das Array-Feld 7 wird ja direkt zugegriffen.
Die direkte Zuweisung auf eine Adresse ( in diesem Fall 8 ) ist auch nicht sauber.
Aber 4L hat ja die bessere Lösung schon an seinem Beitrag geändert.


----------



## Paule (26 Januar 2010)

spezy schrieb:


> Das Programm ist keine Mittelwertbildung, sondern ein Schieberegister.
> Der erste Wert wird gelöscht.
> Die 2. bis 8. Werte werden an Stelle 1 - 7 verschoben
> und der neue Wert (#rInput) wie an die 8. Stelle geschrieben.
> ...


He Pinolino, 
jetzt wurden Dir hier schon verschiedene Lösungen angeboten.
Ist ja OK das Du Dich für die Lösung von 4L entschieden hast, aber da hat der Spezy mit seinem erst Beitrag absolut recht, die Daten hast Du jetzt erstmal verschoben. 
Von einem Mittelwert bist Du noch eine Addition und einer Division entfernt.


----------



## Buster (26 Januar 2010)

*Benutze fertigen Baustein SAMP_AVE*

In der CFC Library unter ELEM_300 gibt es einen fertigen Baustein zu Mittelwertbildung. FB4 "SAMP_AVE". Den benutze ich immer. Rufe ihn in einem Weckalarm-OB auf, um eine vernünftige Zeitbasis zu haben.

Beschreibung aus der Hilfe zum FB4:

SAMP_AVE

Funktion

Dieser Baustein gibt am Ausgang den Mittelwert der letzten N Eingangswerte aus. 
OUT = (Ink + Ink -1 + ... +  Ink -n + 1) / N
wobei Ink der aktuelle Eingangswert ist. Die Anzahl N der Eingangswerte muss die Bedingung 
0 < N < 33 
erfüllen.

Anlaufverhalten

Bei Anlauf und Erstlauf wird jedes Element des Buffers für IN- und OUT-Werte auf 0 gesetzt.

Gruß Buster


----------



## pinolino (26 Januar 2010)

Danke nochmals für eure Erklärungen!

Das mit dem Schieben habe ich jetzt soweit verstanden... habe mir dazu die einzelnen Array-Felder mit ihren dazugehörigen Adressen notiert :

Array-Feld 0 → DID [AR1, P#0.0] → 1. Wert

Array-Feld 1 → DID [AR1, P#4.0] → 2. Wert

Array-Feld 2 → DID [AR1, P#8.0] → 3. Wert

Array-Feld 3 → DID [AR1, P#12.0] → 4. Wert

Array-Feld 4 → DID [AR1, P#16.0] → 5. Wert

Array-Feld 5 → DID [AR1, P#20.0] → 6. Wert

Array-Feld 6 → DID [AR1, P#24.0] → 7. Wert

Array-Feld 7 → DID [AR1, P#28.0] → 8. Wert


@Paule: 
Ja stimmt schon, dass bereits mehrere Lösungen aufgezeigt wurden. Mir geht es aber auch darum, die Sache mit den Pointern und Arrays zu verstehen und nachvollziehen zu können, da dies Neuland für mich ist. Denke, wenn ich das Prinzip verstanden habe, dann verstehe ich auch die anderen Codes...


So, nun noch ein *Problem*: 

Wollte das Ganze gerne mal mit PLCSIM testen - aber sobald ich im FB1 auf den Beobachtungsmodus klicke, geht die CPU in *Stop*! Wo könnte das Problem liegen?

Was ich gemacht habe:

1. 
FB1 angelegt und den bekannten Code programmiert. In dem Deklarationsbereich des FBs habe ich "aRealArray" als *statische* Variable angelegt (siehe Bild!).

2.
Durch den Aufruf "Call FB1, DB1" im OB1 hat sich der Instanz-DB1 lt. Bild angelegt.

Wäre super nett, wenn ich noch einen Tipp bekommen könnte, was ich hier falsch gemacht habe...

Vielen Dank - auch für eure Geduld mit mir!
pinolino


----------



## vierlagig (26 Januar 2010)

1. diagnosepuffer?
2. ich tippe darauf, dass du den DB1 nicht mit übertragen hast.


----------



## vierlagig (26 Januar 2010)

jetz hab ich mir dann auch mal die bilder angeguckt

deine anfangsadresse ist NICHT 8


----------



## pinolino (26 Januar 2010)

Danke vierlagig,

habe den FB1, den DB1 und den OB1 geladen.


Der Diagnosepuffer weist auf *zwei *Probleme hin:

1)
STOP durch Programmierfehler (OB nicht geladen oder nicht möglich, bzw. kein FRB vorhanden ) 
Unterbrechungstelle im Anwenderprogramm: Zyklisches Programm (OB 1) 
Prioritätsklasse: 1
FB-Nummer: 1
Bausteinadresse: 16 
Bisheriger Betriebszustand: RUN
Angeforderter Betriebszustand: STOP (intern)
interner Fehler, kommendes Ereignis


2)
Bereichslängenfehler beim Lesen 
Instanz-DB, Doppelwortzugriff, Zugriffsadresse: 32
FB-Nummer: 1
Bausteinadresse: 16
Angeforderter OB: Programmierfehler-OB (OB 121)
OB nicht vorhanden oder gesperrt oder nicht startbar im aktuellen Betriebszustand
interner Fehler, kommendes Ereignis


Leider sagt mir das nicht so viel - kann man daraus ein Problem feststellen?

Danke, pinolino


----------



## Bernard (26 Januar 2010)

*Lineare Mittelwertbildung und Archiv über X Array Elemente*

Hallo an alle,
mein Ansatz ist folgender.Ich baue einen Datenbaustein der nur eine Variable hat,ein Array[1..X] of real.Die Größe des Array ist beliebig(nur durch S7 geschränkt) und realisiert das Messarchiv .
Der gebaute Fb(Linear_Mittelwert_real) macht dann folgendes, er füllt das Array vollständig und bildet über alle Elemente den linearen Mittelwert unabhängig von der Größe des Array.Ist das Archiv voll fängt der FB wieder bei der ersten Zelle an.
Die Archivierung erfolgt getaktet(bei O3X nicht nötig da selbst ein Takt),aus der Taktfrequenz und der Größe des Archives ergibt sich die Geschwindigkeitsänderung des Mittelwertes.Beispiel Takt:=100ms,DB:=100 Elemente, somit währe das Archiv nach 10Sekunden vollständig neu gefüllt worden.

Awl-Quelle liegt bei.
Beispielprogramm liedt bei.
Aufrufgrafik liegt bei.

AWL Textcode:

```
FUNCTION_BLOCK "Linear_Mittelwert_real"
TITLE =
VERSION : 0.1


VAR_INPUT
  Takt : BOOL ;    //Externer Impuls
  Real_Messwert : REAL ;    //Messwert normiert auf real
  DB_NR : INT ;    //Nr des DB ,der DB ist Array[1..X] of real Ausschließlich
END_VAR
VAR_OUTPUT
  Linearer_Mittelwert : REAL ;    
END_VAR
VAR
  Pointer_Speicher_Stat : DWORD ;    
END_VAR
VAR_TEMP
  DB_NR_intern : INT ;    
  Pointer_Speicher_temp : DWORD ;    
  Pointer_schleife : DWORD ;    
  schleife : INT ;    
  SummeMesswert : REAL ;    
  Anzahl_Messelemente : DINT ;    
END_VAR
BEGIN
NETWORK
TITLE =Messwertspeicherung in einem beliebig großem Array of real(DB)
//Datensammlung des Messwertes.Bei jeder messung wird der Wert hochlaufend in 
//eine Zelle geschrieben.Ist der DB voll wird mit der ersten zelle 
//wieder angefangen.
      UN    #Takt; //wenn Takt=false keine Bearbeitung
      SPB   Ende; 
//***************************************************
      L     #DB_NR; //Indirektes öffnen des Messpeicher DB
      T     #DB_NR_intern; 
      AUF   DB [#DB_NR_intern]; 
//***************************************************
      L     #Pointer_Speicher_Stat; //Übergabe statischen an Temp zwecks Indirekte
      T     #Pointer_Speicher_temp; 
//++++++++++++++++++++++++++++++
      L     #Real_Messwert; //Wertablage in Mess_speicher db
      T     DBD [#Pointer_Speicher_temp]; 
//++++++++++++++++++++++++++++++
      L     P#4.0; //Pointererhöhung für nächste Messspeicherung
      L     #Pointer_Speicher_Stat; 
      +D    ; 
      T     #Pointer_Speicher_Stat; 
//***************************************************
//Berechnen der Grenzen des Messspeicher DB und Neubelegung des Pointers mit null
      L     #Pointer_Speicher_Stat; //Adresse des Pointers ermitteln
      SRD   3; //umwandeln nach dint,int
      L     DBLG; //laden der DB Länge in byte
      >=D   ; //wenn der Pointer >= ist als die Anzahl der Byte`des DB
      SPBN  neu; 
      L     P#0.0; //Neubelegung des Pointer
      T     #Pointer_Speicher_Stat; 
neu:  NOP   0; 


NETWORK
TITLE =Lineare Mittelwertbildung über alle Elemente des Array`s (DB)

      L     P#0.0; //Pointer auf erstes Messelement legen
      T     #Pointer_schleife; 
      L     0.000000e+000; 
      T     #SummeMesswert; //vorbelegung Summe Messwert mit null
      L     DBLG; //Datenbausteinlänge in Byte
      L     4; 
      /D    ; 
      T     #Anzahl_Messelemente; 
next: T     #schleife; 
      L     DBD [#Pointer_schleife]; //lade Messelement
      L     #SummeMesswert; 
      +R    ; 
      T     #SummeMesswert; 
      L     P#4.0; 
      L     #Pointer_schleife; 
      +D    ; 
      T     #Pointer_schleife; 

      L     #schleife; 
      LOOP  next; 
//*************************************************
      L     #SummeMesswert; 
      L     #Anzahl_Messelemente; 
      DTR   ; //Umwandlung in real
      /R    ; //Die summe der Messungen durch Anzahl ist Mittelwert
      T     #Linearer_Mittelwert; 
Ende: NOP   0; 
      SET   ; 
      SAVE  ; 
END_FUNCTION_BLOCK
```


----------



## pinolino (26 Januar 2010)

vierlagig schrieb:


> jetz hab ich mir dann auch mal die bilder angeguckt
> 
> deine anfangsadresse ist NICHT 8


 
Hm, ja stimmt - die Adresse im DB1 für das RealArray[0] geht mit 0.0 los!

1) Vermutlich muss ich das immer *händisch* nachholen, wenn die Startadresse *nicht* bei 0 losgeht, oder?

2) Jetzt müsste ich ja eigentlich die Adressen von RealArray[0] bis RealArray[7] per Hand abändern - aber ich kann im DB *keine* Eingaben machen.

Danke!


----------



## vierlagig (26 Januar 2010)

pinolino, verwende bitte, dass in der ersten PN und hier angesprochene:


```
*
      LAR1     P##aRealArray
```

!

und: DON'T TOUCH THE IDB!


----------



## pinolino (26 Januar 2010)

Ok vierlagig,

ich versuche es mit "LAR1     P##aRealArray".


Nur zum Verständnis:

*Was* müsste ich *wo* abändern, damit es auch so bei mir läuft?

Offensichtlich liegt es ja an der Startadresse..


----------



## vierlagig (26 Januar 2010)

pinolino schrieb:


> Ok vierlagig,
> 
> ich versuche es mit "LAR1     P##aRealArray".
> 
> ...



laut screenshot fängt dein array bei *0.0* an also die angebliche startadresse 8 ist *0*


----------



## pinolino (26 Januar 2010)

Ja, genau - und damit das Ganze wieder zusammenpasst, müsste ich doch jetzt *per Hand* die Adressen im IDB1 anpassen, so dass die Startadresse eben die 8.0 ist.

Aber genau das geht nicht - es werden keine Änderungen zugelassen, vermutlich weil es ein Instanz-DB ist! Ich hatte aber doch auch keine Möglichkeit, beim Generieren des DBs die Adresse bei 8 beginnen zu lassen...

Frage:

Was macht man in diesem Fall in der *Praxis* - wie kann die oben genannte Änderung dennoch vorgenommen werden?

Danke!


----------



## vierlagig (26 Januar 2010)

pinolino schrieb:


> Ja, genau - und damit das Ganze wieder zusammenpasst, müsste ich doch jetzt *per Hand* die Adressen im IDB1 anpassen, so dass die Startadresse eben die 8.0 ist.
> 
> Aber genau das geht nicht - es werden keine Änderungen zugelassen, vermutlich weil es ein Instanz-DB ist! Ich hatte aber doch auch keine Möglichkeit, beim Generieren des DBs die Adresse bei 8 beginnen zu lassen...
> 
> ...



alter, willste mich verarschen???
das ist nicht lustig!

1. LAR1
2. vielleicht statt der acht in zeile 85.879372 eine 0 hinschreiben


----------



## PBO-WE (26 Januar 2010)

Ich glaube der Kollege versucht den Instanz DB so zu ändern, daß sein Array bei adresse 8 anfängt.


----------



## vierlagig (26 Januar 2010)

PBO-WE schrieb:


> Ich glaube der Kollege versucht den Instanz DB so zu ändern, daß sein Array bei adresse 8 anfängt.



dummyArray davor anlegen ... aber was ist der sinn?


----------



## R.Blum (26 Januar 2010)

Hallo Leute,

mal ein ganz anderer Ansatz ganz ohne Arrays.

Ich verwende meistens die gleitende Mittelwertbildung. Vorteil, kommt ganz ohne speicherfressendes Array aus. Nachteil es ergibt sich immer ein kleiner Fehler, der aber meist vernachlässigbar ist.

Hier die AWL Quelle:


```
FUNCTION "VM" : VOID
TITLE =Gleitende Mittelwertbildung
AUTHOR : VIS_Blum
FAMILY : CALC
NAME : FC_169
VERSION : 1.0
 
VAR_INPUT
  AKT : REAL ; //Aktueller Wert
  Tiefe : INT ; //Filtertiefe
END_VAR
VAR_IN_OUT
  Mittel : REAL ; //Mittelwert
END_VAR
VAR_TEMP
  Faktor : REAL ; //Bewertung, Stärke des Mittelwertes
  Divisor : REAL ; //Filtertiefe für Mittelwert
END_VAR
BEGIN
NETWORK
TITLE =
      L     2; 
      L     #Tiefe; 
      >I    ; 
      SPB   AUS; 
      L     #Tiefe; 
      DTR   ; 
      T     #Divisor; 
      L     #Tiefe; 
      +     -1; 
      DTR   ; 
      T     #Faktor; 
      L     #Mittel; 
      L     #Faktor; 
      *R    ; 
      L     #AKT; 
      +R    ; 
      L     #Divisor; 
      /R    ; 
      T     #Mittel; 
      BEA   ; 
AUS:  L     #AKT; 
      T     #Mittel; 
END_FUNCTION
```
 
Vielleicht hilft es ja,

Gruß Rolf


----------



## pinolino (26 Januar 2010)

PBO-WE schrieb:


> Ich glaube der Kollege versucht den Instanz DB so zu ändern, daß sein Array bei adresse 8 anfängt.


 
Yep, das wäre mein Vorhaben gewesen!

Aber offensichtlich ist das bei einem Instanz-DB *nicht* machbar...

Vermutlich legt der Instanz-DB seine erste Adresse *immer bei 0* an. Habe auch keine Möglichkeit gefunden,* im* Instanz-DB die Startadresse festzulegen.

Grüße
pinolino


----------



## PBO-WE (26 Januar 2010)

Du kannst den IDB über die Schnittstellen des Bausteins parametrieren.
Wenn Du vor dem ARRAY 0..7 noch ein DW als dummy anlegst, wird sich die Adresse des arrays im IDB um 4 Byte verschieben.
Das wäre die einzige mir bekannte möglichkeit das zu tun, aber es macht glaub ich mehr sinn, die änderung im code vor zu nehmen.


----------



## petzi (26 Januar 2010)

PBO-WE schrieb:


> Du kannst den IDB über die Schnittstellen des Bausteins parametrieren.
> Wenn Du vor dem ARRAY 0..7 noch ein DW als dummy anlegst, wird sich die Adresse des arrays im IDB um 4 Byte verschieben.


 
Hallo PBO-WE, 

ich nehme an du meinst mit "über die Schnittstellen des Bausteins" den *Deklarationsbereich des Funktionsbausteins*?

Gibt es echt keine Möglichkeit, z.B. die Adressen eines IDB _im Baustein selber_ zu ändern?


----------



## PBO-WE (26 Januar 2010)

petzi schrieb:


> ich nehme an du meinst mit "über die Schnittstellen des Bausteins" den *Deklarationsbereich des Funktionsbausteins*?
> zu ändern?



Genau den meine ich. Sorry, kenn mich mit den Begrifflichkeiten nicht so super aus, da ich mir mein Wissen überwiegend durch experimentieren beigebracht habe. 

Mir ist nicht bekannt, daß man den IDB irgendwie bearbeiten kann.


----------



## petzi (26 Januar 2010)

Kein Problem...

Es ist nur so, dass ich ziemliche Anfängerin bin und daher nicht immer genau weiß, was die Profis meinen, wenn die Dinge nicht genau bei ihrem Namen genannt werden... 

Müsste dieses Dummy-Array eigentlich unbedingt in der statischen-Schnittstelle (also dort wo auch das Array deklariert ist) eingefügt werden, oder ginge es z.B. auch im TEMP-Bereich?

Danke!


----------



## PBO-WE (26 Januar 2010)

Im Temp-Bereich ist es leider nicht möglich, da diese Variablen nicht im IDB abgelegt werden, sondern nach jedem Bausteinaufruf verloren gehen.
Im IN, Out, IN/OUT oder Statischen Bereich ist es möglich.


----------



## petzi (26 Januar 2010)

Aja vielen Dank, PBO-WE!

Somit muss dieses Dummy-Array also *nicht* zwangsweise im gleichen Bereich eingefügt werden, wie das bestehende, richtig?


----------



## vierlagig (26 Januar 2010)

ich weise gerne nochmal darauf hin:

http://sps-forum.de/showpost.php?p=239550&postcount=23

kein mensch brauch ein dummyArray außer vielleicht um daten irgendwie zu verwurschteln...


----------



## petzi (26 Januar 2010)

Ok vierlagig, habe verstanden - zumindest das. 

Hätte man diesen "Fehler" denn bei der Programmierung überhaupt verhindern können, außer dass man den Code

LAR1 P##aRealArray

verwendet hätte?

Ich meine, aus welchem Grund wurde denn die Startadresse des Arrays im IDB beim Aufruf des FBs falsch angelegt? Der IDB muss doch eigentlich "wissen", welche Adressbereiche im FB deklariert sind. 

Thanks!


----------



## vierlagig (26 Januar 2010)

petzi schrieb:


> Ok vierlagig, habe verstanden - zumindest das.
> 
> Hätte man diesen "Fehler" denn bei der Programmierung überhaupt verhindern können, außer dass man den Code
> 
> ...



hier wurde nischtens falsch angelegt, das war einfach nur ein ziemlich dämlicher programmierfehler. wenn die startadresse nun mal 0 ist, dann ist sie 0 und NICHT 8 ...


----------



## PBO-WE (26 Januar 2010)

Kannst Du "LAR1 P##aRealArray" bitte erleutern?

Ist das eine indirekte addressierung des Arrays?
Heißt das, daß egal wo sich die Anfangsadresse des Arrays befindet, das AR anhand des Namens RealArray weiß wo der anfang ist?
wofür steht das kleine "a"?

Danke!


----------



## vierlagig (26 Januar 2010)

PBO-WE schrieb:


> Kannst Du "LAR1 P##aRealArray" bitte erleutern?
> 
> Ist das eine indirekte addressierung des Arrays?
> Heißt das, daß egal wo sich die Anfangsadresse des Arrays befindet, das AR anhand des Namens RealArray weiß wo der anfang ist?
> ...



LAR1 belädt das adressregister mit einer adresse
die adresse wird mit P# vorgegeben
durch den variablenname wird die startadresse der arrays gewählt

das a ist aus meiner symbolbeschreibung entstanden und steht für den datentyp der hier vorliegenden variablen (x=bit,b=byte,w=wort,r=real ... a=array ...) und erleichtert das zurechtfinden im programm...


----------



## petzi (26 Januar 2010)

vierlagig schrieb:


> hier wurde nischtens falsch angelegt, das war einfach nur ein ziemlich dämlicher programmierfehler. wenn die startadresse nun mal 0 ist, dann ist sie 0 und NICHT 8 ...


 
Hm, glaube kann dir grad nicht ganz folgen. Du meinst, man hätte statt

L 8
SLD 3
LAR1

programmieren müssen:

L 0
SLD 3
LAR1

Sprichst du also von Programmierfehler, weil eine Adresse im IDB immer bei 0 anfangen muss, oder wie muss ich das verstehen?


----------



## vierlagig (26 Januar 2010)

petzi schrieb:


> Sprichst du also von Programmierfehler, weil eine Adresse im IDB immer bei 0 anfangen muss, oder wie muss ich das verstehen?



die adresse muß nicht immer bei null anfangen, aber im vorliegenden fall tut sie es. dafür gibt es die spalte anfangsadresse... aber wie gesagt, ungeachtet dieser anfangsadresse kann man es mit der direkten zuweisung der adresse so dynamisch gestalten, dass es scheiß egal ist, mit welcher startadresse das array abgeht


----------



## petzi (26 Januar 2010)

vierlagig schrieb:


> die adresse muß nicht immer bei null anfangen, aber im vorliegenden fall tut sie es. dafür gibt es die spalte anfangsadresse...


 
Sorry, aber meinst du die Spalte *Adresse* im FB? Eine Spalte mit der Bezeichnung Anfangsadresse sehe ich nämlich nicht!


----------



## vierlagig (26 Januar 2010)

petzi schrieb:


> Sorry, aber meinst du die Spalte *Adresse* im FB? Eine Spalte mit der Bezeichnung Anfangsadresse sehe ich nämlich nicht!



oder die, is doch buggie, steht sowieso nur die anfangsadresse drin ... aber, und ich werd nicht müde es zu erwähnen, man sollte nicht wirklich damit proggen weil eine später eingefügte variable das gesammte konstrukt zum einsturz bringen kann ...

btw: soll der FB multiinstanzfähig sein muß dem AR1 noch der offset AR2 hinzugefügt werden, wurde aber schon ausreichend im forum erläutert...


----------

