Siemens Simatic S7 SCL Programlama Dili

Yarı çapı r olan cemberin, cevresi ve alanını hesaplar, cisim küre ise hacmini ve yüzey alanını hesaplar
http://tr.wikipedia.org/wiki/K%C3%BCre_%28geometri%29
Kod:
FUNCTION FC13 : VOID
(* www.kontrolkalemi.com, programlayan:=elektronikmuh 
Bu prg SCL ile matematiksel işlemlerin ne kadar basit old. göstermek için yapılmıştır*)
VAR_INPUT
    R:REAL;
END_VAR

VAR_OUTPUT
    Cevre,Alan:REAL;
    KureHacim,KureYuzeyAlani:REAL;
END_VAR

CONST
    pi:=3.1415926535897932384626433832795;
END_CONST

BEGIN
    Cevre           :=2*pi*R;
    Alan            :=pi*R*R; 
    KureHacim       :=4/3*pi*R*R*R;
    KureYuzeyAlani  :=4*pi*R*R;       
END_FUNCTION
 
Son düzenleme:
İki noktası (x1,y1) ve (x2,y2) olan doğrunun denklemini bulur ve herhangi bir x degeri için fonksiyonun sonucunu hesaplar.
Doğrusal denklemlerle ilgili bilgi için:
http://tr.wikipedia.org/wiki/Doğru_denklemi

http://www.frmtr.com/geometri/1438388-analitik-geometri-genis-anlatim.html

Kod:
FUNCTION F_LIN2 : REAL  // Fonk. sonucu y degeri
TITLE = 'F_LIN2'

//this function calculates the linear equation f_lin = a*x + b given by two points x1/y1 and x2/y2.


VAR_INPUT       //Değişkenleri tanıtma kısmımız
    X : REAL;   // X için sonucu hesaplanacak değişken
    X1: REAL;   // Varolan x1 degeri
    Y1 : REAL;  // Varolan  y1 degeri
    X2 : REAL;  // Varolan x2 degeri
    Y2 : REAL;  // Varolan y2 degeri
END_VAR

BEGIN    //Programımız burdan başlıyor
     
     IF X1 = X2 THEN
          F_LIN2 := 0;
     ELSE
          F_LIN2 := (Y2 - Y1) / (X2 - X1) * (X - X1) + Y1;
     END_IF

END_FUNCTION
 
Son düzenleme:
Kod:
FUNCTION_BLOCK LTCH
TITLE = 'LTCH'
(* L girişi true oldugu surece, D girişindeki bool sinyal Q çıkışına atanır,
L yi false çektigimizde D deki son konum Q da kalır ta ki RST gelene kadar *)
VAR_INPUT
    D : BOOL;
    L : BOOL;
    RST : BOOL;
END_VAR
VAR_OUTPUT
    Q : BOOL;
END_VAR
VAR
END_VAR

BEGIN

(* as long as L is true, the latch is transparent and and change of D is transferred to Q *)
(* of course only when there is no asynchronous reset *)
IF rst THEN       (* if asynchronous reset then Q=0 *)
    Q := FALSE;
ELSIF L THEN      (* latch is transparent *)
    Q := D;
END_IF;

END_FUNCTION_BLOCK
 
Flip Floplarla ilgili bilgi için:
http://hbogm.meb.gov.tr/modulerprogramlar/kursprogramlari/elektrik/moduller/lojikuygulamalar2.pdf

http://hbogm.meb.gov.tr/modulerprogramlar/kursprogramlari/elektrik/moduller/lojikuygulamalar3.pdf

Kod:
FUNCTION_BLOCK FF_JKE

//JK-type flip flop with set, reset and rising clock trigger
//set and reset are asynchron while the FF is rising edge triggered
//J=0 and K=0 and CLK >>> no action
//J=1 and K=0 and CLK >>> output = 1
//J=0 and K=1 and CLK >>> output = 0
//J=1 and K=1 and CLK >>> toggle output

VAR_INPUT
  SET : BOOL;
  J : BOOL;
  CLK : BOOL;
  K : BOOL;
  RST : BOOL;
END_VAR
VAR_OUTPUT
  Q : BOOL;
END_VAR
VAR
  edge : BOOL;
END_VAR

BEGIN

IF rst OR set THEN
    Q := NOT rst;
ELSIF clk AND NOT edge THEN
    IF J XOR K THEN Q := J;
    ELSE Q := K XOR Q;
    END_IF;
END_IF;
edge := CLK;

