# DI's entprellen



## Küffel (13 August 2007)

Hallo zusammen,

ich suche nach einer Möglichkeit Eingänge für ca. 20-50 ms zu entprellen, am besten ohne Timer. 

Da es sich um ca. 40 Eingänge handelt möchte ich ungern 40 Timer verwenden, wenn ich die überhaupt noch frei habe. 

CPU ist eine 315....

Vielen Dank für jeden Tip!

Gruß
Küffel


----------



## zotos (13 August 2007)

Bau es in einen FB und verwende TONs.


----------



## godi (13 August 2007)

Hier habe ich es mal mit IEC Timer gemacht für ein Byte. (Wie Zotos Vorschlag)

```
FUNCTION_BLOCK FB 1
TITLE =Entprellung von Eingängen
VERSION : 0.1

VAR
  Entprellung_DI_0_0 : SFB 5; 
  Entprellung_DI_0_1 : SFB 5; 
  Entprellung_DI_0_2 : SFB 5; 
  Entprellung_DI_0_3 : SFB 5; 
  Entprellung_DI_0_4 : SFB 5; 
  Entprellung_DI_0_5 : SFB 5; 
  Entprellung_DI_0_6 : SFB 5; 
  Entprellung_DI_0_7 : SFB 5; 
END_VAR
BEGIN
NETWORK
TITLE =Entprellung Eingang 0.0
      CALL #Entprellung_DI_0_0 (
           IN                       := E      0.0,
           PT                       := T#50MS,
           Q                        := E      0.0);//Wenn du den Baustein an erster stelle im OB1 aufrufst dann kannst du den Eingang gleich direkt wieder überschreiben ausser du benötigst den nicht Entprellten Eingang dann solltest du ein DB Bit oder Merker verwenden!

NETWORK
TITLE =Entprellung Eingang 0.1
      CALL #Entprellung_DI_0_1 (
           IN                       := E      0.1,
           PT                       := T#50MS,
           Q                        := E      0.1);

NETWORK
TITLE =Entprellung Eingang 0.2
      CALL #Entprellung_DI_0_2 (
           IN                       := E      0.2,
           PT                       := T#50MS,
           Q                        := E      0.2);

NETWORK
TITLE =Entprellung Eingang 0.3
      CALL #Entprellung_DI_0_3 (
           IN                       := E      0.3,
           PT                       := T#50MS,
           Q                        := E      0.3);

NETWORK
TITLE =Entprellung Eingang 0.4
      CALL #Entprellung_DI_0_4 (
           IN                       := E      0.4,
           PT                       := T#50MS,
           Q                        := E      0.4);

NETWORK
TITLE =Entprellung Eingang 0.5
      CALL #Entprellung_DI_0_5 (
           IN                       := E      0.5,
           PT                       := T#50MS,
           Q                        := E      0.5);

NETWORK
TITLE =Entprellung Eingang 0.6
      CALL #Entprellung_DI_0_6 (
           IN                       := E      0.6,
           PT                       := T#50MS,
           Q                        := E      0.6);

NETWORK
TITLE =Entprellung Eingang 0.7
      CALL #Entprellung_DI_0_7 (
           IN                       := E      0.7,
           PT                       := T#50MS,
           Q                        := E      0.7);

END_FUNCTION_BLOCK
```
 
Wenn deine ganzen Eingänge Byteweiße vorhanden sind kannst du das ja so umprogrammieren das du das ganze Eingangsbyte den FB übergibst und das Entprellte Byte zurückgibst. Dann brauchst du das ganze nicht so oft programmieren.

godi


----------



## xhasx (13 August 2007)

Bei der ET200s kannst du so etwas in der HW-Config machen!!!


----------



## godi (13 August 2007)

xhasx schrieb:


> Bei der ET200s kannst du so etwas in der HW-Config machen!!!


 
Ja das kannst du auch bei CPU'n mit integrierten Eingängen machen aber er hat nur geschrieben das er eine 315... hat und somit bin ich davon ausgegangen das er von normalen Eingangskarten spricht.
Naja den Rest von der Hardware nach den Punkten kann man sich dazudenken... :???: 

