# Scheife - kleines Prog.



## Limette (2 März 2011)

Hallo zusammen,


```
L     4                           // Lade Eingangadresse        
      SLD   3                           // Verschiebe Bit um 3, da Aufbau des Pointer. vereinfacht: Byteadress(16Bit).Bitadress(3Bit)
      LAR1                              // Lade Adressregister 1
      L     EB [AR1,P#0.0]              // Lade Eingangsbyte in Adressregister nach AKK1
      T     DIB    5                    // Transfer Akk1 auf Adresse Byte 5 im Instanzdatenbausten
```
Ich hoffe das Programm ist verständlich.
der eingang hat nun z.b. ein bereich von 4.0 bis 4.7. nun möchte ich in einer schleife abfragen ob auch wirklich etwas anliegt und es gegenenfalls "transferieren". 
also wenn zum beispiel:

L  EB [AR1,P#0.*1*] anliegt, es in 
T     DIB    5.*1*   zu schreiben. und so weiter.

danke im voraus.


----------



## godi (2 März 2011)

Hallo!

Hast du den Groschen (seit 2002 Cent) schon wieder aufgehoben?

Eigentlich ist nichts verständlich...
Was verstehst du unter "wirklich etwas anliegt"?
Einzelne Bits können nicht mit Transferbefehlen transferiert werden.
Dazu sind die Operatoren S und = vorhanden.
Aber wenn du das ganze Byte übertragen willst dann brauchst du keine einzelnen Bits Adressieren sondern kannst gleich
L EB4
T DBx.DBBy
schreiben.

Was ist DIB 5.1? 

godi


----------



## Gerhard K (2 März 2011)

ich denke er meinte DIX godi

@godi Wie gehts dir überhaupt alter Leidensgenosse 
Was macht das Studium?


```
U E[AR1,P#0.1]
= DIX 5.1
```
 
Willst du dein Eingangsbyte nach True durchsuchen und 
wenn True ein DIX x.x setzen?


----------



## Limette (2 März 2011)

Gerhard K schrieb:


> ich denke er meinte DIX godi
> 
> @godi Wie gehts dir überhaupt alter Leidensgenosse
> Was macht das Studium?
> ...


 
ja genau. du hast mich glaub verstanden.


----------



## online (2 März 2011)

Vergleiche dein Eingangsbyte mit 0, wenn nicht Null, = Zielbit


----------



## Limette (2 März 2011)

godi schrieb:


> Hallo!
> 
> Hast du den Groschen (seit 2002 Cent) schon wieder aufgehoben?
> 
> godi


 

nein nein, das ist ein neuer Groschen bzw. Cent. der alte liegt noch. 
Hast du noch fragen oder konnte dir Gehard schon helfen.


----------



## Gerhard K (2 März 2011)

Willst du damit geziehlt verschiedene DIX x.x setzen oder einfach 1:1
vom EB auf dein DIB transferieren?
Schreib mal, was du wirklich willst?


----------



## bimbo (2 März 2011)

Limette schrieb:


> Hast du noch fragen oder konnte dir Gehard schon helfen.


 

Hilf doch Du


----------



## Limette (3 März 2011)

Gerhard K schrieb:


> Willst du damit geziehlt verschiedene DIX x.x setzen oder einfach 1:1
> vom EB auf dein DIB transferieren?
> Schreib mal, was du wirklich willst?



entschuldigung dass ich mich so schlecht ausdrücken kann. ich versuche es nochmal.

ich möchte nur peripherie die zum beispiel von E4.0 bis E6.5 angeschlossen in einen zum beispiel Dix von 7 bis 8.5 laden. bit für bit, in einer schleife.


----------



## Limette (7 März 2011)

hat niemand ne idee ? :sad:


----------



## PN/DP (7 März 2011)

Limette schrieb:


> ich möchte nur peripherie die zum beispiel von E4.0 bis E6.5 angeschlossen in einen zum beispiel Dix von 7 bis 8.5 laden. bit für bit, in einer schleife.


Vorab: Die Peripherie-Adressen müssen im PAE liegen, weil sonst Byte- oder Bitzugriffe auf die Peripherie-Eingänge meist nicht funktionieren.


```
//einfache Variante: E4.0..E6.7 -> DIX7.0..DIX9.7
      L     EW     4                    //  E4.0..E5.7
      T     DIW    7                    //DIX7.0..DIX8.7
      L     EB     6                    //  E6.0..E6.7
      T     DIB    9                    //DIX9.0..DIX9.7
```

Bit-Kopier-Schleife:

```
//Schleife für "krumme" Anfangs- oder Endeadressen
      TAR2  #tmpDW_AR2save              //AR2 sichern
      LAR1  P#E 4.0                     //Quell-Bereichsbeginn
      LAR2  P#DIX 7.0                   //Ziel-Bereichsbeginn

loop: U      [AR1,P#0.0]                //E[AR1] lesen
      =      [AR2,P#0.0]                //in DIX[AR2] übertragen

      +AR1  P#0.1                       //E-Pointer auf nächstes Bit
      TAR1  
      L     P#E 6.5                     //Quell-Endadresse
      >D                                //überschritten?
      SPB   end
      +AR2  P#0.1                       //DIX-Pointer auf nächstes Bit
      SPA   loop                        //Schleife wiederholen

end:  LAR2  #tmpDW_AR2save              //AR2 wiederherstellen
```

Harald


----------



## Limette (7 März 2011)

PN/DP schrieb:


> Vorab: Die Peripherie-Adressen müssen im PAE liegen, weil sonst Byte- oder Bitzugriffe auf die Peripherie-Eingänge meist nicht funktionieren.
> 
> 
> ```
> ...



danke, werde es gleich mal probieren.


----------



## Limette (7 März 2011)

Den Befehl 


```
#tmpDW_AR2save
```

mag er leider gar nicht.


----------



## PN/DP (7 März 2011)

Limette schrieb:


> Den Befehl
> 
> 
> ```
> ...


*tmpDW_AR2save* ist eine Hilfsvariable DWORD im TEMP-Bereich des Bausteins.
Die müßtest Du in Deinem Baustein erst noch anlegen.

Harald


----------



## Limette (8 März 2011)

PN/DP schrieb:


> *tmpDW_AR2save* ist eine Hilfsvariable DWORD im TEMP-Bereich des Bausteins.
> Die müßtest Du in Deinem Baustein erst noch anlegen.
> 
> Harald



ach, da hätte ich auch selbst drauf kommen können.. danke


----------



## Limette (18 März 2011)

PN/DP schrieb:


> Vorab: Die Peripherie-Adressen müssen im PAE liegen, weil sonst Byte- oder Bitzugriffe auf die Peripherie-Eingänge meist nicht funktionieren.
> 
> 
> ```
> ...




ich habe daran kaum etwas verändert, leider geht die sps in stop und zeigt SF Fehler an.

an was könnte das liegen ? 

Grüße


----------



## Paule (18 März 2011)

Limette schrieb:


> ich habe daran kaum etwas verändert, leider geht die sps in stop und zeigt SF Fehler an.


Definiere doch mal >>> kaum <<<


----------



## Limette (18 März 2011)

Paule schrieb:


> Definiere doch mal >>> kaum <<<





```
LAR1  P#E 4.0
```
zu

```
LAR1  P##Eingang
```
und im ob dann die adresse zugewiesen. an dem dürfte es wohl nicht liegen.

bei


> LAR2  P#DIX 7.0


greife ich ja auf den instanz db zu. kann es sein dass ich den db zuerst laden muss ?


----------



## Paule (18 März 2011)

Limette schrieb:


> ```
> LAR1  P#E 4.0
> ```
> zu
> ...


Ich glaub schon.
Spontan würde ich jetzt sagen dass nun die Bereichskennung fehlt. ( E )


----------



## Limette (18 März 2011)

Paule schrieb:


> Ich glaub schon.
> Spontan würde ich jetzt sagen dass nun die Bereichskennung fehlt. ( E )




ich hab mein abgeänderter quelltext durch den orgianlen ersetz und wieder hochgeladen. leider immer SF Fehler. willst du ihn bei dir mal kurz in der sps hochladen und gucken was passiert(falls zeit und lust  ). dann wüßte ich ob es am code oder doch an meiner s7-300 liegt.


----------



## PN/DP (18 März 2011)

Hallo Limette,

Du hast anscheinend aus dem Codeschnipsel einen parametrierbaren FB gemacht. Zeige uns doch mal die Aufrufschnittstelle Deines FB.

Mit *LAR1 P##Eingang* lädst Du die Adresse des FB-Eingangsparameters und NICHT die Adresse, die Du beim Aufruf übergibst. Du müßtest die Bereichs-Anfangsadresse und die Bereichs-Endeadresse als POINTER übergeben, dann kannst Du beim FB-Aufruf *E4.0* und *E6.5* dranschreiben.

Den Instanz-DB brauchst Du nicht öffnen, der wird beim FB-Aufruf automatisch als DI geöffnen. *LAR2 P#DIX 7.0* solltest Du noch zu einem symbolischen Zugriff umformulieren.

Ich habe jetzt leider nicht mehr Zeit.

Harald


----------



## Der Pfälzer (18 März 2011)

Limette schrieb:


> ```
> bei
> greife ich ja auf den instanz db zu. kann es sein dass ich den db zuerst laden muss ?[/QUOTE]
> 
> ...


----------



## Limette (18 März 2011)

Der Pfälzer schrieb:


> Der IDB muss natürlich mit entsprechender Länge in der CPU vorhanden sein.
> 
> Was sagt den der Diagnosespeicher bei CPU-STOP?
> 
> Gruß Roland



ok, ich kopier ihn einfach mal rein. vllt kannst du damit was anfangen.




> Ereignis 1 von 2:  Ereignis-ID 16# 4562
> STOP durch Programmierfehler (OB nicht geladen oder nicht möglich, bzw. kein FRB vorhanden )
> FB-Nummer:     1
> Bausteinadresse:     20
> ...


----------



## Limette (18 März 2011)

PN/DP schrieb:


> Hallo Limette,
> 
> Du hast anscheinend aus dem Codeschnipsel einen parametrierbaren FB gemacht. Zeige uns doch mal die Aufrufschnittstelle Deines FB.
> 
> ...



wie ich sehe habe ich noch ein wenig nachholbedarf. so richtig habe ich dich nicht verstanden.
was wohl aber dann nicht geht ist


```
LAR1 P##[B]Eingang[/B]
```
"Eingang" in der Schnittstelle als Integer oder Dword Eingang zu bestimmen und ihm dann einfach im OB z.b. 4 bzw. DW#16#4 zu zuweisen.


----------



## PN/DP (18 März 2011)

Tscha, die registerindirekte Adressierung ist am Anfang ziemlich schwer zu meistern.
Zeig doch mal die komplette Deklaration Deines FB, dann kann ich Dir das für Deinen FB passend umschreiben.
Muß Dein FB multiinstanz-fähig sein?

Harald


----------



## Limette (19 März 2011)

PN/DP schrieb:


> Tscha, die registerindirekte Adressierung ist am Anfang ziemlich schwer zu meistern.
> Zeig doch mal die komplette Deklaration Deines FB, dann kann ich Dir das für Deinen FB passend umschreiben.
> Muß Dein FB multiinstanz-fähig sein?
> 
> Harald


 

Herzlichen Dank für deine Mühe !

ich umreiße mal kurz mein gesamtes vorhaben.
ich habe 10 fbs mit gleicher logik die nur verschieden Eingänge haben (je 8 -13 Eingänge von DP, max. 2 byte groß), die dann 4 weitere FBs (Ausgänge) aufrufen sollen.
ich dachte es wäre das beste per Schleife die Eingänge eines fbs abzufragen, sie dann "intern" zu einer Logik verarbeiten und dann die entsprechenden Ausgänge zu setzen. Den code könnte ich ja dann praktisch 10 mal anwenden, müsste nur im OB die entsprechenden Eingangsadressen angeben.
Was mir noch nicht ganz klar ist, warum der code den du geschrieben hast nicht funktioniert hat. Ich hab noch ein wenig rumprobiert und bin mir sicher dass die sps bei 
	
	



```
LAR2  P#DIX 7.0
```
 auf jeden fall in "Stop" gegangen ist.


----------



## PN/DP (20 März 2011)

Limette schrieb:


> Ich hab noch ein wenig rumprobiert und bin mir sicher dass die sps bei
> 
> 
> 
> ...


Bei dieser Operation ist die CPU *GARANTIERT NICHT* in Stop gegangen.
Da wird nur das Adressregister AR2 mit irgendeiner Adresse geladen, es ist noch nicht einmal ein Speicherzugriff.

Die CPU geht aber z.B. bei *= [AR2,P#0.0]* in Stop, wenn Dein Instanz-DB nicht mindestens 8 Byte lang ist (und kein OB121 in der CPU ist).

Die genaue Stop-Stelle erfährt man aus dem Diagnosepuffer der CPU, da ist direkt vor (unter) dem Eintrag "STOP durch Programmierfehler" der Eintrag mit der Fehlerursache, bei Dir: "Bereichslängenfehler beim Schreiben". Den Eintrag markierst Du und liest Dir die Details zum Ereignis durch. 


> Ereignis 2 von 2: Ereignis-ID 16# 2523
> Bereichslängenfehler beim Schreiben
> Instanz-DB , Bitzugriff, Zugriffsadresse: 7


Das bedeutet: Der Instanz-DB in der CPU hat keine Adresse 7, er ist also zu kurz oder garnicht geladen.
Die Operation war ein Bit-Schreibzugriff: S, R oder =.

Mit dem Button "Baustein öffnen" springt Step7 dann genau zu der Zeile, die den Fehler verursacht hat.




Limette schrieb:


> Was mir noch nicht ganz klar ist, warum der code den du geschrieben hast nicht funktioniert hat.


Der Code, den ich geschrieben habe, der funktioniert. 
Es funktioniert nicht der Code, den Du daraus gemacht hast. 
Wie ich weiter oben schon schrieb: *LAR2 P#DIX 7.0* solltest Du noch zu einem symbolischen Zugriff umformulieren.
Der Bereich, wohin Du die Eingangszustände kopieren willst, beginnt bei Dir höchstwahrscheinlich nicht bei DBX7.0.
Bei einem symbolischen Zugriff setzt der Editor automatisch die richtige Adresse ein.

Ist es so schwer, hier endlich mal die Deklaration Deines FB zu posten? Du brauchst keine Betriebsgeheimnisse verraten, Deinen Code brauchen wir nicht, um die kurze Programmschleife passend zu Deinem FB umzuschreiben.
Ohne Deine FB-Deklaration können wir Dir auch wieder nur Code geben, der andere Variablennamen als bei Dir hat, an dem Du dann "kaum" etwas ändern mußt - und bums - geht Deine CPU wieder in Stop.

Wenn Du es selber hinbekommen willst, dann brauchst Du:
- einen Eingangsparameter "Eingangsbereichsanfang" vom Typ POINTER
- einen Eingangsparameter (oder TEMP/STAT-Variable) "Eingangsbereichsende" vom Typ POINTER
- eine TEMP/STAT-Variable (oder Eingangsparameter) "Eingangsbereichslaenge" vom Typ INT (Dein FB muß ja auch wissen, ob er 8 oder 13 Eingänge verarbeiten muß)
(die Länge kann der FB aus "Eingangsbereichsende" und "Eingangsbereichsanfang" selber berechnen oder das Ende aus Anfang und Länge)
- ein ARRAY[0..15] OF BOOL im STAT-Bereich Deines FB, wohin die Eingangszustände kopiert werden
- statt P#DIX 7.0 mußt Du den Name des Arrays einsetzen
- falls Dein FB als Multi-Instanz genutzt wird, mußt Du den Multi-Instanz-Offset im AR2 beachten (besser: das AR2 auf jeden Fall dazuaddieren)
- Beachte: zwischen dem LAR2 P#DIX 7.0 und dem LAR2 #tmpDW_AR2save kann nicht symbolisch auf Variablen der Instanz zugegriffen werden

Viel Erfolg!
Harald


----------



## Limette (21 März 2011)

Hi, 

ich hab noch Verständnisfragen zu PN/DPs Code.

Momentan lese ich ja 5 Bit, für DP-Eingänge ein (P#E5.0 - P#E5.5)und lade sie in den Instanzdatenbaustein ab Byte 15, also 15.0 bis 15.5, richtig ?

wenn ja, wie kann ich jetzt damit arbeiten? wenn ich zum Beispiel P#E5.0 auf "1" setze, müsste ja im DI an Byte 15 auch eine "1" stehen, richtig ?

wie könnte ich sowas abfragen ? 



```
//Schleife für "krumme" Anfangs- oder Endeadressen
      TAR2  #tmpDW_AR2save              //AR2 sichern
      LAR1  P##AP1_Anfangsadresse       //Quell-Bereichsbeginn [B]P#E5.0[/B]
      [B]LAR2  P#DIX 15.0[/B]           //Ziel-Bereichsbeginn

loop: U      [AR1,P#0.0]                //E[AR1] lesen
      =      [AR2,P#0.0]                //in DIX[AR2] übertragen

      +AR1  P#0.1                       //E-Pointer auf nächstes Bit
      TAR1  
      L     P##AP1_Endadresse           //Quell-Endadresse
      >D                                //überschritten? [B]P#E5.5[/B]
      SPB   end
      +AR2  P#0.1                       //DIX-Pointer auf nächstes Bit
      SPA   loop                        //Schleife wiederholen

end:  LAR2  #tmpDW_AR2save              //AR2 wiederherstellen
```


----------



## PN/DP (22 März 2011)

Es ist schon ein großer Unterschied, ob das Kopierprogramm mit festen Adressen oder mit parametrierbaren Adressen arbeitet! Es kommt zusätzlicher Code zur Parameterübernahme und Parameterprüfung dazu! Am kompliziertesten ist das korrekte Empfangen der als POINTER übergebenen Adressen der Kopierbereiche. Deshalb habe ich mal die Kopierschleife für den parametrierbaren Einsatz in FB erweitert. Die eigentliche Kopierschleife ändert sich fast nicht, es werden nur die festen Adressen durch Adress-Variablen ersetzt.

Zunächst die Deklaration der verwendeten FB-IN-Parameter und FB-Variablen:

```
VAR_INPUT
  Anfangsadresse : POINTER ;	
  Endadresse : POINTER ;	
END_VAR
VAR
  stat_irgendwas : WORD ;	
  stat_E : ARRAY  [0 .. 15 ] OF BOOL  := FALSE; //hier liegen dann die eingelesenen Eingänge
  stat_nochwas : BOOL ;	
END_VAR
VAR_TEMP
  tmp_AR2save : DWORD ;	
  tmp_Anfangsadresse : DWORD ;	
  tmp_Endadresse : DWORD ;	
  tmp_Bereichslaenge : INT ; //Anzahl der eingelesenen Bits
  tmp_Bit : BOOL ;	
END_VAR
```

Hier nun der Programmcode (funktioniert NICHT mit Bits aus DB! Limette will ja nur Ex.y einlesen):

```
TAR2  #tmp_AR2save                //AR2 sichern, weil dies ein FB ist

//Pointer auf Quellbereichsbeginn erstellen (das kann hier kein DB-Bereich sein!)
      LAR1  P##Anfangsadresse           //Adresse des IN-Parameters in der Grund-Instanz
      TAR2                              //eventueller Multiinstanz-Offset
      +AR1                              //Pointer auf IN-Parameter Quell-Bereichsbeginn
      L     D [AR1,P#2.0]               //nur Speicherbereichsadresse des übergebenen POINTER
      T     #tmp_Anfangsadresse
//**      LAR1                              //(zum Beobachten)

//Sicherstellen, daß Endadresse im selben Speicherbereich wie Anfangsadresse ist
//und im Bereich Anfangsadresse ... Anfangsadresse+15 ist (begrenzte Array-Größe!)
      LAR1  P##Endadresse               //Adresse des IN-Parameters in der Grund-Instanz
      TAR2                              //eventueller Multiinstanz-Offset
      +AR1                              //Pointer auf IN-Parameter Quell-Endadresse
      L     D [AR1,P#2.0]               //nur Speicherbereichsadresse des übergebenen POINTER
//**      LAR1                              //(zum Beobachten)

      L     #tmp_Anfangsadresse         //Akku1: Anfangsadresse / Akku2: Endadresse
      -D                                //Endadresse - Anfangsadresse = Bereichslaenge-1
      SPPZ  ckmx                        //OK, Endadresse >= Anfangsadresse
      L     0                           //Endadresse < Anfangsadresse! nur 1 Bit kopieren
ckmx: L     15                          //maximale Bereichslänge-1
      >D    
      SPB   cead                        //Endadresse unzulässig -> 15 übernehmen
      POP                               //ursprüngliche Breichslaenge-1 oder 0 übernehmen
cead: PUSH                              //( für S7-400 und PLCSIM: Akku2 = Akku1 = Bereichslaenge-1 )  
      PUSH                              //( für S7-400 und PLCSIM: Akku3 = Akku2 = Akku1 )  
      L     #tmp_Anfangsadresse         //Akku1: A.adr | Akku2: B.laenge-1 | (Akku3: B.laenge-1)
      +D                                //( S7-400 und PLCSIM: Akku2:=Akku3! )
      T     #tmp_Endadresse
//**      LAR1                              //(zum Beobachten)

      POP                               //Breichslaenge-1 zurück in Akku1
      +     1
      T     #tmp_Bereichslaenge         //Anzahl der Bits

//Pointer-Register (ARx) für Kopierschleife initialisieren
      LAR1  #tmp_Anfangsadresse         //Pointer auf Quell-Bereichsbeginn
//      LAR2  P##tmp_E                    //TEMP-Array: Pointer auf Ziel-Bereichsbeginn
      TAR2                              //STAT-Array: eventuellen MultiinstanzOffset in Akku1
      LAR2  P##stat_E                   //STAT-Array: Pointer auf Ziel-Bereichsbeginn Grund-I.
      +AR2                              //STAT-Array: ="= + eventuellen MultiinstanzOffset

//Kopierschleife
loop: U      [AR1,P#0.0]                //E[AR1] lesen
      =      [AR2,P#0.0]                //in DIX[AR2] übertragen (bzw. L[AR2])

      +AR1  P#0.1                       //Quell-Pointer auf nächstes Bit
      TAR1  
      L     #tmp_Endadresse             //Quell-Endadresse
      >D                                //überschritten?
      SPB   end
      +AR2  P#0.1                       //Ziel-Pointer auf nächstes Bit
      SPA   loop                        //Schleife wiederholen

//AR2 wiederherstellen
end:  LAR2  #tmp_AR2save                //AR2 wiederherstellen

//Beispiel Verarbeitung der kopierten Bits
      U     #stat_E[0]
      U     #stat_E[13]
      =     #tmp_Bit
```
Die mit //** auskommentierten Zeilen sind beim Beobachten/Testen des Bausteins recht nützlich, für die Funktion aber nicht erforderlich.

Da die Eingangsbits immer in das Array kopiert werden, ist es auch möglich, das Array in den TEMP-Bereich (Lokaldaten) zu legen. Dann darf das AR2 aber nicht zum Ziel-Pointer addiert werden.

So wird der FB aufgerufen:

```
CALL  FB    11 , DB11
       Anfangsadresse:=E4.0
       Endadresse    :=E5.5
```
Das geht auch mit symbolischen E-Adressen an den IN-Parametern.
Weil die IN-Parameter vom Typ POINTER sind, könnte man auch P#E4.0 und P#E5.5 dranschreiben - das wird dann aber nicht symbolisch.
Wenn man bequem E4.0 und E5.5 dranschreibt, dann wandelt Step7 das unsichtbar in P#E4.0 und P#E5.5 um.

Harald


----------



## Limette (22 März 2011)

Vielen vielen Dank.


Wenn ich mit einer S7-300 arbeite kann ich diesen Teil rausnehmen, oder ?


```
cead: PUSH                              //( für S7-400 und PLCSIM: Akku2 = Akku1 = Bereichslaenge-1 )  
      PUSH                              //( für S7-400 und PLCSIM: Akku3 = Akku2 = Akku1 )  
      L     #tmp_Anfangsadresse         //Akku1: A.adr | Akku2: B.laenge-1 | (Akku3: B.laenge-1)
      +D                                //( S7-400 und PLCSIM: Akku2:=Akku3! )
      T     #tmp_Endadresse
//**      LAR1                              //(zum Beobachten)

      POP                               //Breichslaenge-1 zurück in Akku1
```
Bei *L     D [AR1,P#2.0] *geht er leider in Stop:

```
TAR2  #tmp_AR2save                //AR2 sichern, weil dies ein FB ist

//Pointer auf Quellbereichsbeginn erstellen 
      LAR1  P##Anfangsadresse           //Adresse des IN-Parameters in der Grund-Instanz
      TAR2                              //eventueller Multiinstanz-Offset
      +AR1                              //Pointer auf IN-Parameter Quell-Bereichsbeginn
      [B]L     D [AR1,P#2.0][/B]               //nur Speicherbereichsadresse des übergebenen POINTER
      T     #tmp_Anfangsadresse
```



> Ereignis 10 von 10:  Ereignis-ID 16# 2522
> Bereichslängenfehler beim Lesen
> Instanz-DB, Doppelwortzugriff, Zugriffsadresse:      2
> Angeforderter OB: Programmierfehler-OB (OB 121)
> ...


Das ist jetzt leider wieder so eine Fehlermeldung, bei der ich nicht weiter weiß. wo kann ich den nachgucken, wo genau mein Bereich startet und wo er aufhört. bei 2.0 ist er schon mal nicht. ^^


----------



## Limette (22 März 2011)

Habe OB121 nachgeladen und schon läufts.


----------



## PN/DP (24 März 2011)

Limette schrieb:


> Habe OB121 nachgeladen und schon läufts.


Das ist ein Irrtum, es funktioniert höchstwahrscheinlich NICHT, nur die CPU geht nicht mehr in STOP. An der CPU müßte die SF-LED rot leuchten und der Diagnosepuffer läuft über mit den Bereichslängenfehler-Einträgen.
Ich vermute mal, Du hast Dir aus meinen Code zum Testen einen neuen FB erstellt und vergessen, den zugehörigen IDB in die CPU zu laden.

Harald


----------



## PN/DP (24 März 2011)

Wie testest Du eigentlich Deine Programme?
CPU geht nicht in STOP -> Programm müßte funktionieren?
Oder beobachtest Du auch den Programmablauf (bei der Entwicklung von register-indirekten Programmteilen ganz wichtig! Adressregister einblenden!) und simulierst/schaltest mal Deine zu kopierenden Eingänge und schaust, ob die auch in Deinen IDB korrekt ankommen?

Harald


----------



## PN/DP (24 März 2011)

Limette schrieb:


> Wenn ich mit einer S7-300 arbeite kann ich diesen Teil rausnehmen, oder ?
> 
> 
> ```
> ...


Du kannst nur das rot markierte rausnehmen (die beiden PUSH-Operationen).
Allerdings funktioniert das Programm dann nicht mehr in PLCSIM, weil PLCSIM eine S7-400-CPU mit 4 Akkus simuliert, und bei der S7-400 die Operation *+D* den Akku2 verändert (wird mit Akku3 überschrieben). Die beiden *PUSH* kosten die 300-CPU gerade mal 4 Byte Programmspeicher und weniger als 1µs Rechenzeit.

Eine Alternative wäre, den Wert Bereichslaenge-1 im TEMP zwischen-zu-speichern. Ich wollte dafür nicht extra eine Variable benutzen und den bei S7-300 noch im Akku2 vorhandenen Wert weiternutzen. Allerdings funktioniert das eben bei S7-400 und PLCSIM leider nicht.

```
cead: T     #tmp_INT                    //Bereichslaenge-1 zwischenspeichern
      L     #tmp_Anfangsadresse
      +D
      T     #tmp_Endadresse
//**      LAR1                              //(zum Beobachten)

      L     #tmp_INT                    //Bereichslaenge-1 zurück in Akku1
```

Harald


----------



## IBFS (24 März 2011)

PN/DP schrieb:


> Wie testest Du eigentlich Deine Programme?
> CPU geht nicht in STOP -> Programm müßte funktionieren?



Was ist mit dem OB121 (PROG_ERR) ??? 

Frank


----------



## PN/DP (25 März 2011)

IBFS schrieb:


> Was ist mit dem OB121 (PROG_ERR) ???


Was meinst Du damit? Einen Vorschlag, den OB121 in die CPU zu laden?
Das hat er gerade gemacht, nutzt es aber offensichtlich nicht zur Fehlersuche per Programm-Beobachtung.
Eigentlich ist diese register-indirekte Adressierung noch viel zu früh für seine Step7-Fähigkeiten.



Limette schrieb:


> Bei *L     D [AR1,P#2.0] *geht er leider in Stop:
> [...]
> 
> 
> ...





Limette schrieb:


> Habe OB121 nachgeladen und schon läufts.


Limette hat mir auch einige PN geschrieben, u.A. war da ein eigener Versuch dabei, meinen Beispielcode mit festen Adressen in parametrierbaren Code umzuschreiben. Wegen falscher Übernahme der Quell-Adressen aus FB-Inputs tat sein Progammentwurf zwar überhaupt nicht, was er soll, doch weil die CPU dabei nicht (mehr) in Stop ging, war Limettes Aussage 





> dein Code funktioniert ja in der Tat.


.

Harald


----------



## IBFS (25 März 2011)

PN/DP schrieb:


> Was meinst Du damit? Einen Vorschlag, den OB121 in die CPU zu laden?



Die Frage  war eher an Limette gerichtet, weil er wahrscheinlich den Sinn 
von OBs noch nicht komplett erfasst hat.

Ich war gestern an einer Anlage, da war nur der OB1 und der OB100 im Projekt.
Alle anderen schönen OBs waren wahrscheinlich dem Ersteller unbekannt ;-)

Frank


----------



## PN/DP (25 März 2011)

IBFS schrieb:


> Die Frage  war eher an Limette gerichtet, weil er wahrscheinlich den Sinn
> von OBs noch nicht komplett erfasst hat.


Oh, wenn Du meinst, daß Limette den OB121 zur Fehlerauswertung benutzen soll (also die OB121-Fehlerinformationen auswerten statt leerer OB121 zur reinen Stop-Verhinderung), dann meine ich, daß Limette damit zur Zeit rettungslos überfordert wäre. Da muß man ja noch eine Stufe höher abstrahieren als bei der vergleichsweise "einfachen" register-indirekten Adressierung.

Limette braucht erstmal viel Übung mit den vorhandenen Step7-Test/Diagnosemöglichkeiten. Und er sollte sich intensiver mit der register-indirekten Adressierung und Pointern beschäftigen, bis er sie verstanden hat. Besonders auch meinen Programmcode aus #29 beim Ablauf BEOBACHTEN. Nur dann sieht er, was die Operationen mit P# tun und kann daran denken, selbst funktionierende Programmteile zu erstellen.

Harald


----------



## Paule (25 März 2011)

IBFS schrieb:


> Ich war gestern an einer Anlage, da war nur der OB1 und der OB100 im Projekt.
> Alle anderen schönen OBs waren wahrscheinlich dem Ersteller unbekannt ;-)


Hallo Frank,
was ist daran falsch oder verwerflich?
Wenn alles sauber programmiert wurde und ich keine dezentrale Peripherie habe, brauche ich keine Fehler OB's.
Ich habe sie selbst schon nach erfolgter IBN gelöscht, meistens lasse ich sie aber aus Bequemlichkeit drin.


----------



## bike (25 März 2011)

Paule schrieb:


> Hallo Frank,
> was ist daran falsch oder verwerflich?
> Wenn alles sauber programmiert wurde und ich keine dezentrale Peripherie habe, brauche ich keine Fehler OB's.
> Ich habe sie selbst schon nach erfolgter IBN gelöscht, meistens lasse ich sie aber aus Bequemlichkeit drin.



Also ich mache meist den umgekehrten Weg.
Wenn ich an der Anlage sitze ist z.B kein OB121 in der Steuerung.
So kann ich sehen wann das Teil abschmiert 
Bevor ich wegfahre kopiere ich einen rein, damit die Steuerung nicht auf Stopp geht, wenn ich etwas übersehen habe.


bike


----------



## IBFS (25 März 2011)

Paule schrieb:


> Ich habe sie selbst schon nach erfolgter IBN gelöscht, meistens lasse ich sie aber aus Bequemlichkeit drin.





bike schrieb:


> Bevor ich wegfahre kopiere ich einen rein, damit die Steuerung nicht auf Stopp geht, wenn ich etwas übersehen habe.



so verschieden sind die Ansichten 

Richtig wäre - alle OBs rein und in den OBs eine vernünftige Auswertung.
Im OB121 reicht ein BIT im Störungsmeldebereich, so kenne ich das.

Und falls es eine ET200S im System gibt gehört für mich ein OB83
rein, damit kann man unter Dampf jeweils ein Baugruppe im ET200S-
RACK ziehen/stecken ohne das die SPS in STOP geht.

Frank


----------