END_FUNCTION_BLOCK
 
Operator Panelinden Reçete numarasını seçeceksin.
Operator panelinde recete oluşturacaksın.
Operator panelinden Receteyi bir tampon DB'ye yazacaksın.
Kullanmak istediğin Receteyi seçip Reçete yaz dediğinde istediğin bir DB'ye Reçeteyi aktaracaksın.

Bunu yapabilen SCL kodları;
Kod:
FUNCTION_BLOCK FB10
TITLE = 'recete'

VAR_INPUT
    Recete_no:INT;         //Recete Numarasi Belirlenir
    Recete_Adimi:INT;      //Recetenin Kac Adimdan Olusacagi Belirlenir
    Recete_Kaydet:BOOL;    //Recete Tampon_DB'ye yazilir
    Recete_Yaz:BOOL;       //Receteyi Out_DB'ye yazar

END_VAR

VAR
    n:INT;
    x:INT;
    Adim:INT;
END_VAR

BEGIN
IF Recete_Adimi=0 THEN
    Adim:=2;
ELSE
    Adim:=Recete_Adimi;
END_IF;
  
IF Recete_Kaydet THEN
    FOR n:=0 TO  Adim-2 BY 2 DO
        DB3.DW[(Recete_no*Adim)+n]:=DB2.DW[n];
    END_FOR;
END_IF;

IF Recete_Yaz THEN
    FOR x:=0 TO Adim-2 BY 2 DO
       DB4.DW[x]:=DB3.Dw[(Recete_no*Adim)+x];
    END_FOR;
END_IF;
       
END_FUNCTION_BLOCK

Projede MW20 ile reçete numarasını seçiyorsun.
Operator panelinden DB2'ye reçeteni yazabilirsin.
DB3 Tampon DB'dir.
M22.0 1 olduğunda;
MW20 ile belirlediğin adres ve reçete adımına göre tampon DB'ye yazılır.
DB4 Output DB'dir.
M22.1 1 olduğunda MW20 ile belirlediğin reçete numarası Output DB'ye yazılır.

Registerdaki veriyi adres olarak kullanmak için en kolay yol bence bu. Yazdığım SCL kodunda karmaşık çok fazla şey olduğunu düşünmüyorum. Biraz incelersen kolayca ne yapmaya çalıştığımı anlayabilirsin. Tampon DB diye adlandırdığım DataBlock senin tüm reçetelerinin saklandığı datablock'tur. Oluşturduğun tüm reçeteler Tampon DB'de saklanacaktır. MW20 ile Tampon DB'nin hangi adresinden itibaren yazmaya ve okumaya başlayacağını belirlersin.

https://www.kontrolkalemi.com/forum/konu/s7-300-de-register-İçeriğini-adres-olarak-kullanmak.22464/
konusundan alıntıdır...
Katkılarından dolayı "morfeus" üyemize teşekkür ederiz...
 
Aşağıdaki kod girişindeki REAL tipi bir değişkenin (bu degişken herhangi bir bilgi olabilir, pozisyon, sıcaklık, basınç, seviye, ağırlık vb) minimum ve max. yaptığı değerleri çıkışına(mx,mn) yazar.

Kod:
FUNCTION_BLOCK FT_MIN_MAX
TITLE = 'FT_MIN_MAX'

VAR_INPUT
    in : REAL;    // Giriş değişkenimiz
    rst : BOOL;   // Reset girişi
END_VAR
VAR_OUTPUT
    mx : REAL;   // Yakalanan Max.
    mn : REAL;   // Yakalanan Min.  değer
END_VAR
VAR
    init: BOOL;  // sis. ilk açıldıgında in degerini mx ve mn ye atmak için degişken
END_VAR

BEGIN            // Prg. başı

  IF rst OR NOT init THEN  // Reset varsa veya init yoksa  sistem ilk açıldıgında
    mn := in;              // mn  :=in
    mx := in;              // mx  :=in yapar
    init := 1;
  ELSIF in < mn THEN       //Giriş degeri mn den küçükse  mn:=in olur
    mn := in;
  ELSIF in > mx THEN       //Giriş degeri mx dan büyükse  mx:=in olur
    mx := in;
  END_IF;
END_FUNCTION_BLOCK         //Prg. sonu
 
Son düzenleme:
D girişindeki Bool tipi veri, A0, A1, A2 adresleme uçlarılarıyla binary olarak seçilen çıkışlara sürekli aktarılır. Yukarıdaki tabloda çalışma karekteristiği verilmiştir.
Tabloda D girişindeki data sinyali, A0, A1,A2 uçlarından adres değiştirilerek, D deki On-Off bilgisi Q0-Q7 arasındaki çıkışlara(adreslere) aktarılmıştır.