godi


----------



## Küffel (13 August 2007)

Ok, sorry das ich nicht mehr geschrieben habe worum es genau geht. Aber die Vermutung von godi war richtig. Es handelt sich größtenteils um normale Digitale Eingabebaugruppen.

Vielen Dank für die Antworten. Werde es mit TONs probieren, auch wenn ich erst mal genau nachlesen muss worum es sich genau handelt  .

Gruß
Küffel


----------



## Küffel (15 August 2007)

godi schrieb:


> Hier habe ich es mal mit IEC Timer gemacht für ein Byte. (Wie Zotos Vorschlag)
> 
> ```
> FUNCTION_BLOCK FB 1
> ...



Hallo godi,

leider habe ich noch nichts viel (eigentlich nicht mit SCL) gemacht. Aber ich denke ich werde mich einlesen, dein Beispiel sieht schön strukturiert aus. Ich habe es auch mal versucht in eine SCL Quelle einzufügen. Leider ohne Erfolg. Erstmal gehe ich davon aus, du meintest SFB4 nicht 5, richtig? 

Die Variablen Deklaration verstehe ich noch nicht so richtig: du legst eine Variable "Entprellung_DI_0_0" an, die vom TYP SFB4 ist, richtig? 

Diese werden dann in den Lokaldaten von FB1 gespeichert, richtig? Damit braucht man dann nicht mehr für jeden SFB4 aufruf einen eigenen Instanzdatenbaustein, oder?

Meine SCL Version meckert schon über den Titelbezeichner vom Netzwerk. Verison 5.3.1, mit welcher version hast du programmiert?


Was ich danach nicht verstehe ist der CALL. Du rufst eine Funktion, wo ich dachte es sei eine Variable, hmmm, hier gebe ich erst mal auf und warte auf weitere Tipps... 

Danke schon mal vorab!

Gruß
Küffel


----------



## the bang 2 (15 August 2007)

Anfängerfrage - was versteht man unter "entprellen" ?


----------



## zotos (15 August 2007)

Küffel schrieb:


> Hallo godi,
> 
> leider habe ich noch nichts viel (eigentlich nicht mit SCL) gemacht.
> ...



Du kannst ja nicht mal AWL von SCL unterseiden ;o(

Das von godi ist eine AWL Quelle!


----------



## IBFS (15 August 2007)

the bang 2 schrieb:


> Anfängerfrage - was versteht man unter "entprellen" ?


 
Wenn du einen Taster drückst, dan schließt der Kontakt nicht sofort dauerhaft....

....sondern er hüpft (prellt - vgl. Prellbock oder Prellball) manchmal kurzzeitig minimal auf und ab. 
Wenn du an den Taster einen Zählereingang schalten würdest, dann würde also der Zählerstand 
nach einem Tastendruck nicht "1" sondern evtl. "3" oder "4" betragen.


Deshalb entpellen - MINDESEINSCHALTZEIT erst dann AKTION

Gruß


----------



## Küffel (15 August 2007)

zotos schrieb:


> Du kannst ja nicht mal AWL von SCL unterseiden ;o(
> 
> Das von godi ist eine AWL Quelle!



Jetzt wirds peinlich, dachte es sei scl. dann wurdert mich das mit den netzwerken auch nicht
Wusste gar nicht, dass man auch awl-quellen einbinden kann. Mach das ganze nur hobby mäßig! Man lernt halt nie aus!


----------



## zotos (15 August 2007)

Küffel schrieb:


> Jetzt wirds peinlich, dachte es sei scl. dann wurdert mich das mit den netzwerken auch nicht
> Wusste gar nicht, dass man auch awl-quellen einbinden kann. Mach das ganze nur hobby mäßig! Man lernt halt nie aus!



Nicht schlimm hier sind einige "Profis" die damit ihr Geld verdienen die den Unterschied auch nicht erkannt hätten ;o)


----------



## Küffel (15 August 2007)

zotos schrieb:


> Nicht schlimm hier sind einige "Profis" die damit ihr Geld verdienen die den Unterschied auch nicht erkannt hätten ;o)



Sehr gut, die Antwort ermuntert mich doch sofort eine neue Frage zu stellen:

Kann man in der AWL quelle eine Konstante definieren? Falls ich die 50ms ändern muss will ich dies nur einmal machen. Oder muss ich ne statische Variable in meinem DB verbraten?


----------



## IBFS (15 August 2007)

...wenn du gaaaanz oben im FC eine TEMP  mit dem gewünschten Wert lädst, dann hast du deine LOKAL wirkende KONSTANTE.


Gruß


----------



## zotos (15 August 2007)

Das geht auch in der Quelle.


```
VAR
Entprellung_DI_0_0 : SFB 5; 
myTime : TIME := T#50ms;

