# B&R Schieberegister?



## Anaconda55 (13 August 2009)

Habe vor eine Prüfstation zu programmieren.

Es ist ein inkrementargeber für ein Band vorhanden wo sich einzelne Schrauben drauf befinden. 

Ablauf wird folgender sein:

Wenn die Triggerlichtschranke belegt ist wir ein Teil gespeichert, das dann wenn es bei einer Kamera ist die Kamera triggert und dann bekommt die Steuerung von der Kamera IO oder NIO Teil. Je nachdem wird dann ein Teil an Position 1 oder 2 abgeblasen.

Sollte man das ganze über ein Schieberegister machen?
Es kann sein das die Lücken zwischen den Schrauben unterschiedlich sind, sowie die Schraubenabmessungen.

Wie würdet ihr soetwas lösen?


----------



## zotos (13 August 2009)

Ich würde zu einem FIFO greifen. Beherrscht B&R ST?


----------



## Anaconda55 (13 August 2009)

B&R beherrscht ST wird aber in Automation Basic geschrieben.
Fifo okay.
Was noch dazukommt ist wenn man auf das Ergebnis wartet bereits ein neues Teil oder mehere für die Kamera getriggert wird/werden ...


----------



## zotos (13 August 2009)

Schau Dir mal folgenden Thread an:
http://sps-forum.de/showpost.php?p=125571&postcount=7



Anaconda55 schrieb:


> ...
> Was noch dazukommt ist wenn man auf das Ergebnis wartet bereits ein neues Teil oder mehere für die Kamera getriggert wird/werden ...



Darum würde ich ja zu einem FIFO greifen da die Anzahl der gespeicherten Werte variabel ist.


----------



## Anaconda55 (13 August 2009)

Ja sowas habe ich mir schon überlegt, aber wie mache ich es mit den Positionen.

z.B. so:

Array[100]

Bei der TriggerLS folgenden Wert setzen:

Array[1].Bauteilstatus=0
Array[1].Position=0
Array[1].Belegt=TRUE

Trigger Kamera auslösen über eine Schleife die das Array durchläuft und nach Position z.B. 1100 sucht. Wenn True dann Kamera triggern und Status auf 8 (Wartezustand setzen)

Array von hinten nach vorne durchlaufen und abfragen ob Status 8 wenn Status 8 zwischen Kamera und Abblasposition dann IO oder NIO zuweisen, IO Status 1.

Beim Ausblasen genau die gleiche Verfahrensweise:

Abblasen 1 bei 1600. Wenn Position stimmt und Status 1 dann Abblasen und Belegt auf 0 setzen.


----------



## Larry Laffer (13 August 2009)

Hallo,
ich würde es vielleicht in etwa so machen :
Kommt ein Teil (steigende Flanke der 1. Lichtschranke) dann merkst du dir den aktuellen Zählwert der Zählerkarte, an der der Inkrementalgeber angeschlossen ist in der ersten freien Speicher eines ARRAY's.

Zyklisch scannst du die Eintrags-Positionen dieses Array's ob ein gespeicherter Wert plus dem Offset deiner Bearbeitungsposition dem aktuellen Zählerstand entspricht. Ist dem so, dann lösst du die jeweilige Aktion aus.

Genauso kannst du dann mit den weiteren Positionen verfahren ...

Gruß
LL


----------



## Anaconda55 (13 August 2009)

Ja, dass ist auch eine Möglichkeit.

Man muss natürlich noch den Überlauf der Zählermoduls beachten.

Bei der ersten Lichtschranke muss ich es dann aber so machen dass ich bei fallenden Flanke und steigende Flanke zähle, dadurch den Druchmesser der Schraube ermittele und diese Position im Array speichere.

Sollte ja möglich sein?!


----------



## zotos (13 August 2009)

Ich würde das ganz ähnlich wie Larry machen.

Angenommen der Inkrementalgeber liefert fortlaufend einen Vorzeichenlosenwert (z.B. UDINT oder DWORD).

Dann kann man den Detlawert errechnen (das klappt auch beim Überlauf). 

```
Delta :=  Neuerwert - Gespeicherterwert ;
```
Wenn der Delta-Wert nun in einem Toleranzfenster zu gewünschten Position liegt kann der Aktor angesteuert werden.

 Der Ablauf wäre dann wie folgt:

 Immer wenn der Trigger ausgelöst wird, wird ein Eintrag in den FIFO mit dem aktuellen Inkremental wert gemacht.

 Wenn mindestens ein Eintrag im FIFO ist wird dieser gelesen und in jedem SPS-Zyklus der Delta-Wert gebildet wenn dieser Wert im Fenster liegt wird der Aktor angesteuert. Wenn der FIFO nicht leer ist wird ein neuer Wert daraus genommen und das ganze beginnt von vorne.

 Um nun mehrere Abblaspositionen (Gut, Schlecht, sonstwas) verwalten zu können würde ich einfach für jede Abblaspositionen einen eigenen FIFO-Speicher einrichten.


----------



## zotos (13 August 2009)

Anaconda55 schrieb:


> ...
> Man muss natürlich noch den Überlauf der Zählermoduls beachten.
> ...



Muss man nicht. Vorausgesetzt der Inkrementalwert ist Vorzeichenlos.


