Programarea aplicatiilor SCADA
  • Obiective
  • Organizarea sarcinilor de lucru
    1.Instructiunea FOR


         In multe cazuri e nevoie sa se repete executia uneia sau mai multor instructiuni. Exista o serie de instructiuni repetitive cum ar fi: instructiunea for, instructiunea while, etc.

        Instructiunea for Se foloseste pentru a executa repetitiv o instructiune sau o secventa de instructiuni. De obicei implementeaza structura ciclica cu numar cunoscut de pasi.

        Formatul instructiunii:
        Instructiunea for are urmatorul format:

        FOR Variabila=expresie1 TO expresie2 DO
          instructiune(instructiuni;)
        END

          Unde expresie1 este valoarea de start a variabilei iar expresie2 este valoarea de stop a variabilei.

    Aplicatii care utilizeaza instructiunea FOR

        In cadrul proiectului   Sch_el  creat anterior vom realiza diverse pagini grafice in care se vor utiiza instructiuni repetitive.
        Se va realiza o pagina grafica "led4" in care se va utiliza instructiunea for pentru a aprinde secvential 10 LED-uri. asemanatoare cu imaginea de mai jos.



        La apasarea butonului "Start", trebuie sa se aprinda secvential cele 10 LED-uri, iar la comanda "Stop" se vor stinge secvential cele 10 LED-uri.
        Vom scrie deci doua functii: leduri_on() si leduri_off() care vor fi atribuite celor doua butoane prin intermediul facilitatii "Button Properties".

    FUNCTION leduri_on()
        INT i;
    	FOR i=1 TO 10 DO
    		ld[i]=1;
    		Sleep(1);	
    	END
    END
    
    FUNCTION leduri_off()
        INT i;
    	FOR i=1 TO 10 DO
    		ld[i]=0;
    		Sleep(1);	
    	END
    END
    


        Dupa cum se observa, s-a folosit instructiunea for pentru a atribui tag-ului ld[i] valoarea 1 respectiv 0. Dupa fiecare instructiune de atribuire, se invoca functia Sleep(1) care introduce o intarziere de cate o secunda.
        Functia "Sleep" are ca parametru, numarul de secunde de intarziere. Pentru a obtine intarzieri mai mici de o secunda, vom aplica o alta metoda, si anume vom scrie o functie care se apeleaza din pagina principala de fiecare data cand se scaneaza pagina. Timpul dupa care se face o noua scanare poate fi stabilit pe pagina principala :



        Dupa cum se observa, timpul de scanare implicit este de 250 ms dar se poate stabili alt timp prin invalidarea optiunii default.
        Dupa setarea corespunzatoae a intervalului de timp dintre doua scanari, plasam functia f(x) pe pagina principala "led5" .



        Cu click dreapta pe f(x), completam Citect Object Properties->Command cu: ecran_0( ). Cu alte cuvinte de fiecare data cand se scaneaza pagina grafica, se lanseaza functia ecran_0( ) cu urmatorul continut:

    FUNCTION ecran_0()
      IF (ld_on=1) THEN
        ld_off=0;
    	ld[i]=1;
    	i=i+1;
    	IF (i=11) THEN
    	   ld_on=0;
    	   i=0;
    	END
      END
      IF (ld_off=1) THEN
        ld_on=0;
    	ld[i]=0;
    	i=i+1;
    	IF (i=11) THEN
    	   ld_off=0;
    	   i=0;
    	END
      END
    END
    


        Pe evenimentele click ale butoanelor "ON" respectiv "OFF" nu se mai lanseaza functiile leduri_on() respectiv leduri_off(). Sunt introduse insa doua variabile tag locale astfel: tag-urile corespunzatoare adica:

    Tag-uri aferente
    Nume Tip Domeniu Um Comentariu
    ld_on DIGITAL - - Comanda LED-uri on
    ld_off DIGITAL - - Comanda LED-uri off


        La apasarea butonului "On" se va seta variabila ld_on



        La apasarea butonului Off se va seta variabila ld_of



        Functie de variabilele de sus, la fiecare scanare a paginii, LED-urile se vor aprinde secvnential, respectiv se vor aprinde secvential. Desi este o operatie repetitiva, aceasta nu s-a mai implementat folosind instructiunea repetitiva for, repetitivitatea s-a realizat prin intermediul scanarii implicite a paginii la intervalul stabilit anterior.
        Sa presupunem acum ca dorim activarea LED-urilor intr-o anumita ordine. Pentru acest lucru vom devini un vector de prioritati de genul:

        INT Prior[11]=0,1,5,7,4,2,9,3,6,8,10;

        Dupa cum se vede, s-au definit 11 elemente nu 10, pe motiv ca numerotarea LED-urilor incepe de la 1 nu de la 0.
        Conform modului de initializare al valorilor elementelor vectoruljui "Prior", ordinea de activare al LED-urilor este: 1,5,7,4,2,9,3,6,8,10
        In urmatoarea aplicatie "led6" , vom rescrie deci fuctiile: leduri_on() si leduri_off() ele devenind:

    FUNCTION leduri_on()
        INT i;
    	FOR i=1 TO 10 DO
    	ld[Prior[i]]=1;
    	Sleep(1);	
    	END
    END
    FUNCTION leduri_off()
        INT i;
    	FOR i=1 TO 10 DO
    	ld[Prior[11-i]]=0;
    	Sleep(1);	
    	END
    END
    
    

        Dupa cum se observa, nu se mai activeaza LED-ul i ci LED-ul Prior[i]. Dezactivarea se face in ordine inversa adica: nu se mai dezactiveaza LED-ul i ci LED-ul Prior[11-i].
        In urmatoarea aplicatie "led7" , se opteaza pentru folosirea intervalului de scanare al paginii principale, vom modifica functia: ecran_0( ) astfel:

    FUNCTION ecran_0()
      IF (ld_on=1) THEN
        ld_off=0;
    	i=i+1;
    	
    	IF (i=11) THEN
    	   ld_on=0;
    	   i=0;
    	END
    	ld[Prior[i]]=1;
      END
      IF (ld_off=1) THEN
        ld_on=0;
    	i=i+1;
    	IF (i=11) THEN
    	   ld_off=0;
    	   i=0;
    	END
    	ld[Prior[11-i]]=0;
      END
    END
    


    2.Instructiunea WHILE


        Instructiunea while Se foloseste pentru a executa repetitiv o instructiune sau o secventa de instructiuni atata timp cat o expresie este adevarata.

        Formatul instructiunii:

        Instructiunea while are urmatorul format:

        WHILE (expresie) DO
          instructiune(instructiuni;)
        END


        Instructiunea se executa repetat atîta timp cît valoarea expresiei "expresie" este adevarata.

        Testul are loc înaintea fiecarei executii a instructiunii. Modul de functionare al instructiunii este urmatorul:
  •      Se testeaza expresia din paranteze. Daca ea este adevarata (sau expresia din paranteze are o valoare diferita de zero)
  •      Se executa corpul instructiunii while
  •      Se reia testarea si executia pana expresia devine falsa (sau valoarea expresiei din paranteze este zero)
  •      Se continua executia cu instructiunea de dupa corpul instructiunii while, deci instructiunea while se termina.

    Aplicatii care utilizeaza instructiunea WHILE

        Pornind de la aplicatia in care avem plasate cele 10 LED-uri, sa realizam o noua aplicatie in care pornind de la o anumita secventa de LED-uri utilizand butoanele L1-L10, la apasarea butonului ON sa complementam pe rand starea fiecarul LED pana la apasarea butonului OFF.
        Fuctiile: leduri_on() si leduri_off() lansate de butonul ON respectiv OFF fiind:

    FUNCTION leduri_on()
        INT i=1;
        ld_off=0;
        ld_on=1;
    	WHILE ld_on=1 DO
    		Toggle(ld[i]);
    		Sleep(1);
    		i=i+1;
    	 	IF i=11 THEN
    	 		i=1;
    		END			
    	END
    END
    FUNCTION leduri_off()
        ld_off=1;
        ld_on=0;
    END
    


        Rulam aplicatia si obtinem "led8" :



        Instructiunea FOR poate fi inlocuita cu o instructiune WHILE. O instructiune FOR de forma:

        FOR Variabila=expresie1 TO expresie2 DO
          instructiune(instructiuni;)
        END


        este echivalenta cu:

        Variabila=expresie1;
        WHILE (expresie2) DO
          instructiune(instructiuni;)
          expresie3;
        END


         Unde :
         expresie1 constituie initializarea ciclului si se executa o singura data înaintea ciclului.
         expresie2 specifica testul care controleaza ciclul. El se executa înaintea fiecarei iteratii. Daca conditia din test este adevarata atunci se executa corpul ciclului, dupa care se executa expresie3, care consta de cele mai multe ori în modificarea valorii variabilei de control al ciclului. Se revine apoi la reevaluarea conditiei. Ciclul se termina cînd expresie2 devine falsa.
        Spre exemplu, vom putea rescrie fuctiile: leduri_on() si leduri_off() astfel:

    FUNCTION leduri_on()
        INT i=1;
    	WHILE i<=10 DO
    		ld[Prior[i]]=1;
    		Sleep(1);
    		i=i+1;	
    	END
    END
    FUNCTION leduri_off()
        INT i=1;
    	WHILE i<=10 DO
    		ld[Prior[11-i]]=0;
    		Sleep(1);
    		i=i+1;	
    	END
    END
    
    


    3.Diverse aplicatii in care sunt utilizate instructiunile repetitive


        Urmatoarele aplicatii vor fi de o complexitate mai ridicata, ingloband diverse instructiuni descrise anterior.
        Vom incerca sa implementam diversi algoritmi. Pentru inceput vom realiza o aplicatie in care avem parametrii de valori diferite, si in functie de valoarea acestora vom lua diferite decizii.

    Determinarea valorilor maxime

        Sa presupunem ca avem 10 valori diferite si vrem sa semnalizam cu niste LED-uri valoarea maxima. La fiecare apasare a butonului, se va aprinde LED-ul care are valoarea corespunzatoare cea mai mare dintre valorile LED-urilor neaprinse inca. Valorile vor fi generate aleator, de asemenea vom plasa controale de tip Genie -> controls -> Ramp_UpDown_btn1 "led9" .



        Avem nevoie de urmatoarele tag-uri:
    Tag-uri aferente
    Nume Tip Array Size Um Comentariu
    ld DIGITAL 11 - Ledurille ld[1]...ld[10]
    val_l INT 11 - Valori prag pentru comanda led-urilor


        La apasarea butonului ON se lanseaza functia leduri9_on()

    FUNCTION leduri9_on()
        INT i=1;
        INT j=1;
        INT mx=0;
    	FOR i=1 TO 10 DO
    	 	IF ((val_l[i]>mx) AND (ld[i]=0)) THEN
    	 		mx=val_l[i];
    	 		j=i;
    		END
    	END
    	ld[j]=1;	
    END
    

        La apasarea butonului OFF se lanseaza functia leduri9_off(),

    FUNCTION leduri9_off()
        INT i=1;
        INT j=1;
        INT mx=0;
    	FOR i=1 TO 10 DO
    	 	IF ((val_l[i]>mx) AND (ld[i]=1)) THEN
    	 		mx=val_l[i];
    	 		j=i;
    		 END
    	END
    	ld[j]=0;	
    END
    

        La apasarea butonului INIT se lanseaza functia init_9()

    FUNCTION init_9()
    	INT i=1;
    	FOR i=1 TO 10 DO
    		val_l[i]=Rand(100);
    	END	
    END
    


    Afisare binara

        Pentru a afisa un numar intreg sub forma binara, se utilizeaza metoda impartirilor repetate cu 2. Resturile impartirilor reprezinta valorile bitilor in ordine inversa. Afisarea binara va fi facuta prin intermediul simbolurilor de tip LED. Vom crea deci pagina grafica "led13"



        Numarul intreg i ce urmeaza a fi convertit este generat aleator utilizand functia rand(1024) . Maximul este fixat la 1024 deoarece avem 10 leduri deci numarul maxim este 2 la puterea 10=1024.

        Avem nevoie de urmatoarele tag-uri:
    Tag-uri aferente
    Nume Tip Array Size Um Comentariu
    ld DIGITAL 11 - Ledurille ld[1]...ld[10]
    i INT - - Contor


        Functia care face conversia se intituleaza af_bin( ) si este plasata pe pagina grafica.

    FUNCTION af_bin()
    INT j
    INT nr
    	nr=Rand(1023);
    	i=nr;
    	FOR j=1 TO 10 DO
    		ld[11-j]= nr MOD 2
    		nr=nr/2;
    	END 
    END
    


    Afisare histograma

        Urmatoarea aplicatie "led14" , genereaza 10 valori aleatoare si le afiseaza sub forma de histograma.



        Valorile generate sunt elementele unui vector, la fel si valorile LED-urilor.
        Afisarea sub forma de histograma se face plasand dreptunghiuri la care se seteaza proprietatea Fill->Level.
        Avem nevoie deci de urmatoarele tag-uri:

    Tag-uri aferente
    Nume Tip Array Size Um Comentariu
    ld DIGITAL 11 - Ledurille ld[1]...ld[10]
    val_l INT 11 - Valorile elem. histogramei




        Functia care afiseaza histograma histo( ) este plasata pe pagina grafica.

    FUNCTION histo()
    INT j=1;
    i=i+1;
    IF i>4 THEN
    	i=0;	
    	FOR j=1 TO 10 DO
    		val_l[j]=Rand(100);
    		IF val_l[j]>77 THEN 
    			ld[j]=1;
    		ELSE
    			ld[j]=0;
    		END	
    	END		
    END	
    END
    


        Contorul i permite afisarea mai lenta, aceasta facandu-se din 5 in 5 scanari. LED-urile retin pozitiile in care au fost depasiri peste pragul de 77

    Test de autoevaluare


    Rezumat


    Limbajul de programare Cicode

        Cicode este un limbaj de programare integrat in mediul de dezvoltare CitectSCADA destinat dezvoltarii de aplicatii SCADA, permitand controlul software a elementelor utilizate pentru mimarea si controlul proceselor.
        Limbajul Cicode permite utilizarea structurilor repetitive cum ar fi:     Instructiunea for

        -Se foloseste pentru a executa repetitiv o instructiune sau o secventa de instructiuni.
        -Implementeaza structura ciclica cu numar cunoscut de pasi.
        Formatul instructiunii:       -Expresie1 este valoarea de start a variabilei iar expresie2 este valoarea de stop a variabilei.

        Instructiunea while

        -Se foloseste pentru a executa repetitiv o instructiune sau o secventa de instructiuni atata timp cat o expresie este adevarata.
        Formatul instructiunii:     -Instructiunea se executa repetat atîta timp cît valoarea expresiei "expresie" este adevarata.
        -Testul are loc înaintea fiecarei executii a instructiunii. Modul de functionare al instructiunii este urmatorul:

  • Rezultate asteptate
  • Termeni esentiali


  • Recomandari bibliografice

  • Link-uri utile

    Test de evaluare