END_VAR

CALL #Entprellung_DI_0_0 (
   IN                       := E      0.0,
   PT                       := #myTime,
   Q                        := E      0.0);
```

Ungetestet !


----------



## IBFS (15 August 2007)

VAR
myTime : TIME := T#50MS; 
END_VAR

geht natürlich im FB, weils im STAT-Bereich liegt.
Diese Deklaration schreibt aber NUR der Anfangswert.
und ist in der VAT immer ONLINE änderbar.
Das natürlich für jeden FB-Aufruf getrennt. 

Deshalb bei späteren Änderungen lieber im Codebereich
nochmal zusätzlich laden:

myTime := T#50MS; 


Gruß


----------



## zotos (15 August 2007)

IBFS schrieb:


> ...
> Deshalb bei späteren Änderungen lieber im Codebereich
> nochmal zusätzlich laden:
> 
> ...



Das ist nun aber SCL ;o)

AWL in etwa so:

```
L     T#50MS
 T     #myTime
```


----------



## IBFS (15 August 2007)

...jaja ,  hab den gaaazen Tag heute nur SCL programmiert   :-D :-D


----------



## zotos (15 August 2007)

IBFS schrieb:


> ...jaja ,  hab den gaaazen Tag heute nur SCL programmiert   :-D :-D



Lobenswert!
@Küffel: SCL Lohnt sich ;o)


----------



## IBFS (15 August 2007)

...auch wenns jetzt langsam OT wird, aber ich bin SCL und CFC (ohne PCS7) - Fan.

Einigen Firmen kann ich sogar meine SCL-Bausteine unterjubeln ohne dasse maulen, waaaas kein KOP/FUP/AWL!

Gruß


----------



## hovonlo (15 August 2007)

Also wenn ihr wirklich nur vom Entprellen des 0 -> 1 Übergangs sprecht, dann ist die Lösung mit dem SFB 5 ja ganz ok. Aber wo steht bitte in der ursprünglichen Fragestellung, dass es nur um 0 -> 1 geht?? Wenn es darum geht, generell kurze Störungen zu unterdrücken, dann sollte doch wohl auch der 1 -> 0 Übergang entsprechend behandelt werden.
Mir ist schon klar, dass der angesprochene Taster normalerweise nur beim Schließen prellt, aber geht's hier wirklich um die klassische Tastaturentprellung?


----------



## Küffel (16 August 2007)

hovonlo schrieb:


> Also wenn ihr wirklich nur vom Entprellen des 0 -> 1 Übergangs sprecht, dann ist die Lösung mit dem SFB 5 ja ganz ok. Aber wo steht bitte in der ursprünglichen Fragestellung, dass es nur um 0 -> 1 geht?? Wenn es darum geht, generell kurze Störungen zu unterdrücken, dann sollte doch wohl auch der 1 -> 0 Übergang entsprechend behandelt werden.
> Mir ist schon klar, dass der angesprochene Taster normalerweise nur beim Schließen prellt, aber geht's hier wirklich um die klassische Tastaturentprellung?



Mir geht es nur um den Übergang 0-->1 und SFB4!


----------



## godi (16 August 2007)

Küffel schrieb:


> Hallo godi,
> 
> leider habe ich noch nichts viel (eigentlich nicht mit SCL) gemacht. Aber ich denke ich werde mich einlesen, dein Beispiel sieht schön strukturiert aus. Ich habe es auch mal versucht in eine SCL Quelle einzufügen. Leider ohne Erfolg. Erstmal gehe ich davon aus, du meintest SFB4 nicht 5, richtig?
> 
> ...


 
Hallo!

Ja sorry, meinte natürlich SFB 4!

Variablendekleration:
Ja habe eine Variable im Statischen Bereich des FB's angelegt vom Typ SFB (4) Das ist dann eine Multiinstanz! 
Also alle Statischen Variablen vom SFB 4 werden dann zugleich die Statischen Variablen vom FB wo die Variable deklariert ist und somit braucht man nur mehr einen Instanzdatenbaustein für den übergeordneten FB.

Call #Variablennamen:
Ja hier rufe ich den SFB über den Variablennamen auf weil es ja eine Multiinstanz ist.
Also durch den Variablennamen weiß dann die CPU wo sich der Speicherbereich des SFB im übergeordneten Instanzdatenbaustein befindet.
Natürlich kannst du bei Multiinstanzen den Variablennamen nur einmal aufrufen sonst würde es nicht funktionieren weil sich die Speicherbereiche im IDB selbst überschreiben würden.
Wenn du jetzt 2 mal den SFB benötigst dann musst du auch 2 mal eine Variable deklarieren mit dem SFB!

godi


----------



## godi (17 August 2007)

So und weil hier auch immer das Gespräch von SCL ist/war habe ich mal einen Baustein in SCL geschrieben (SCL muss ich eh lernen) wo als Input ein Byte angegeben werden kann und als Output kommt das Entprellte Byte heraus. Natürlich kann man auch die Verzögerungszeit einstellen!  

Ich hoffe es stimmt halbwegs was ich programmiert habe aber die SCL Profis werden mich schon korrigieren!  
Funktionieren tuts auf jeden Fall mal!  


```
FUNCTION_BLOCK FB2
VERSION : '0.1'
AUTHOR  : godi
NAME    : Byte_Entprellen
FAMILY  : Byte_Entprellen
 