Kod çözücülerle ilgili daha fazla bilgi için(sayfa 47/97):

http://hbogm.meb.gov.tr/modulerprogramlar/kursprogramlari/elektrik/moduller/lojikuygulamalari1.pdf

Kod:
FUNCTION_BLOCK DEC_8
TITLE = 'DEC_8'
//a bit input will be decoded to one of the 8 outputs
//dependent on the Adress on A0, A1 and A2

VAR_INPUT
    D: BOOL;
    A0: BOOL;
    A1: BOOL;
    A2: BOOL;
END_VAR
VAR_OUTPUT
    Q0: BOOL;
    Q1: BOOL;
    Q2: BOOL;
    Q3: BOOL;
    Q4: BOOL;
    Q5: BOOL;
    Q6: BOOL;
    Q7: BOOL;
END_VAR
VAR
    X : INT;
        _X AT X : ARRAY[0..15] OF BOOL;
END_VAR

BEGIN

x := 0; _X[8] := A0; _X[9] := A1; _X[10] := A2;

Q0 := FALSE;
Q1 := FALSE;
Q2 := FALSE;
Q3 := FALSE;
Q4 := FALSE;
Q5 := FALSE;
Q6 := FALSE;
Q7 := FALSE;
 
CASE X OF
    0 : Q0 := D;
    1 : Q1 := D;
    2 : Q2 := D;
    3 : Q3 := D;
    4 : Q4 := D;
    5 : Q5 := D;
    6 : Q6 := D;
    7 : Q7 := D;
END_CASE;

END_FUNCTION_BLOCK
 
Yukarıdaki kodla biraz oynayarak bu sefer işlemin tam tersini yapalım, yani D0 ila D7 arasından gelen çeşitli bool tipindeki data sinyallerinden hangisini çıkışa aktaracağımızı, A0,A1,A2 adres uçlarıyla seçerek çıkışa aktaralım. Burda tek çıkış var! O çıkış biz hangi adresi seçersek girişteki adresten datayı alıp tek bir çıkışa sürekli yazıyor.

Kod:
FUNCTION_BLOCK MUX_8
TITLE = 'MUX_8'

VAR_INPUT
     D0:  BOOL;
     D1:  BOOL;
     D2:  BOOL;
     D3:  BOOL;
     D4:  BOOL;
     D5:  BOOL;
     D6:  BOOL;
     D7:  BOOL;
    A0: BOOL;
    A1: BOOL;
    A2: BOOL;
END_VAR
VAR_OUTPUT
    Q: BOOL;
END_VAR
VAR
    X : INT;
        _X AT X : ARRAY[0..15] OF BOOL;
END_VAR

BEGIN

x := 0; _X[8] := A0; _X[9] := A1; _X[10] := A2;

 
CASE X OF
    0 : Q := D0; 
    1 : Q := D1; 
    2 : Q := D2; 
    3 : Q := D3; 
    4 : Q := D4; 
    5 : Q := D5; 
    6 : Q := D6; 
    7 : Q := D7; 
    
END_CASE;

END_FUNCTION_BLOCK
 
Aşağıdaki örnekte bir Db içinde rastgele verilmiş 32 adet real tipinde veriyi küçükten büyüğe sıralattım kodda ufak bir oynama yaparak tersinide yapabilirsiniz.
Fantazi yapmak isteyen ark.lar verilerin toplayıp, ortalamasını aldırıp, standart sapmasını da hesaplatabilir, datalar içindeki enküçük ve enbüyük verileri buldurtabilirsiniz, SCL için bunlar iş degildir.

Kod:
FUNCTION_BLOCK FB100

VAR_IN_OUT
     Start:INT;  // Hedef DB deki (DB aşağıda)  başlangıç indeksi
     End  :INT;  // Hedef DB deki son indeks
END_VAR

VAR
    i,j:INT;
    Swap:REAL;  // Takas degişkeni verileri yer degiştirmede kullandım
END_VAR    

BEGIN
    FOR i:=Start    TO (End-1) BY 1     DO   // İç içe iki for döngüsüyle verileri 
        FOR j:= i+1 TO End     BY 1     DO     // tarıyoruz
            IF DB101.Data[i]> DB101.Data[j] THEN  // i ve j inci veriler test edilir
                Swap         :=DB101.Data[j];    // Yer degiştirme işlemi yapıyoruz 
                DB101.Data[j]:=DB101.Data[i];
                DB101.Data[i]:=Swap;
            END_IF;
        END_FOR;
    END_FOR;

