Programarea aplicatiilor SCADA
  • Obiective
  • Organizarea sarcinilor de lucru
    1.Limbajul de programare Cicode

        Aplicatiile SCADA simple se pot crea in principiu fara a utiliza notiuni de programare. Aplicatiile mai complexe nu pot fi realizate decat utilizand facilitatile oferite de 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. Este un limbaj structurat similar cu "C" sau Visual Basic.
        Vom dezvolta in continuare proiectul numit   Sch_el , urmand pasii descrisi in cursul anterior anterior pentru a crea un nou proiect, sau se poate utiliza proiectul   Sch_el_start  proiect in care au fost parcursi toti pasii pentru crearea unui nou proiect.
        In proiectul "Sch_el_start" , sunt realizate deja o serie de astfel de simboluri, asa ca vom porni de la acest proiect.
        Dupa ce s-a download-at acest fisier, din Citect Explorer->Restore se incarca acest proiect si i se atribuie numele "Sch_el" .
        Proiectul contine pagina grafica intitulata: "start" afisata mai jos.


        Pentru a crea simboluri noi, se alege optiunea "Past Symbol" dupa care din meniul deschis se alege optiunea "New".
        In cadrul editarii unui nou simbol este activ un Tools Box cu care se poate edita noul simbol sau se alege din meniul orizontal :
    Tools->Bitmap Editor pentru simboluri mai detaliate. Din acelasi meniu, de la View se poate afisa o fereastra Show Zoom pentru detalii.



    Set simbolul on/off

        Vom incerca acum sa creem o pagina grafica "led1" pentru a simula comanda de alimentare cu energie a unui proces. Alimentarea va fi semnalizata in pagina grafica prin aprinderea unui LED. LED-ul va avea doua stari. Starea stins de culore gri si starea aprins, de culoare verde.



         Pentru a putea afisa cele doua stari vom folosi un Simbol-Set de tip LED.


        Pentru a afisa deci LED-ul s-a plasat un Simbol Set in care s-au plasat cele doua simboluri pentru LED stins si LED aprins
        Dupa cum se observa, pentru a controla comportamentul LED-ului, acestuia i s-a atribuit tag-ul DIGITAL numit "led".


        Comanda se face prin apasarea unui butonului cu titlul "Pornit" care seteaza tag-ul "led" la 1 iar oprirea prin apasarea butonului cu titlul "Oprit" care seteaza tag-ul "led" la 0 .

    Functii predefinite

        Vom crea o noua pagina grafica "led2" , in care vom introduce un singur buton care sa poarte titlul "Pornit/Oprit" si care sa insumeze functiilor celor doua butoane din aplicatia anterioara. Alimentarea cu energie se va semnaliza prin aprinderea unui LED. Pentru a realiza functionarea butonului vom folosi functia predefinita toggle( ) completand "Up command" al butonului "Pornit/Oprit" cu Toggle(led) .



        Am putea sa simulam circuite simple in care sa avem comutatoare pornit oprit sub forma unui Set Simbol nu sub forma unui buton. Vom crea deci o noua pagina grafica "circ_01" in care vom simula circuitul de alimentare a unuei rezistente.
        Tag-ul corespunzator comutatoruliui pentru alimentarea rezistentei, va fi un tag DIGITAL pe care il vom numi "k1".

    Tag-uri aferente
    Nume Tip Domeniu Um Comentariu
    k1 DIGITAL - - Comutator k1




        Am utilizat Set simbolul "k_on", "k_off" definita in biblioteca "Global" Caruia i-am setat proprietatea "Imput" cu toggle(k1) astfel:



        Introducand inca un LED in circuit, vom realiza o noua pagina grafica "circ_02" in care avem un nou circuit cu elemente interactive de comanda si afisare.



    Seturile simbol multi-state

        De multe ori, pentru mimarea cat mai fidela a diverselor procese, avem nevoie de simboluri cu mai multe stari. Vom utiliza in continuare un "Symbol Set Multi-state" pentru a afisa un LED cu patru stari distincte reprezentate de culorile gri, verde, galben, rosu.



        Vom realiza o aplicatie "led11" care utilizeaza un "Symbol Set Multi-state". Pentru a realiza cele patru combinatii, avem nevoie de doua variabile booleene pe care le vom controla cu doua butoane.
    Tag-uri aferente
    Nume Tip Domeniu Um Comentariu
    b0 DIGITAL - - Variabila booleana b0
    b1 DIGITAL - - Variabila booleana b1


        Butoanele b0 respectiv b1 schimba starea variabilelor b0 respectiv b1, utilizand functiile toggle(b0) respectiv toggle(b1)

    Seturile simbol array

    Seturile simbol animated

        O alta metoda pentru mimarea diverselor procese, o reprezinta utilizarea simbolurilor animate care reiau in continuu mai multe imagini predifinite, dand iluzia de miscare continua. Vom utiliza in continuare un "Symbol Set Animated" pentru a afisa un un ventil cu si un agitator.



        Butonul b0 declanseaza afisarea secventiala a imaginilor predefinite.



    Tablouri de elemente

        In multe situatii avem de-a face cu mai multe elemente de acelasi tip. Este mult mai convenabil sa definim un tablou de elemente decat sa definim fiecare element in parte. Sa presupunem ca vrem sa afisam starea a 10 LED-urim pe ecran. Am putea defini cate un tag pentru fiecare LED sau sa definim o singuraa variabila tag de tip tablou. Sa realizam o pagina grafica "led10" de forma imaginii de jos in care plasam 10 LED-uri si 10 butoane de la care sa controlam cele 10 LED-uri.



        In cadrul variabilelor locale vom introduce o variabila de forma:


        Pentru fiecare LED vom seta in cadrul facilitatii "Simbol Set Properties" tag-ul ld[i] in care i ia valori de la 1 la 10.
        Pentru fiecare buton vom seta "Button Properties"-> Input cu: toggle(ld[i]);in care, la fel i ia valori de la 1 la 10.

        Vom relua aceasta aplicatie in cursurile urmatoare si vom conecta un sistem Multiio pe USB.




        Vom putea astfel sa comandam efectiv Led-uri cu aplicatia:



        Tablourile pot fi definite si utilizate in diverse alte cazuri. Pentru a utiliza un tablou, acesta trebuie initial definit. Definirea acestora se poate face sub forma de tag-uri sau se pot defini din program.

        Definirea unui tablou:

        Un tablou de elemente se defineste astfel:

        tip nume[dim1,{dim2},{dim2}]{=vaoare};

        Putem defini deci tabluiri de 1,2 sau 3 dimensiuni. Vom defini un tablou de o singura dimensiune, deci un vector, astfel:

        INT Num[10]

        Am definit mai sus un tablou de numere intregi cu numele "Num", avand maxim 10 elemente.

         Se pot atribui implicit valori astfel:

        INT Num[10]=0,1,58,71,134,2,999,3,6,8;

        Pentru a accesa elementul i se utilizaeaza forma Num[i]
        Vom putea realiza alte moduri de implementare a comenzii Pornit/ Oprit, folosind limbajul propriu de programare "Cicode".
        Utilizand limbajul de programare Cicode se pot controla prin program toate variabilele locale si cele in timp real, precum si toate facilitatile oferite de CitectSCADA cum ar fi tag-uri, variabile locale, trends, grfice, rapoarte.
        Cicode se poate utiliza si pentru a interfata aplicatia cu alte resurse cum ar fi porturi de comunicatie, sistemul de operare, baze de date, etc.

    2. Instructiuni decizionale


        Instructiunea if se foloseste pentru a selecta executia unei instructiuni (sau a unui grup de instructiuni) functie de valoarea logica a unei expresii relationale

        Formatul instructiunii:
        Instructiunea if are urmatoarele formate:

        If expresie relationala THEN
          instructiune(instructiuni);
        END


        sau

        If expresie relationala THEN
          instructiune(instructiuni);
        ELSE
          instructiune(instructiuni);
        END


    Aplicatii care utilizarea instructiuni decizionale

        Vom incerca sa utilizam in continuare "Cicode" pentru a controla functionarea buronului Pornit/ Oprit. In primul caz am completat "Up command" cu Toggle(led) . De data aceasta vom inlocui functia Toggle(led) cu urmatorul program :

    IF led =0  THEN
      led = 1;
    ELSE
      led=0;
    END
    


        Liniile de cod de sus, vor fi atribuite: Button Properties->Input.



        Am realizat astfel pagina grafica "led3" in care, folosind instructiunea IF, un singur buton preia functia de Start/Stop.



        Urmatoarea aplicatie "circ_03" analizeaza starea unui circuit electric si afiseaza starea acestuia.



        Pentru realizarea aplicatiei, avem nevoie de urmatoarele tag-uri

    Tag-uri aferente
    Nume Tip Domeniu Um Comentariu
    k1 DIGITAL - - Intrerupator k1
    k2 DIGITAL - - Intrerupator k2
    k3 DIGITAL - - Intrerupator k3
    led DIGITAL - - LED


        La apasarea butoului "Stare circuit" se aprinde LED-ul corespunzator. Primul LED este controlat de expresia led=1 iar LED-ul de jos de expresia led=0. Va trebui deci ca la apasarea butoului "Stare circuit" sa se ruleze un mic program care seteaza in mod corespunzator tag-ul led in functie de starea intrerupatoarelor k1, k2, k3.

    IF k1 AND ( k2  OR k3) THEN
          led=1;
    ELSE
          led=0;
    END
    


        O rezolvare mai eleganta "circ_04" , ar fi obtinuta prin introducerea unui LED in serie cu rezistenta. Controlul acestuia nu va mai fi facut de tag-ul led ci de expresia: k1 AND ( k2 OR k3)



    3. Functii


        Functiile sunt des utilizate pentru realizarea aplicatiilor SCADA. Majoritatea butoanelor, prin intermediul evenimentelor lanseaza secvente de cod impachetate in cadrul unor functii. Exista o varietate mare de functii astfel avem functii cu sau fara parametri, functii care returneaza sau nu valori.

        Formatul pentru definirea unei functii fara parametri si fara returnare de valori:
        Pentru definirea unei astfel de functii se foloseste urmatorul format:

        FUNCTION nume_functie()
          declaratii;
          .
          .
          .
          declaratii;
        END


        Formatul pentru definirea unei functii cu parametri si fara returnare de valori:
        Pentru definirea unei astfel de functii se foloseste urmatorul format:

        FUNCTION nume_functie(Argumente)
          declaratii;
          .
          .
          .
          declaratii;
        END


        Formatul pentru definirea unei functii cu parametri si cu returnare de valori:
        Pentru definirea unei astfel de functii se foloseste urmatorul format:

        Tip valoare returnata FUNCTION nume_functie(Argumente)
          declaratii;
          .
          .
          .
          declaratii;
          RETURN valoare
        END


    Aplicatii care utilizeaza functii definite de utilizator

        In aplicatiile anterioare, am apelat functia Toggle() , functie aflata in biblioteca limbajului Cicode, sau am scris direct in campul "Up command" cateva linii de program care inlocuiesc functia Toggle().
        De data aceasta vom incerca sa scriem o functie proprie pe care sa o invocam la apasarea butonului "Pornit/ Oprit"
        Sa denumim functia "comut_a()" si sa deschidem CicodeEditor pentru a o scrie. CicodeEditor editor se lanseaza din "Citec Explorer"->Cicode Files->Create new Cicode page.
        Vom defini functia "comut_a()" astfel:

    FUNCTION comut_a()
    
    	IF led =0 THEN
    		led = 1;
    	ELSE
    		led=0;
    	END
    END
    
    


         In acest moment, pentru butonul "Start/Stop" - setam proprietatea " Input" -Action up, "Up command" cu comut_a()
        Utilizam deci butonul "Start/Stop" si realizam o noua pagina grafica avand numele "led12" similara cu pagina grafica de jos.



        Pentru LED s-a ales un "Symbol Set" de tip "On/Off" controlat de tag-ul "led"
        Functia comut_a() se lanseaza de evenimentul click al butonului. In general functiile scrise de utilizatori, se lanseaza de diverse evenimente. Avem posibilitatea sa plasam o functie chiar si pe pagina grafica. Vom relua aplicatia "circ_04" si vom realiza aplicatia "circ_05" in care vom plasa o functie care comuta aleator cele trei comutatoare



        Functia plasata am denumit-o "comutare( )". Declansarea acesteia se face la fiecare scanare a paginii. In mod implicit, scanarea se face la 250 ms dar se poate stabili un alt timing.



    FUNCTION comutare()
    	k1=Rand(2);
    	k2=Rand(2);
    	k3=Rand(2);
    END
    


        Dupa cum se observa, s-a folosit functia predefinita Rand(2) functie care intoarce un numar intr 0 si 1.
        Dupa rularea aplicatiei, se observa ca in fiecare secunda se produc 4 comutari. Pentru a mari timpul intre doua comutari, am putea sa umblam la timpul de scanare, dar asta ar inrautati functionarea paginii grafice.
        Vom incerca sa rescriem functia comutare( ) astfel incat sa putem controla timpul intre doua comutari. Vom contoriza scanarile paginii grafice si vom executa atribuirea de valori pentru k1, k2, k3 numai dupa un anumit numar de scanari. Vom introduce un tag, pe care il vom folosi pe post de contor. Avem deci nevoie de tag-urile:

    Tag-uri aferente
    Nume Tip Domeniu Um Comentariu
    k1 DIGITAL - - Intrerupator k1
    k2 DIGITAL - - Intrerupator k2
    k3 DIGITAL - - Intrerupator k3
    i INTEGER - - Contor


        Functia comutare( ) devine:

    FUNCTION comutare()
    	i=i+1;
    	IF i>3 THEN
    		k1=Rand(2);
    		k2=Rand(2);
    		k3=Rand(2);
    		i=0;
    	END	
    
    END
    


        In acest caz comutarea se face numai la interval de 4 scanari deci la interval de 4*250ms=1s

    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:     Definirea unui tablou:

        tip nume[dim1,{dim2},{dim2}]{=vaoare};

        exemplu

        INT Num[10]

        INT Num[10]=0,1,58,71,134,2,999,3,6,8;

        Instructiunea if

        Formatul instructiunii:
        If expresie relationala THEN
          instructiune(instructiuni);
        END


        sau

        If expresie relationala THEN
          instructiune(instructiuni);
        ELSE
          instructiune(instructiuni);
        END


         Functii

        - Formatul pentru definirea unei functii fara parametri si fara returnare de valori
        FUNCTION nume_functie()
          declaratii;
          .
          .
          .
          declaratii;
        END


        - Formatul pentru definirea unei functii cu parametri si fara returnare de valori

        FUNCTION nume_functie(Argumente)
          declaratii;
          .
          .
          .
          declaratii;
        END


        -Formatul pentru definirea unei functii cu parametri si cu returnare de valori
        Tip valoare returnata FUNCTION nume_functie(Argumente)
          declaratii;
          .
          .
          .
          declaratii;
          RETURN valoare
        END


  • Rezultate asteptate
  • Termeni esentiali


  • Recomandari bibliografice

  • Link-uri utile

    Test de evaluare