VAR_INPUT
    Unentprelltes_Byte : BYTE;  //Eingangsbyte wo die einzelnen Bits Einschaltverzögert ausgegeben werden
    Entprellzeit : TIME;        //Zeit für Einschaltverzögerung
END_VAR
 
VAR_OUTPUT
    Entprelltes_Byte : BYTE;    //Ausgangsbyte -> alle Bits sind schon entprellt
END_VAR
 
VAR_TEMP
    Unentprelltes_Word : WORD;
    Entprelltes_Word : WORD;
    IN_Bit_Timer AT Unentprelltes_Word : ARRAY [0..15] OF BOOL;
    OUT_Bit_Timer AT Entprelltes_Word : ARRAY [0..15] OF BOOL;
    Entprelltes_Byte_Array AT Entprelltes_Word : ARRAY [0..1] OF BYTE;
    Bit_Index : INT;
END_VAR
 
VAR    
  Entprellung_Bit_0 : SFB4;    
  Entprellung_Bit_1 : SFB4; 
  Entprellung_Bit_2 : SFB4; 
  Entprellung_Bit_3 : SFB4; 
  Entprellung_Bit_4 : SFB4; 
  Entprellung_Bit_5 : SFB4; 
  Entprellung_Bit_6 : SFB4; 
  Entprellung_Bit_7 : SFB4;   
END_VAR
 