END_FUNCTION_BLOCK

DATA_BLOCK DB101    //Hedef DB miz DB101, 32 adet bilgi var içinde
STRUCT
    Data       : ARRAY [0..31] OF REAL;
END_STRUCT    
BEGIN

END_DATA_BLOCK
 
Son düzenleme:
PID kontrol algoritması
FB41 kadar iyi olmayabilir ama :D

REF : referans girişi (int)
C : geri besleme (int)
CLOSED_LOOP : PID / açık çevrim seçeneği. 1-PID
P_SEL , I_SEL , D_SEL : P/I/D enable
RESET : PID değerlerini resetler. 1-Reset
T : Örnekleme zamanı (REAL)
TI, TD, KC : PID parametreleri (REAL)
Umin , Umax : Saturasyon
U : Kontrol işareti (int)

Kod:
FUNCTION_BLOCK FB241

VAR_INPUT
REF:INT;
C:INT ;
CLOSED_LOOP:BOOL;
P_SEL:BOOL;
I_SEL:BOOL;
D_SEL:BOOL;
RESET:BOOL;
T:REAL;
TI:REAL;
TD:REAL;
KC:REAL;
Umin:REAL;
Umax:REAL;
END_VAR

VAR
CR_1:REAL;
I_1:REAL;
END_VAR

VAR_TEMP
UminR:REAL;
UmaxR:REAL;
UR:REAL;
D:REAL;
I:REAL;
P:REAL;
REFR:REAL;
ER:REAL;
CR:REAL;
END_VAR

VAR_OUTPUT
U:INT; 
END_VAR

UR:=INT_TO_REAL(U);
REFR:=INT_TO_REAL(REF);
CR:=INT_TO_REAL(C);

IF T>0.0 THEN
    IF CLOSED_LOOP THEN
        ER:=REFR-CR;
        UminR:=Umin;
        UmaxR:=Umax;
      
        IF UmaxR>=32767.0 THEN
            UmaxR:=32767.0;
        END_IF;
        IF UminR<=-32767.0 THEN
            UminR:=-32767.0;
        END_IF;
      
        IF P_SEL THEN
        P:=KC*ER;
        ELSE
        P:=0.0;
        END_IF;
  
        IF TI>0 THEN
            IF I_SEL THEN    
                I:=I_1 + KC *(T/TI) * ER;
                IF UR>=UmaxR THEN
                   I:=I_1;
                END_IF;
                IF UR<=UminR THEN
                   I:=I_1;
                END_IF;  
                I_1:=I;
            ELSE
                I:=0.0;
                I_1:=0.0;
            END_IF;
        ELSE
            I:=0.0;
            I_1:=0.0;
        END_IF;
  
        IF D_SEL THEN
        D:=KC * (TD/T) * (CR_1 - CR);
        IF D>=UmaxR THEN
            D:=UmaxR;
        END_IF;
        IF D<=UminR THEN
            D:=UminR;
        END_IF;
        CR_1:=CR;
        ELSE
        D:=0.0;
        END_IF;

        UR:=P + I + D;
        IF UR>=UmaxR THEN
            UR:=UmaxR;
        END_IF;
        IF UR<=UminR THEN
            UR:=UminR;
        END_IF;
        U:=REAL_TO_INT(UR);

    END_IF;
END_IF;

IF CLOSED_LOOP=0 THEN
    UR:=REFR;
    U:=REAL_TO_INT(UR);
END_IF;

IF RESET THEN  
    D:=0.0;
    I:=0.0;
    I_1:=0.0;
    P:=0.0;
    UR:=0.0;
    REFR:=0.0;
    ER:=0.0;
    CR:=0.0;
    CR_1:=0.0;
END_IF;

END_FUNCTION_BLOCK

not : https://www.kontrolkalemi.com/forum/konu/scl-ile-pid-fonksiyon-blok-s7-300-400.28882/#post160652

konusundan alıntıdır.
Katkılarından dolayı ABSY üyemize kontrolkalemi adına teşekkürü borç biliriz...
 
Son düzenleme:

Forum istatistikleri

Konular
129,903
Mesajlar
931,173
Kullanıcılar
452,789
Son üye
yigitt.m

Çevrimiçi üyeler

Geri
Üst