----------



## Anaconda55 (13 August 2009)

> Muss man nicht. Vorausgesetzt der Inkrementalwert ist Vorzeichenlos.


Verstehe ich nicht, kannst Du mir das genauer erklären?



Angenommen ich setze den Wert bei 1500 die Zielposition ist 1800 bei 1750 wird der Zähler auf 0 gesetzt. 1500 - 1800 währen 300 da er aber zurückgesetzt wird währe er bei 50. 1500 - 50 währen dann 1450.


----------



## zotos (13 August 2009)

Anaconda55 schrieb:


> Verstehe ich nicht, kannst Du mir das genauer erklären?



Meine Aussage stimmt auch nur unter der Voraussetzung das der Abstand zwischen dem Start- und Zielpunkt kleiner eines vollen Inkrementzykluses ist.

Für diesen Fall:

Gilt die Differenz zweier werte ist absolut gesehen gleich.

Hier mal das Beispiel mit Byte (USINT):


```
Delta := Neuerwert - Alterwert;
```


```
0 := 100 - 100;
1 := 101 - 100;
100 := 200 - 100;
155 := 255 - 100;
156 := 0 - 100;
157 := 1 - 100;
206 := 50 - 100;
```


Nun zu dem Fall das der Abstand größer eines Inkrementalzykluses ist dann kann man den von Hand zu Fuß selber bauen.

In jedem SPS-Zyklus das Delta zum vorhergehenden SPS-Zyklus berechnen und den immer auf eine ausreichend große Variable um kopieren in dem man z.B. die Inkremente auf mm umrechnet und diese dann in eine UDINT bzw. DWORD Variable kopiert.... ist das nun verständlich?


----------



## Anaconda55 (13 August 2009)

Ja das ist mir jetzt schon klar.

Allerdings funktioniert das nicht wenn in dieser Strecke der Inkrementalwert 2mal oder öfters auf 0 gesetzt wird.

Eventuell könnte ich es so machen?

Bandtaktvorgabe = 5
iDiff = Inkremental - InkrementalALT

if iDiff >= Bandtaktvorgabe then
  Bandtakt=true
  InkrementalALT = InkrementalALT  + Bandtaktvorgabe 
else
  Bandtakt=false
endif


Bei jedem Bandtakt setze ich dann die Positionen im Array um Bandtaktvorgabe hier 5 hoch.


----------



## zotos (13 August 2009)

zotos schrieb:


> ...
> Nun zu dem Fall das der Abstand größer eines Inkrementalzykluses ist dann kann man den von Hand zu Fuß selber bauen.
> 
> In jedem SPS-Zyklus das Delta zum vorhergehenden SPS-Zyklus berechnen und den immer auf eine ausreichend große Variable um kopieren in dem man z.B. die Inkremente auf mm umrechnet und diese dann in eine UDINT bzw. DWORD Variable kopiert.... ist das nun verständlich?



Also wars doch nicht verständlich ;o(

Hier mal in Codeform:

```
(* Alles was nicht explizit angegeben ist entspricht dem Type UDINT *)

FaktorInkrementeProZehntelmillimeter := InkrementeProUmdrehung * 10 / REAL_TO_UDINT(UDINT_TO_REAL(DurchmesserInMillimeter) * PI); (* muss nicht zyklisch berechnet werden PI idt vom Typ Real *)


DeltaInkremente := InkrementeAktuell - InkrementeLetzerZyklus;
InkrementeLetzerZyklus := InkrementeAktuell;

DeltaZehntelmillimeter := DeltaInkremente / FaktorInkrementeProZehntelmillimeter;

Neuerwert := Neuerwert + DeltaZehntelmillimeter;

Delta := NeuerWert - GespeicherterWert; (* Der Gespeicherte Wert stammt aus dem FIFO *)

InPosition := ((Delta < (Sollposition + Toleranz)) AND (Delta > (Sollposition - Toleranz)); (*InPos ist vom Typ Bool*)
```


----------



## Anaconda55 (13 August 2009)

Ja okay. Das wird wohl auch funktionieren. Aber geht das nicht noch einfacher?


----------



## Anaconda55 (6 September 2009)

Was ist eigentlich mit der Variable "PI" in der ersten Zeile gemeint?


----------



## zotos (6 September 2009)

Die *Kreiszahl* (Pi)


----------



## Anaconda55 (6 September 2009)

Ist die im Codesys gleich als PI definiert oder was?


----------



## zotos (6 September 2009)

nein.

Schreib einfach an stelle PI     3.14159


----------



## Anaconda55 (6 September 2009)

Also da stimmt jetzt was nicht weil z.B. bei UDINT folgendes rauskommt

NeuerWert:=0
GespeicherterWert:=10

Delta := NeuerWert - GespeicherterWert;

Delta Ergebnis = 4294967286

Das heißt das ich nie in Position sein kann ...


----------



## zotos (6 September 2009)

Anaconda55 schrieb:


> Also da stimmt jetzt was nicht ...


*ACK*Sorry!

Leider passt der Code nicht (ich hatte ihn auch nicht getestet).


----------



## Anaconda55 (7 September 2009)

Ja macht nix. Hast mir mit der Theorie alleine schon weitergeholfen ...


----------