BEGIN
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Wandle Byte in Word wegen AT Befehl
Unentprelltes_Word := BYTE_TO_WORD(Unentprelltes_Byte);
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Entprellung Bit 0
Bit_Index := 0 + 8; // + 8 für niederwertiges Byte wegen Wandlung zu Word
Entprellung_Bit_0(IN := IN_Bit_Timer[Bit_Index] // IN: BOOL
          ,PT := Entprellzeit // IN: TIME
          ); 
 //Bit_Index := 0         
 OUT_Bit_Timer[Bit_Index] := Entprellung_Bit_0.Q; // OUT: BOOL
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
//Entprellung Bit 1
Bit_Index := 1 + 8; // + 8 für niederwertiges Byte wegen Wandlung zu Word
Entprellung_Bit_1(IN := IN_Bit_Timer[Bit_Index] // IN: BOOL
          ,PT := Entprellzeit // IN: TIME
          ); 
 OUT_Bit_Timer[Bit_Index] := Entprellung_Bit_1.Q; // OUT: BOOL
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Entprellung Bit 2
Bit_Index := 2 + 8; // + 8 für niederwertiges Byte wegen Wandlung zu Word
Entprellung_Bit_2(IN := IN_Bit_Timer[Bit_Index] // IN: BOOL
          ,PT := Entprellzeit // IN: TIME
          ); 
 OUT_Bit_Timer[Bit_Index] := Entprellung_Bit_2.Q; // OUT: BOOL
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Entprellung Bit 3
Bit_Index := 3 + 8; // + 8 für niederwertiges Byte wegen Wandlung zu Word
Entprellung_Bit_3(IN := IN_Bit_Timer[Bit_Index] // IN: BOOL
          ,PT := Entprellzeit // IN: TIME
          ); 
 OUT_Bit_Timer[Bit_Index] := Entprellung_Bit_3.Q; // OUT: BOOL
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Entprellung Bit 4
Bit_Index := 4 + 8; // + 8 für niederwertiges Byte wegen Wandlung zu Word
Entprellung_Bit_4(IN := IN_Bit_Timer[Bit_Index] // IN: BOOL
          ,PT := Entprellzeit // IN: TIME
          ); 
 OUT_Bit_Timer[Bit_Index] := Entprellung_Bit_4.Q; // OUT: BOOL
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Entprellung Bit 5
Bit_Index := 5 + 8; // + 8 für niederwertiges Byte wegen Wandlung zu Word
Entprellung_Bit_5(IN := IN_Bit_Timer[Bit_Index] // IN: BOOL
          ,PT := Entprellzeit // IN: TIME
          ); 
 OUT_Bit_Timer[Bit_Index] := Entprellung_Bit_5.Q; // OUT: BOOL
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Entprellung Bit 6
Bit_Index := 6 + 8; // + 8 für niederwertiges Byte wegen Wandlung zu Word
Entprellung_Bit_6(IN := IN_Bit_Timer[Bit_Index] // IN: BOOL
          ,PT := Entprellzeit // IN: TIME
          ); 
 OUT_Bit_Timer[Bit_Index] := Entprellung_Bit_6.Q; // OUT: BOOL
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Entprellung Bit 7
Bit_Index := 7 + 8; // + 8 für niederwertiges Byte wegen Wandlung zu Word
Entprellung_Bit_7(IN := IN_Bit_Timer[Bit_Index] // IN: BOOL
          ,PT := Entprellzeit // IN: TIME
          ); 
 OUT_Bit_Timer[Bit_Index] := Entprellung_Bit_7.Q; // OUT: BOOL
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Schreibe Entprelltes Byte
Entprelltes_Byte := Entprelltes_Byte_Array[1];
 
END_FUNCTION_BLOCK
```
 
godi


----------



## Küffel (18 August 2007)

godi schrieb:


> So und weil hier auch immer das Gespräch von SCL ist/war habe ich mal einen Baustein in SCL geschrieben (SCL muss ich eh lernen) wo als Input ein Byte angegeben werden kann und als Output kommt das Entprellte Byte heraus. Natürlich kann man auch die Verzögerungszeit einstellen!
> 
> Ich hoffe es stimmt halbwegs was ich programmiert habe aber die SCL Profis werden mich schon korrigieren!
> Funktionieren tuts auf jeden Fall mal!
> ...



Sehr schön, ich habe es natürlich sofort ausprobiert und es scheint tatsächlich zu funktionieren!!!!! Ich habe zwar deine Lösung 1 bereits umgesetzt (für insgesamt 50! Eingänge), allerdings bereitet mir der Speicher ein kleines Problem. Diese Lösung hier ist wesentlich kleiner.

Ich versuche das Progrämmchen zu verstehen, und werde noch versuchen eine Maske als Eingang einzubauen, da ich häufig nur 7 Bit eines Bytes Filtern will! Oder hast du auf die schnelle noch eine Idee?

Auf jeden Fall ein großes Danke an die Hilfsbereitschaft, auch wenns nicht ganz Uneigennützig ist und du was lernen möchtest:-D 

Gruß
Küffel


----------



## Küffel (18 August 2007)

Noch eine Frage, eigentlich sieht es so aus, als könnte man das ganze schön durch eine FOR schleife laufen lassen: 

```
VAR_INPUT
    Unentprelltes_Byte : BYTE;  //Eingangsbyte wo die einzelnen Bits Einschaltverzögert ausgegeben werden
    Entprellzeit : TIME;        //Zeit für Einschaltverzögerung
END_VAR
 
VAR_OUTPUT
    Entprelltes_Byte : BYTE;    //Ausgangsbyte -> alle Bits sind schon entprellt
END_VAR
 
VAR_TEMP
    Unentprelltes_Word : WORD;
    Entprelltes_Word : WORD;
    IN_Bit_Timer AT Unentprelltes_Word : ARRAY [0..15] OF BOOL;
    OUT_Bit_Timer AT Entprelltes_Word : ARRAY [0..15] OF BOOL;
    Entprelltes_Byte_Array AT Entprelltes_Word : ARRAY [0..1] OF BYTE;
    Bit_Index : INT;
    Loop_Index : INT ;

END_VAR
 
VAR      
    Entprellung_Bit_X : ARRAY[0..7] OF SFB4; 
END_VAR
 
BEGIN
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Wandle Byte in Word wegen AT Befehl
Unentprelltes_Word := BYTE_TO_WORD(Unentprelltes_Byte);
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
FOR Loop_Index:=0 TO 7 DO
//Entprellung Bit 0
Bit_Index := #Loop_Index + 8; // + 8 für niederwertiges Byte wegen Wandlung zu Word
Entprellung_Bit_X[Loop_Index](IN := IN_Bit_Timer[Bit_Index] // IN: BOOL
          ,PT := Entprellzeit // IN: TIME
          ); 
 //Bit_Index := 0         
 OUT_Bit_Timer[Bit_Index] := Entprellung_Bit_X[Loop_Index].Q; // OUT: BOOL
EXIT
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Schreibe Entprelltes Byte
Entprelltes_Byte := Entprelltes_Byte_Array[1];
 
END_FUNCTION_BLOCK
```

Leider funktioniert die Variablendeklaration von SFB4 in einem Array nicht. Gibts eine Chance?


----------



## godi (18 August 2007)

Küffel schrieb:


> Leider funktioniert die Variablendeklaration von SFB4 in einem Array nicht. Gibts eine Chance?


 
Hallo!

Ja leider funktioniert in SCL ein Array of SFB (generell mit Bausteinen) nicht! :twisted: 
Ich glaube aber das es mit ST von Codesys möglich ist. Zotos weiß das bestimmt.
@Siemens: Hängt euch rein und ändert das!

godi


----------



## Küffel (18 August 2007)

Guten Morgen godi,

wenn du schon so früh da bist:

Warum wandelst du erst alles in WORD? Warum kann man nicht auf Byte Ebene arbeiten? 

Echt mist, dass das mit dem Array auf SFB4 Type nicht geht. Man könnte ein struct erstellen, das dem type von SFB4 entspricht, oder?


----------



## godi (18 August 2007)

Wegen den AT Befehl wandle ich alles in Word.
lese hier http://www.sps-forum.de/showthread.php?t=15026

Ja Vielleicht kommst ja noch auf ne bessere Lösung mit dem SFB 4! Wie gesagt bin selbst noch am herumprobieren mit SCL.


----------

