Návrh a realizácia vývojového prostredia pre jednočipové PLC: Rozdiel medzi revíziami

Z Kiwiki
Skočit na navigaci Skočit na vyhledávání
Riadok 9: Riadok 9:
 
__TOC__
 
__TOC__
 
{{Abstrakt
 
{{Abstrakt
|slovensky
+
|
|anglicky
+
Cieľom tejto diplomovej práce je vytvoriť softvérové vybavenie na prácu s jednočipovým PLC. Aplikácia bola vytvorená v jazyku Python s použitím API knižnice wxWidgets a pozostáva s niekoľkých modulov. Najdôležitejšou časťou aplikácie je prekladač jazyka STL. Výsledkom prekladu je strojový kód mikrokontroléra Atmel AVR.
 +
 
 +
Ďalej aplikácia dokáže zabezpečovať komunikáciu s PLC cez sériový alebo USB port, konfigurovať a používať ovládače IIC zariadení a terminálového modulu.
 +
 
 +
Súčasťou je aj editor a simulátor v jazyku LAD, nastroj na online sledovanie stavu pamäti.
 +
|
 +
The intention of this thesis to realize software tool for work with single-chip PLC. Application was developed in Python programing language. It used API library wxWidgets and it consist of several modules. The most important part of application is STL compiler. The result of STL program compilation is Atmel AVR processor code.
 +
 
 +
Next, application can control serial or USB communication with PLC,it can configure or use IIC and terminal drivers.
 +
 
 +
Part of application is LAD editor, simulator and online memory watching tool.
 
}}
 
}}
  
Riadok 17: Riadok 27:
 
==Lexikálna analýza zdrojového kódu==
 
==Lexikálna analýza zdrojového kódu==
 
==Syntaktická analýza==
 
==Syntaktická analýza==
 +
 +
= Úvod  =
 +
Cieľom práce Návrh a realizácia vývojového prostredia pre jednočipové PLC je vytvoriť užívateľský program na obsluhu, programovanie a debuggovanie jednočipových PLC. Táto práca úzko súvisí s prácou Bc. Mariána Sovu s názvom „Návrh a realizácia jednočipového PLC“, keďže sa tieto práce vzájomne dopĺňajú. Navrhovaný program by mal spĺňať niekoľko základných parametrov. Multiplatformovosť, intuitívne ovládanie, možnosť programovania v jazyku ST, LAD. Ďalej by mal obsahovať nástroj na odhaľovanie chýb, editor ovládačov externých IIC zariadení, nástroj na kontrolu stavu pamäte simuláciu a iné pokročilé možnosti pri projektovaní zariadenia s PLC.
 +
 +
V prvej kapitole sa zaoberám kompilátorom jazyka ST. Rozoberám štruktúru súborov lexikálnej a syntaktickej analýzy a tiež konfiguráciu rôznych typov PLC.
 +
 +
V druhej kapitole rozoberám realizáciu kompilátora IIC datablokov a spôsoby použitia v projekte.
 +
 +
V tretej kapitole sa zaoberám komunikáciou s PLC. Formátom odosielaných dát a tiež základnými pravidlami riadenia komunikácie medzi PLC a počítačom.
 +
 +
V poslednej, štvrtej kapitole opisujem užívateľské prostredie a konkrétne možnosti využitia modulov z predchádzajúcich kapitol.
 +
 +
 +
= 1. Kompilátor jazyka ST  =
 +
Účelom tejto kapitoly je vytvoriť prekladač zdrojového kódu jazyka ST. Prekladač alebo tiež kompilátor, je možné definovať prostredníctvom konečného stavového automatu. Pre jazyk Python je k dispozícii modul <tt>ply.py</tt>. Je to čisto Pytonovská implementácia nástrojov na vytváranie komilátora, LEX a YACC. Tieto moduly slúžia na vytvorenie takéhoto konečného stavového automatu. Súčasne musí výsledný kompilátor umožňovať užívateľskú konfiguráciu. Pre tento účel bol zvolený jednoduchý model konfiguračných súborov XML.
 +
 +
[[Image:|thumb|<center>''Obrázok 1: Kompilačná sekvencia''</center>]]
 +
 +
== 1.1 Lexikálna analýza zdrojového kódu ==
 +
Modul <tt>lex.py</tt> slúži na spracovanie vstupného textu do kolekcie tokenov, vytvorenej prostredníctvom množiny regulárnych výrazov. Zjednodušene, lexikálna analýza tokenizuje vstupný reťazec. <nowiki>Informácie v tejto časti sú čerpané z [9],[10].</nowiki>
 +
 +
Vstupný reťazec
 +
    x = 3 + 42 * (s – t)
 +
 +
Tokenizér rozdelí na individuálne tokeny
 +
 +
    'x','=', '3', '+', '42', '*', '(', 's', '-', 't', ')'
 +
 +
Tokenom sú potom pridelené mená kvôli identifikácii
 +
 +
'ID','EQUALS','NUMBER','PLUS','NUMBER','TIMES',
 +
'LPAREN','ID','MINUS','ID','RPAREN'
 +
 +
Nakoniec je vstup rozdelený do párov pozostávajúcich s typu tokenu a hodnoty.
 +
 +
('ID','x'), ('EQUALS','='), ('NUMBER','3'),
 +
('PLUS','+'), ('NUMBER','42'), ('TIMES','*'),
 +
('LPAREN','('), ('ID','s'), ('MINUS','-'),
 +
('ID','t'), ('RPAREN',')'
 +
 +
=== 1.1.1 Štruktúra zdrojového kódu pre LEX ===
 +
Implementované pravidlá lexikálnej analýzy tvoria samostatný modul ktorý používa knižnica LEX. Výstup tohto modulu, sled tokenov, využíva modul YACC pre syntaktickú analýzu. Syntax zápisu modulu pozostáva z niekoľkých častí.
 +
 +
 +
{| class="prettytable"
 +
|  import ply.lex as lex
 +
<nowiki># Zoznam mien tokenov</nowiki>
 +
tokens = ('ID','ID2',...)
 +
<nowiki># Regulárne výrazy pre jednoduché tokeny</nowiki>
 +
<nowiki># 't_'+Meno_tokenu</nowiki>
 +
t_ID = r'regulárny výraz'
 +
<nowiki># Regulárny výraz so zdrojovým kódom </nowiki>
 +
def t_ID2(t):
 +
        r'regulárny_výraz'
 +
        t.value=10
 +
        …
 +
        return t
 +
<nowiki># Definovanie pravidla pre sledovanie počtu riadkov</nowiki>
 +
def t_newline(t):
 +
        r'\n+'
 +
        t.lexer.lineno+=len(t.value)
 +
<nowiki># Ignorované reťazce</nowiki>
 +
t_ignore=r' \t'
 +
<nowiki># Zachytávanie chýb</nowiki>
 +
def t_error(t):
 +
        <nowiki>print "Illegal character '%s'" % t.value[0]</nowiki>
 +
        t.lexer.skip(1)
 +
<nowiki># Vytvoríme samotný lexer</nowiki>
 +
lex.lex()
 +
 +
|}
 +
<center>''Ukážka 1: Štruktúra zdrojového kódu pre LEX''</center>
 +
 +
 +
Prvou povinnou časťou je importovanie modulu LEX a definovanie listu tokenov. Tento list je takisto povinný a obsahuje všetky možne mená tokenov, ktoré môžu byť vytvorené lexerom. Tento list taktiež využíva modul <tt>yacc.py</tt> na identifikovanie výrazov.
 +
 +
Každý token je špecifikovaný regulárnym výrazom. Každé toto pravidlo je definované pomocou premennej s predponou t_ ktorá identifikuje premennú ako token. Pre jednoduché výrazy, definujeme regulárny výraz ako reťazec ktorý je obsahom premennej. Pre zložitejšie výrazy je token definovaný ako funkcia. Regulárny výraz je zadaný ako dokumentačný reťazec za hlavičkou funkcie. Funkcia vždy preberá jeden argument ktorý je inštancia <tt>LexTokenu.</tt> Tento objekt ma viacero atribútov, t.type typ tokenu (reťazec), t.value je lexovaný výraz, t.lineno je aktuálne číslo riadku, t.lexpos pozícia tokenu relatívne od začiatku vstupného textu, t.type meno tokenu.
 +
 +
Pretože <tt>lex.py</tt> nevie nič o počtu riadkov, je potrebné aktualizovať tieto informácie pomocou špeciálneho pravidla.
 +
 +
Špeciálne pravidlo t_ignore je rezervované modulom lex.py pre ignorované znaky. Najčastejšie sa používa pre „biele miesta“ vo vstupnom prúde.
 +
 +
Nakoniec t_error je funkcia na zachytávanie chýb v lexikálnej analýze. Táto funkcia je volaná zakaždým keď je detekovaný neprípustný reťazec.
 +
 +
=== 1.1.2 Lexikálna analýza jazyka STL ===
 +
Zoznam tokenov, alebo tiež zoznam príkazov jazyka STL, je rozdelený do štyroch skupín, podľa počtu parametrov s ktorými asociovaný príkaz pracuje. Toto delenie je dôležite pre následnú syntaktickú analýzu, kde slúži na odhaľovanie chýb. V spracovávanom texte sú vyhľadávané znaky a symboly definovane ako t_ pravidla. Ak pre daný reťazec nieje definovaný token, je vykonaná záverečná kontrola či sa nenachádza v niektorom zo štyroch zoznamov príkazov alebo nejde o definíciu adresy pamäti. V prípade úspechu je návratovou hodnotou príslušný token, v opačnom prípade navracia token error. Pre jazyk STL sme definovali tieto základné tipy tokenov:
 +
 +
 +
#
 +
{| class="prettytable"
 +
|  t_ignore = ' \t\r'
 +
 +
|}
 +
<center>''Ukážka 2: Definícia tokenu (t_ignore)''</center>'''ignore''' – pomocný token odstraňujúci zo spracovávaného textu znaky bez informačnej hodnoty. Tento token sa ďalej v syntaktickej analýze nepoužíva.
 +
#
 +
{| class="prettytable"
 +
|  t_NUMBER =      r'\d+'
 +
 +
|}
 +
<center>''Ukážka 3: Definícia tokenu (t_NUMBER)''</center>'''NUMBER''' – token definujúci celočíselnú kladnú konštantu.
 +
# '''PLUS''' – token znamienka (+).
 +
 +
 +
{| class="prettytable"
 +
|  t_PLUS =      r'\+'
 +
 +
|}
 +
<center>''Ukážka 4: Definícia tokenu (t_PLUS)''</center>
 +
 +
# '''MINUS''' – token znamienka (-).
 +
#
 +
{| class="prettytable"
 +
|  t_MINUS =      r'-'
 +
 +
|}
 +
<center>''Ukážka 5: Definícia tokenu (t_MINUS)''</center>'''DOT''' – token znamienka (.) .
 +
#
 +
{| class="prettytable"
 +
|  t_DOT =      r'\.'
 +
 +
|}
 +
<center>''Ukážka 6: Definícia tokenu (t_DOT)''</center>
 +
{| class="prettytable"
 +
|  def t_COMMA(t):<br/>      r'\,'<br/>      global mem<br/>      mem = False    <br/>      return t
 +
 +
|}
 +
<center>''Ukážka 7: Definícia tokenu (t_COMMA)''</center>'''COMMA''' – token znamienka (,). Veľmi často sa používa v syntaktickej analýze na identifikovanie príkazov, kde oddeľuje jednotlive parametre.
 +
# '''BIT''' – token reprezentujúci bitovú časť adresy. Hodnota tokenu je číslo predstavujúce adresu bitu.
 +
#
 +
{| class="prettytable"
 +
|  def t_BIT(t):<br/>      <nowiki>r'\.[0-7]'</nowiki><br/>      global mem<br/>      mem = False<br/>      <nowiki>t.value = t.value[1]</nowiki><br/>      return t
 +
 +
|}
 +
<center>''Ukážka 8: Definícia tokenu (t_BIT)''</center>'''FLOAT''' – token reprezentujúci číselnú premennú typu float. Zápis tejto premennej je možný v rôznych tvaroch. Napr. (3.14 1e100 3.14e-10 0e0 -1.14e-3). Tento token sa ďalej v syntaktickej analýze nevyskytuje. Ak sa jedná o číselnú konštantu a nie adresu v pamäti, je hodnota float uložená ako token NUMBER a jeho hodnota je skutočný tvar premennej float. (tzn. bajtová reprezentácia čísla v pamäti)
 +
#
 +
{| class="prettytable"
 +
|  def t_FLOAT(t):<br/>      <nowiki>r'[-+]?[0-9]*\.[0-9]+([eE][-+]?[0-9]+)?'</nowiki><br/>      if mem: <br/>            global mem<br/>            mem = False<br/>
 +
          t.type = 'FULLBIT'<br/>            return t<br/>      global mem<br/>      mem = False <br/>      t.value = exp(expf(float(t.value)))<br/>      t.type = 'NUMBER'<br/>      return t
 +
 +
|}
 +
<center>''Ukážka 9: Definícia tokenu (t_FLOAT)''</center>'''ID''' – token symbolizujúci reťazec ktorý nebol doposiaľ identifikovaný ako token. Jedná sa o pomocný token, ktorý vyhodnocuje či ide o token COMM (command „príkaz“), alebo MEMO (memory „pamäť“).
 +
#
 +
{| class="prettytable"
 +
|  def t_ID(t):<br/>      <nowiki>r'[a-zA-Z=<>][a-zA-Z=<>]*'</nowiki><br/>
 +
    if t.value.upper() in keywords:<br/>          global mem  <br/>          mem = False<br/>          t.type = 'COMM'<br/>          t.value = t.value.upper()<br/>      elif t.value.upper() in memory:<br/>          t.type = 'MEMO'<br/>          global mem<br/>          mem = True<br/>          t.value = t.value.upper()<br/>      elif t.value == '=': <br/>          print mem<br/>          mem = False<br/>          t.type = 'COMM'      <br/>      return t
 +
 +
|}
 +
<center>''Ukážka 10: Definícia tokenu (t_ID)''</center>'''COMM''' – token príkazu ktorého meno je uložené v zozname keywords. Hodnota tokenu predstavuje jeho meno.
 +
# '''MEMO''' – token špecifikujúci oblasť pamäti. Je súčasťou plnej adresy PLC. Jeho možné tvary sú definované v zozname memory.
 +
# '''COMMENT''' – token poznámky alebo komentára. Slúži len pre potrebu programátora pracujúceho v STL kóde alebo pomôcka na identifikáciu vo vývojovom prostredí.
 +
#
 +
{| class="prettytable"
 +
|  def t_COMMENT(t):<br/>      r'\#.*'<br/>      global mem<br/>      mem = False
 +
 +
|}
 +
<center>''Ukážka 11: Definícia tokenu (t_COMMENT)''</center>'''NEWLINE''' – token nového riadku. Používa sa v dvoch prípadoch. Ako identifikátor nového riadku pre počítadlo a tiež ako ukončenie výrazu v syntaktickej analýze.
 +
#
 +
{| class="prettytable"
 +
|  def t_NEWLINE(t):<br/>      r'\n|\r'<br/>      global mem<br/>      mem = False<br/>      if first: <br/>            t.lexer.lineno = 0<br/>            global first<br/>            first=0<br/>      t.lexer.lineno += len(t.value)<br/>      global size<br/>      size+=1<br/>      return t
 +
 +
|}
 +
<center>''Ukážka 12: Definícia tokenu (t_NEWLINE)''</center>
 +
{| class="prettytable"
 +
|  def t_error(t):<br/>
 +
    <nowiki>print "Illegal character '%s' " % (t.value[0])</nowiki><br/>      t.lexer.skip(1)
 +
 +
|}
 +
<center>''Ukážka 13: Definícia tokenu (t_ERROR)''</center>'''ERROR''' – token chybového stavu. Je ním identifikovaný každý výraz ktorý nemá definovaný token. Ak je token ERROR identifikovaný, lexikálna analýza sa ukončí a program vypíše chybové hlásenie.
 +
 +
== 1.2 Syntaktická analýza ==
 +
Nástrojom na syntaktickú analýzu je modul <tt>yacc.py</tt>. Tento modul umožňuje v spolupráci s modulom <tt>lex.py</tt><nowiki> definovať pravidlá, ako má budúci jazyk vyzerať. Tzn. umožňuje vytvárať programátorské konštrukcie a zápisy. YACC využíva parsovacie techniky známe ako LR-parsing alebo shift-reduce parsing. Informácie v tejto časti sú čerpané z [9],[10].</nowiki>
 +
 +
=== 1.2.1 Štruktúra zdrojového kódu pre YACC ===
 +
Zdrojový kód pre YACC tvorí samostatný modul pozostávajúci z niekoľkých častí.
 +
 +
 +
{| class="prettytable"
 +
|      import ply.yacc as yacc
 +
<nowiki># List tokenov</nowiki>
 +
from userlex import tokens
 +
<nowiki># Gramatické pravidlá</nowiki>
 +
def p_expression(p):
 +
    'expression : expression PLUS term'
 +
    <nowiki>p[0] = p[1] + p[3]</nowiki>
 +
 +
def p_expression_term(p):
 +
    'expression : term'
 +
    <nowiki>p[0] = p[1]</nowiki>
 +
 +
def p_term_factor(p):
 +
    'term : factor'
 +
    <nowiki>p[0] = p[1]</nowiki>
 +
 +
def p_factor_id(p):
 +
    'factor : ID'
 +
    <nowiki>p[0] = p[1]</nowiki>
 +
<nowiki># Pravidlo pre chyby</nowiki>
 +
def p_error(p):
 +
    print "Syntax error in input!"
 +
yacc.yacc()
 +
 +
|}
 +
<center>''Ukážka 14: Štruktúra zdrojového kódu pre YACC''</center>
 +
 +
 +
Prvou povinnou časťou je importovanie modulu yacc.py a listu tokenov zo zdrojového súboru, modulu lexikálnej analýzy.
 +
 +
Každé gramatické pravidlo je definované ako Pythonovská funkcia, kde dokumentačný reťazec obsahuje presnú gramatickú štruktúru daného pravidla. Každá funkcia preberá argument p ktorý je sekvencia obsahujúca hodnotu každého gramatického symbolu podľa odpovedajúceho pravidla.
 +
 +
 +
 +
{| class="prettytable"
 +
|  def p_expression_plus(p):
 +
    'expression : expression PLUS term'
 +
    <nowiki># </nowiki>  ^            ^        ^    ^
 +
    <nowiki># </nowiki> <nowiki>p[0] </nowiki>        <nowiki>p[1] </nowiki>    <nowiki>p[2] p[3]</nowiki>
 +
    <nowiki>p[0] = p[1] + p[3]</nowiki>
 +
 +
|}
 +
<center>''Ukážka 15: Definovanie gramatického pravidla''</center>
 +
 +
 +
Pravidlo p_error(p) je definované pre zachytávanie syntaktických chýb. Keď sa vyskytne syntaktická chyba počas analýzy, je ihneď zachytená. Túto chybu je nutné ďalej spracovať kvôli debugging-u.
 +
 +
Na vytvorenie inštancie parseru, je nutné volať funkciu yacc.yacc(). Táto funkcia vytvorí LR parsovacie tabuľky podľa preddefinovanej gramatiky.
 +
 +
 +
=== 1.2.2 Syntaktická analýza jazyka STL  ===
 +
Syntax jazyka STL je definovaná veľmi jednoducho. Celý program pozostáva s príkazov a parametrov príkazu. Syntaktické pravidlo pre program je teda definované, ako kolekcia príkazov a ich parametrov. Výsledkom je list pevne usporiadaných príkazov a parametrov vhodných na spracovanie. Syntaktické pravidlo príkazu je definované odlišne. Počet parametrov ako aj ich typ, je závislý od príkazu. V tomto kroku používame štyri kategórie príkazov zadefinovaných v module lexikálnej analýzy. Podľa zoznamu v ktorom sa príkaz nachádza, sa k príkazu pripoja príslušné parametre. Parameter príkazu definuje číslo alebo adresa. Syntax adresy je dvojakého druhu. Adresa bitová a bajtová.
 +
 +
Modul syntaktickej analýzy <tt>STLParser.py</tt> obsahuje niekoľko gramatických pravidiel ktoré popisujú jazyk STL:
 +
 +
'''Adresy''' – Na opísanie adresy v pamäti PLC je definovaných niekoľko pravidiel, aby parser dokázal identifikovať všetky možné kombinácie a tvary adresného reťazca a tiež slúžia na odhaľovanie chybného tvaru adresy. *
 +
{| class="prettytable"
 +
|  def p_adress_bite(p):<br/>      '''adress : MEMO NUMBER BIT'''<br/>      <nowiki>p[0] = (p[1],int(p[2]),int(p[3]))</nowiki>
 +
 +
|}
 +
<center>''Ukážka 16: Definícia tokenu (<tt>adress : MEMO NUMBER BIT</tt>)''</center>Adresa definovaná identifikátorom pamäti, bajtom a bitim
 +
*
 +
{| class="prettytable"
 +
|  def p_adress_fullbite(p):<br/>      '''adress : MEMO FULLBIT'''<br/>      <nowiki>i = p[2].find('.')</nowiki><br/>      <nowiki>p[0] = (p[1],int(p[2][:i]),int(p[2][i+1:]))</nowiki>
 +
 +
|}
 +
<center>''Ukážka 17: Definícia tokenu (<tt>adress : MEMO FULLBIT</tt>)''</center>Adresa definovaná identifikátorom pamäti a desatinným číslom
 +
*
 +
{| class="prettytable"
 +
|  def p_adress_byte(p):<br/>      '''adressb : MEMO NUMBER'''<br/>      <nowiki>#print p</nowiki><br/>      <nowiki>p[0] = (p[1],int(p[2]),0)</nowiki>
 +
 +
|}
 +
<center>''Ukážka 18: Definícia tokenu (<tt>adressb : MEMO NUMBER</tt>)''</center>Adresa definovaná ako identifikátor pamäti a číslo – bajtová adresa
 +
*
 +
{| class="prettytable"
 +
|  def p_adress_byte_bad(p):<br/>      '''adressb : MEMO error'''<br/>      <nowiki>#print p</nowiki><br/>      <nowiki>p[0]= '<ERROR> WRONG BYTE ADRESS IN LINE %d ' % (p[2].lineno-_LINES)</nowiki>
 +
 +
|}
 +
<center>''Ukážka 19: Definícia tokenu (<tt>adressb : MEMO error</tt>)''</center>Chybne definovaná adresa s chybou v bajtovej časti adresy. Návratová hodnota je chybový reťazec s popisom chyby a jej umiestnením.
 +
* Chybne definovaná adresa s chybou v bitovej časti adresy. Návratová hodnota je chybový reťazec s popisom chyby a jej umiestnením.
 +
 +
 +
{| class="prettytable"
 +
|  def p_adress_bite_bad(p):
 +
    '''adress : MEMO NUMBER error'''
 +
    <nowiki>p[0]= '<ERROR> WRONG BITE OR BYTE ADRESS IN LINE %d ' % (p[3].lineno-_LINES)</nowiki>
 +
 +
|}
 +
<center>''Ukážka 20: Definícia tokenu (<tt>adress : MEMO NUMBER error</tt>)''</center>
 +
 +
'''Príkazy''' – Príkazy STL sú rozdelené do niekoľkých skupín podľa parametrov ktoré daný príkaz vyžaduje, preto aj gramatické pravidlá delíme na tieto skupiny. V každej definícii je urobená kontrola do ktorej skupiny identifikovaný príkaz patrí a skontroluje sa počet parametrov.
 +
 +
*
 +
{| class="prettytable"
 +
|  def p_command(p):<br/>      '''command : COMM'''<br/>      <nowiki>if p[1] in ONE:</nowiki><br/>          <nowiki>p[0]=(p[1],None)</nowiki><br/>      <nowiki>else: p[0] = '<ERROR> WRONG ARGUMENTS COUNT ET " %s " </nowiki> <nowiki>IN LINE %d'% (p[1],p.lineno(1)-_LINES)</nowiki>
 +
 +
|}
 +
<center>''Ukážka 21: Definícia tokenu (<tt>command : COMM</tt>)''</center>Bezparametrový príkaz. Jediný token ktorý tvorý príkaz je samotný token COMM.
 +
*
 +
{| class="prettytable"
 +
|  def p_command_byte(p):<br/>      '''command : COMM adressb'''<br/>      <nowiki>if isinstance(p[2],str):</nowiki><br/>          <nowiki>p[0]=p[2]</nowiki><br/>      <nowiki>elif p[1] in TWO: </nowiki>  <br/>          <nowiki>p[0] = (p[1],p[2])</nowiki><br/>      <nowiki>else: p[0] = '<ERROR> WRONG ARGUMENTS COUNT ET " %s " </nowiki> <nowiki>IN LINE %d'% (p[1],p.lineno(1)-_LINES)</nowiki>
 +
 +
|}
 +
<center>''Ukážka 22: Definícia tokenu (<tt>command : COMM adressb</tt>)''</center>Jednoparametrový príkaz. Token je tvorený s kombinácie príkazu a adresy bajtu alebo bitu.
 +
*
 +
{| class="prettytable"
 +
|  def p_command_bite(p):<br/>      '''command : COMM adress '''<br/>      <nowiki>if isinstance(p[2],str):</nowiki><br/>          <nowiki>p[0]=p[2]</nowiki><br/>      <nowiki>elif p[1] in TWO : </nowiki>  <br/>          <nowiki>p[0] = (p[1],p[2])</nowiki><br/>      <nowiki>else: p[0] = '<ERROR> WRONG ARGUMENTS COUNT ET " %s " </nowiki> <nowiki>IN LINE %d'% (p[1],p.lineno(1)-_LINES)</nowiki>
 +
 +
|}
 +
<center>''Ukážka 23: Definícia tokenu (<tt>command : COMM adress</tt>)''</center>Chybný príkaz s jedným parametrom.
 +
*
 +
{| class="prettytable"
 +
|  def p_command_bite_bad(p):<br/>      '''command : COMM error '''<br/>      <nowiki>#print p[0],p[1],p[2]</nowiki><br/>      <nowiki>p[0] = '<ERROR> BAD ADRESS SYNTAX ET " %s " IN LINE %d ' % (p[1],p[2].lineno-_LINES)</nowiki>
 +
 +
|}
 +
<center>''Ukážka 24: Definícia tokenu (<tt>command : COMM error </tt>)''</center>Dvojparametrový príkaz. Token tvorí identifikátor príkazu, adresa, čiarka a posledný parameter môže byť adresa alebo konštanta.
 +
*
 +
{| class="prettytable"
 +
|  def p_command_byte_value_bad(p):<br/>      '''command : COMM adressb COMMA error'''<br/>
 +
    <nowiki>p[0] = '<ERROR> BAD SYNTAX ET " %s " IN LINE %d ' % (p[1],p[4].lineno-_LINES)</nowiki>
 +
 +
|}
 +
<center>''Ukážka 27: Definícia tokenu ( <tt>command : COMM adressb COMMA error</tt>)''</center>
 +
{| class="prettytable"
 +
|  def p_command_byte_value(p):<br/>      '''command : COMM adressb COMMA NUMBER'''<br/>      <nowiki>#print p[1],THREE</nowiki><br/>      <nowiki>if isinstance(p[2],str):</nowiki><br/>          <nowiki>p[0]=p[2]</nowiki><br/>      <nowiki>elif p[1] in THREE:</nowiki><br/>          <nowiki>p[0] = (p[1],p[2],int(p[4]))</nowiki><br/>      <nowiki>else: p[0] = '<ERROR> WRONG ARGUMENT COUNT IN LINE '+str(p.lineno(1))</nowiki>
 +
 +
|}
 +
<center>''Ukážka 26: Definícia tokenu ( <tt>command : COMM adressb COMMA NUMBER</tt>)''</center>
 +
{| class="prettytable"
 +
|  def p_command_byte_byte(p):<br/>      '''command : COMM adressb COMMA adressb'''<br/>      <nowiki>#print p[1],THREE</nowiki><br/>      <nowiki>if isinstance(p[2],str): </nowiki><br/>          <nowiki>p[0]=p[2]</nowiki><br/>      <nowiki>elif isinstance(p[4],str): </nowiki><br/>          <nowiki>p[0]=p[4] </nowiki><br/>      <nowiki>elif p[1] in THREE:</nowiki><br/>          <nowiki>p[0] = (p[1],p[2],p[4])</nowiki><br/>      <nowiki>else: p[0] = '<ERROR> WRONG ARGUMENT COUNT IN LINE '+str(p.lineno(1))</nowiki>
 +
 +
|}
 +
<center>''Ukážka 25: Definícia tokenu ( <tt>command : COMM adressb COMMA adressb</tt>)''</center>Chybný príkaz s dvoma parametrami. Ak nastane problém v prvom parametri zachytí sa táto chyba ako u jednoparametrového príkazu, preto stačí definovať chybný token pre druhý parameter.
 +
*
 +
{| class="prettytable"
 +
|  def p_command_byte_value_bad_con(p):<br/>      '''command : COMM adressb error'''<br/>
 +
    <nowiki>p[0] = '<ERROR> BAD SYNTAX ET " %s " IN LINE %d ' % (p[1],p[3].lineno-_LINES)</nowiki>
 +
 +
|}
 +
<center>''Ukážka 28: Definícia tokenu ( <tt>command : COMM adressb error</tt>)''</center>Trojparametrový príkaz. Tvorí ho identifikátor príkazu, čiarka, adresa, čiarka, adresa a posledný parameter je konštanta alebo adresa.
 +
*
 +
{| class="prettytable"
 +
|  def p_command_byte_byte_number(p):<br/>      '''command : COMM adressb COMMA adressb COMMA NUMBER'''<br/>      <nowiki>#print p[1],THREE</nowiki><br/>      <nowiki>if isinstance(p[2],str):</nowiki><br/>          <nowiki>p[0]=p[2]</nowiki><br/>      <nowiki>elif isinstance(p[4],str):</nowiki><br/>          <nowiki>p[0]=p[4]</nowiki><br/>      <nowiki>elif p[1] in FOUR:</nowiki><br/>          <nowiki>p[0] = (p[1],p[2],p[4],int(p[6]))</nowiki><br/>      <nowiki>else: p[0] = '<ERROR> WRONG ARGUMENT COUNT IN LINE '+str(p.lineno(1))</nowiki>
 +
 +
|}
 +
<center>''Ukážka 29: Definícia tokenu ( <tt>command : COMM adressb COMMA adressb COMMA NUMBER</tt>)''</center>
 +
{| class="prettytable"
 +
|  def p_command_byte_byte_byte(p):<br/>      '''command : COMM adressb COMMA adressb COMMA adressb'''<br/>      <nowiki>#print p[1],THREE</nowiki><br/>      <nowiki>if isinstance(p[2],str):</nowiki><br/>          <nowiki>p[0]=p[2]</nowiki><br/>      <nowiki>elif isinstance(p[4],str):</nowiki><br/>          <nowiki>p[0]=p[4]</nowiki><br/>      <nowiki>elif isinstance(p[6],str):</nowiki><br/>          <nowiki>p[0]=p[6] </nowiki><br/>      <nowiki>elif p[1] in FOUR:</nowiki><br/>          <nowiki>p[0] = (p[1],p[2],p[4],p[6])</nowiki><br/>      <nowiki>else: p[0] = '<ERROR> WRONG ARGUMENT COUNT IN LINE '+str(p.lineno(1))</nowiki>
 +
 +
|}
 +
<center>''Ukážka 30: Definícia tokenu ( <tt>command : COMM adressb COMMA adressb COMMA adressb</tt>)''</center>Chybný príkaz s tromi parametrami, s chybou v poslednom parametre. Rovnako ako u dvojparametrového definovania chyby aj v tomto prípade zachytí chybu v prvom parametre jednoparametrová chyba a v druhom dvojparametrová chyba.
 +
 +
 +
{| class="prettytable"
 +
|  def p_command_byte_byte_value_bad(p):
 +
    '''command : COMM adressb COMMA adressb COMMA error'''
 +
 +
    <nowiki>p[0] = '<ERROR> BAD SYNTAX ET " %s " IN LINE %d ' % (p[1],p[6].lineno-_LINES)</nowiki>
 +
 +
|}
 +
<center>''Ukážka 31: Definícia tokenu ( <tt>command : COMM adressb COMMA adressb COMMA error</tt>)''</center>
 +
 +
 +
{| class="prettytable"
 +
|  def p_command_byte_byte_value_bad(p):
 +
    '''command : COMM adressb COMMA adressb COMMA error'''
 +
 +
    <nowiki>p[0] = '<ERROR> BAD SYNTAX ET " %s " IN LINE %d ' % (p[1],p[6].lineno-_LINES)</nowiki>
 +
 +
|}
 +
<center>''Ukážka 32: Definícia tokenu ( <tt>command : COMM adressb COMMA adressb COMMA error</tt>)''</center>
 +
 +
'''Výrazy''' – Pod pojmom výraz v STL parsere, rozumieme akýkoľvek príkaz alebo token ukončený enterom.
 +
 +
 +
{| class="prettytable"
 +
|  def p_statement(p):
 +
    '''statement : command NEWLINE
 +
                  | command'''
 +
 +
    <nowiki>if isinstance(p[1],str):</nowiki>
 +
        <nowiki>print p[1]</nowiki>
 +
        <nowiki>p[0] = None</nowiki>
 +
        p.parser.error = 1
 +
    else:
 +
        <nowiki>p[0] = (p[1])</nowiki>
 +
 +
|}
 +
<center>''Ukážka 33: Definícia tokenu ( <tt>statement : command NEWLINE | command</tt>)''</center>
 +
 +
==
 +
{| class="prettytable"
 +
|  def p_statement_bad(p):
 +
    '''statement : error NEWLINE'''
 +
    print "<ERROR> MALFORMED STATEMENT AT LINE:", p[1].lineno-_LINES
 +
    p[0] = None
 +
    p.parser.error = 1
 +
 +
|}
 +
<center>Ukážka 35: Definícia tokenu ( statement : error NEWLINE)</center>
 +
{| class="prettytable"
 +
|  def p_statement_newline(p):
 +
    '''statement : NEWLINE'''
 +
    p[0] = None
 +
 +
|}
 +
<center>Ukážka 34: Definícia tokenu ( statement : NEWLINE)</center> ==
 +
'''Program''' – Program predstavuje kolekciu po sebe idúcich výrazov s ktorých žiaden nieje token error. Ide od výsledok parsovacieho procesu a vstup do záverečného modulu kompilátora.
 +
 +
 +
 +
{| class="prettytable"
 +
|  def p_program(p):
 +
    '''program : program statement
 +
                | statement'''
 +
    p.parser.lineno=0
 +
    <nowiki>if len(p) == 2 and p[1]:</nowiki>
 +
        <nowiki>p[0] = []</nowiki>
 +
        <nowiki>p[0].append(p[1])</nowiki>
 +
    elif len(p) ==3:
 +
        <nowiki>p[0]=p[1]</nowiki>
 +
        <nowiki>if not p[0]: p[0]=[]</nowiki>
 +
        <nowiki>if p[2]:</nowiki>
 +
            <nowiki>p[0].append(p[2])</nowiki>
 +
 +
|}
 +
<center>''Ukážka 36: Definícia tokenu ( <tt>program : program statement | statement</tt>)''</center>
 +
{| class="prettytable"
 +
|  def p_program_error(p):
 +
    '''program : error'''
 +
    <nowiki>p[0] = None</nowiki>
 +
    p.parser.error = 1
 +
 +
|}
 +
<center>''Ukážka 37: Definícia tokenu ( <tt>program : error</tt>)''</center>
 +
 +
== 1.3 Definovanie konfiguračného súboru PLC ==
 +
Kvôli miernej odlišnosti architektúry jednotlivých typov mikrokontrolérov AVR, je nutné definovať pre každý typ mikrokontroléra konfiguračný súbor. Tento súbor obsahuje špecifické informácie o pamäťových oblastiach, podporovaných príkazoch STL a pod..
 +
 +
 +
=== 1.3.1 Štruktúra konfiguračného súboru PLC ===
 +
Konfiguračný súbor PLC je XML súbor s pevne definovanou stromovou štruktúrou. Jednoduchosť textového formátu a prehľadnosť zápisu, umožňuje rýchlo a flexibilne nakonfigurovať nový typ PLC, bez nutnosti prepisovania zdrojových kódov kompilátora.
 +
 +
 +
{| class="prettytable"
 +
|  <nowiki><?xml version="1.0" encoding="UTF-8"?></nowiki>
 +
<nowiki><MCU type="myPLC32" description="Zakladna verzia plc zalozena na ATMega32"></nowiki>
 +
  <nowiki><Adress></nowiki>
 +
  <nowiki><P </nowiki>  count="4"  memory="0000" size="1" />
 +
  <nowiki><PA </nowiki> count="16"  memory="0005" size="16" />
 +
  <nowiki><SP </nowiki> count="10"  memory="0015" size="1" />
 +
  <nowiki><T </nowiki>  count="384" memory="0029" size="16" />
 +
  <nowiki><C </nowiki>  count="384" memory="01A9" size="16" />
 +
  <nowiki><V </nowiki>  count="377" memory="0329" size="1" />
 +
 +
  <nowiki></Adress></nowiki>
 +
 +
  <nowiki><Command list="LD LDN A AN O ON ALD OLD LPR LPS LPP NOT S R PE NE TON TOFF = MOVB ADDB SUBB ==B &lt;&gt;B &lt;B &gt;B &lt;=B &gt;=B INCB DECB"/></nowiki>
 +
  <nowiki><Config></nowiki>
 +
    <nowiki><Datablock size="128"/></nowiki>
 +
    <nowiki><Memory offset="006E"/></nowiki>
 +
    <nowiki><Port list='FF FF BF B0 00 00 00'/></nowiki>
 +
  <nowiki></Config></nowiki>
 +
<nowiki></MCU></nowiki>
 +
 +
|}
 +
<center>''Ukážka 38: Štruktúra konfiguračného súboru PLC''</center>
 +
 +
Prvou časťou súboru je hlavička xml s definovanou verziou xml a kódovaním znakovej sady. Nasleduje koreňová sekcia ''MCU'' s parametrami ''type'' definuje typ PLC a ''description'' so základným popisom PLC. Táto sekcia obsahuje vetvu ''Address'' ktorej podvetvy definuje adresný priestor PLC a vetvu ''Command'' s parametrom ''list'', obsahujúcim príkazy jazyka ST ktoré PLC podporuje. Adresa je definovaná menom podvetvy, počtom bytov ''count'', začiatočnou 16bitovou adresou v pamäti mikrokontroléru ''memory'' a veľkosťou jednej bunky definovaného adresného priestoru v bitoch ''size''. Je dôležité spomenúť, že kompilátor umožňuje prekrývanie pamäťového priestoru, tzn. jedinečne adresované miesto mikrokontroléra môže byť adresované pomocou viacerých adries PLC. Vetva Config definuje špecifické parametre PLC, ako veľkosť dátového bloku odosielaného programu, offset pamäte a porty ktoré obsahuje PLC.
 +
 +
 +
== 1.4 Spolupráca programov LEX a YACC ==
 +
V tejto časti popisujem spoluprácu programových modulov lex.py a yacc.py pri vytvorení prekladača jazyka ST. Výsledný modul STL.py bude kompilovať zdrojový kód v jazyku ST na strojový kód mikrokontroléra Atmel AVR. Princíp činnosti je vysvetlený na obrázku 2.
 +
 +
Princíp spolupráce je možne opísať v niekoľkých bodoch:
 +
 +
# Nakonfigurovaný lexikálny analyzátor STLex.py vyhľadá v zdrojovom kóde tzv. Tokeny (definované kľúčové slová).
 +
# Zadefinujeme syntaktický analyzátor STLparser.py (vyhľadá možné kombinácie tokenov a spracováva chybové stavy).
 +
# Definujeme konfiguračný súbor PLC pre ktoré je program kompilovaný.
 +
# Kompilačnému modulu STL.py načítame konfiguračný súbor a zdrojový kód jazyka ST.
 +
# Skompilovaný program je sekvencia strojových kódov, určených pre zadefinované PLC.
 +
 +
[[Image:|thumb|<center>''Obrázok 2: Princíp tvorby a funkcie prekladača jazyka definovaného pomocou programov LEX a YACC''</center>]]
 +
 +
<nowiki>Spomenuté možnosti a využitie modulu ply.py a teda programov LEX a YACC nevysvetľuje všetky možnosti využitia ktoré tieto programy ponúkajú. Ide o zhrnutie využitých vlastností počas vývoja kompilátora. Podrobnejšie informácie nájdete v literatúre [9] a [10].</nowiki>
 +
 +
 +
== 1.5 Generovanie strojového kódu ==
 +
Vstupom generátora strojového kódu je výstupná sekvencia parseru jazyka ST. Generátor identifikuje prvky sekvencie podľa Id, ktoré je prvým prvkom každého člena sekvencie.
 +
 +
 +
{| class="prettytable"
 +
|  <nowiki>[('LD', ('P', 0, 0)), ('LPS', None), ('LD', ('P', 0, 5)), ('O', ('P', 0, 7)), ('LD', ('P', 2, 1)), ('O', ('P', 1, 3)), ('=', ('P', 6, 0)), ('=', ('P', 1, 1)), ('A', ('P', 1, 0)), ('=', ('P', 3, 0))]</nowiki>
 +
 +
|}
 +
<center>''Ukážka 39: Výstupná sekvencia parseru''</center>
 +
 +
 +
Druhým prvkom je parameter funkcie, ktorá sa zavolá podľa Id. Týmto parametrom býva najčastejšie adresa PLC. Pre generovanie strojového kódu je nezbytné aby tejto adrese odpovedala adresa mikrokontroléru. Hodnota adresy PLC je rôzna, pre rôzne mikrokontroléry na ktorých je PLC postavené. Tieto adresy sú definované v konfiguračnom súbore aktualizovanom pred samotným generovaním.
 +
 +
 +
{| class="prettytable"
 +
|  def cmd_LD(adr):
 +
    """ Prikaz jazyka STL - LD adr"""
 +
    <nowiki>return adr_htoi(['00','91'])+adr_FlipSplit(adr_ADR(adr))+ </nowiki>  <nowiki>[adr[2]]+adr_htoi(['FB','00','27','00','F9','0F','93'])</nowiki>
 +
 +
|}
 +
<center>''Ukážka 40: Definovanie funkcie generátora''</center>
 +
 +
Z ukážky je zrejmé ako je definovaný generátor strojového kódu, konkrétne príkazu LD. Parameter <tt>adr</tt> je adresa bitovej premennej. Návratovou hodnotou je list strojových kódov. Funkcie <tt>adr_htoi</tt> prevedú list čísel v hexadecimálnej sústave na list typu int. Funkcia <tt>adr_ADR</tt> prevádza adresu PLC na adresu mikrokontroléra a funkcia<tt> adr_FlipSplit</tt> rozdelí 16 bitovú adresu na dve 8 bitové a tie medzi sebou zamení.
 +
 +
== 1.6 Prevod programu LAD do STL ==
 +
Program jazyka LAD je dátovo reprezentovaný ako matica zoznamov predstavujúcich jednotlivé LAD symboly.
 +
 +
 +
{| class="prettytable"
 +
|  <nowiki>[ </nowiki>
 +
<nowiki>[False,“LD”,['V',100,1],False],[False,“LD”,['V',200,1],False], .. </nowiki> 
 +
<nowiki>[False,“LD”,['V',101,0],False],[False,“LD”,['V',201,0],False], .. </nowiki> 
 +
..
 +
]
 +
 +
|}
 +
<center>''Ukážka 41: LAD program''</center>Elementom takejto matice je teda zoznam. Jeho obsah je definovaný ako:
 +
 +
# element – Udáva či je objekt vertikálne prepojený s objektom v riadku pod ním
 +
# element – Identifikátor príkazu
 +
# element – Parametre. Ich počet je variabilný a závisí od príkazu.<br/> n. element - Posledný element predstavuje logicky stav v ktorom sa LAD objekt nachádza.  Je dôležitý iba počas simulácie
 +
 +
Pri prevode program prechádza po riadkoch maticu LAD a ukladá do poľa blokov všetkých sériovo usporiadaných objektov. Ak je program prepojený s riadkom pod ním, je celá prepojená skupina uložená ako jeden blok. Tento blok je vnútorne rozdelený na jednotlivé paralelné vetvy.
 +
 +
[[Image:|thumb|''Obrázok 3: Princíp blokového rozdelenia LAD programu'']]Rozdeľovanie na paralelné vetvy sa vykonáva rekurzívne a preto môžu vzniknúť mnohonásobné vnorené štruktúry. Takto rozdelené pole je už možné jednoduchým spôsobom previesť na STL kód, prechádzaním elementov poľa.
 +
 +
= 2. Kompilátor IIC modulov =
 +
V tejto kapitole vysvetlím princíp modulov IIC a spôsob akým sú IIC zariadenia definované a akým spôsobom sa používajú v PLC. Samotné IIC zariadenie je pripojené na zbernici IIC mikrokontroléra s jedinečnou adresou.
 +
 +
 +
== 2.1 Štruktúra IIC datagramu ==
 +
Nato aby sa dali vyžiť možnosti IIC zariadení, je potrebné mať v PLC zadefinované príkazy, ktorými sa zariadenie ovláda. Tieto príkazy sú definované podľa katalógových listov výrobcu. Výsledkom je datagram nasledovnej štruktúry:
 +
 +
 +
{| class="prettytable"
 +
| Skok
 +
| EBL
 +
| EBH
 +
| EBB
 +
| ADR
 +
| SZ
 +
| R/W
 +
| SZ2
 +
| DL
 +
| DH
 +
| ...
 +
| DL
 +
| DH
 +
| Skok
 +
| EBL
 +
| EBH
 +
| ...
 +
 +
|}
 +
Posledný blok je ukončený 0.
 +
 +
 +
{| class="prettytable"
 +
| Symbol
 +
| Popis
 +
 +
|-
 +
| Skok
 +
| Počet bajtov do ďalšieho bloku
 +
 +
|-
 +
| EBL
 +
| Spodný bajt adresy povoľovacieho bytu
 +
 +
|-
 +
| EBH
 +
| Horný bajt adresy povoľovacieho bytu
 +
 +
|-
 +
| EBB
 +
| Maska povoľovacieho bitu
 +
 +
|-
 +
| ADR
 +
| IIC adresa
 +
 +
|-
 +
| SZ
 +
| Počet zapisovacích a čítacích podprogramov
 +
 +
|-
 +
| R/W
 +
| Typ akcie, 0 čítanie, 1 zápis
 +
 +
|-
 +
| SZ2
 +
| Počet bytov dát
 +
 +
|}
 +
Dátový blok predstavuje sled operácií a dát potrebných na vykonanie nejakej udalosti IIC zariadenia.
 +
 +
 +
== 2.2 Kompilácia IIC datagramu ==
 +
Nato aby sa vytvoril nový IIC blok nieje potrebné presne definovať byty datagramu ale stačí nám opísať IIC príkazy symbolicky.
 +
 +
 +
 +
{| class="prettytable"
 +
|  EN_C,W,123,DATA1,DATA2,R,DATA3
 +
 +
|}
 +
<center>Ukážka 42: Symbolické vyjadrenie príkazu IIC</center>
 +
 +
Ako je zrejme z ukážky je popisovanie príkazov IIC veľmi jednoduché. Prvá premenná EN_C je adresa povoľovacieho bitu, nasleduje typ podprogramu a konštanty s premennými.
 +
 +
O spracovanie symbolického zápisu IIC príkazov sa stará modul<tt> IIC.py, </tt>ktorý je súčasťou modulu <tt>Compiler</tt>. Na kompilovanie symbolického zápisu do databloku slúži príkaz compile(data,value,config),kde data tvorí list symbolických výrazov a adries IIC, value je slovník aliasov premenných a config je cesta ku konfiguračnému súboru PLC. Príkaz compile rozseká reťazec symbolického vyjadrenia na jednotlivé časti oddelené čiarkou. Takto pripravený zoznam parsuje na konštanty a adresy, s ktorých vytvára výsledný dátový blok IIC. Tento blok sa zapisuje do PLC súčasne s programom a veľkosťou programu.
 +
 +
= 3. Komunikačný modul =
 +
Účelom tejto kapitoly je vytvoriť komunikačný modul na zabezpečenie výmeny informácií medzi počítačom a PLC. Komunikácia prebieha v dvoch režimoch. Na protokole <tt>RS232</tt> alebo cez <tt>USB (</tt>pomocou prevodníka <tt>RS232-USB)</tt>. Pre jazyk Python je vytvorený veľmi silný nástroj na zabezpečenie sériovej komunikácie, modul <tt>pySerial</tt>. <nowiki>Informácie v tejto časti sú čerpané z [8].</nowiki>
 +
 +
== 3.1 Modul pySerial ==
 +
Jedná sa o Pythonovský modul ktorý v sebe združuje nástroje na prístup k sériovému portu. Výhodou tohto modulu je multiplatformovosť a jednoduchosť. Konkrétny modul beží na operačnom systéme Windows, Linux a každý iný POSIX-ový systém. Taktiež umožňuje prístup k sériovému portu pomocou Jython a IronPython, čo značne rozširuje možnosti použitia daného modulu.
 +
 +
 +
{| class="prettytable"
 +
|  >>> import serial
 +
>>> ser = serial.Serial('/dev/ttyS1', 19200, timeout=1)
 +
>>> ser.isOpen()          <nowiki>#kontrola portu</nowiki>
 +
True
 +
>>> x = ser.read()        <nowiki>#čítanie jedného bytu</nowiki>
 +
>>> ser.write("hello")    <nowiki>#zápis reťazca</nowiki>
 +
>>> s = ser.read(10)      <nowiki>#čítanie 10 bytov (časovo obmedzené)</nowiki>
 +
>>> line = ser.readline() #čítanie riadku ukončeného '\n'
 +
>>> ser.close()
 +
 +
|}
 +
<center>''Ukážka 43: Základné operácie so sériovým portom''</center>
 +
 +
 +
Ako je patrné z ukážky práca so sériovým portom pomocou pySerial je jednoduchá. Po importovaní modulu <tt>seriál</tt> môžeme vytvoriť objekt <tt>seriál</tt> pomocou ktorého budeme odosielať alebo prijímať informácie cez sériový port, resp. USB port. Takisto je možné definovať špecifickejšie parametre sériového portu ako: <tt>baudrate</tt> prenosová rýchlosť, <tt>bytesyze</tt> počet dátových bitov, <tt>parity</tt> paritu, <tt>stopbits</tt> počet stopbitov, <tt>timeout</tt> čakací čas a ďaľšie. Podrobnejšie informácie o module pySerial nájdete v literatúre <nowiki>[8].</nowiki>
 +
 +
 +
== 3.2 Komunikačný protokol PLC ==
 +
Cieľom komunikačného protokolu je presne definovať priebeh komunikácie medzi komunikujúcimi zariadeniami. Protokol definuje základné príkazy na riadenie a identifikačné kódy jednotlivých operácii a samotné telo správy. <nowiki>Informácie v tejto časti sú čerpané z [5].</nowiki>
 +
 +
=== 3.2.1 Identifikácia PLC ===
 +
Identifikuje pripojené PLC. Slúži na presné určenie konfigurácie pre kompilátor.
 +
 +
 +
{| class="prettytable"
 +
| PC
 +
|
 +
| 0x01
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
| ACK
 +
 +
|-
 +
| PLC
 +
|
 +
|
 +
| SIG0
 +
| SIG1
 +
| SIG2
 +
| RAM HIGHT
 +
| RAM LOW
 +
| STATUS
 +
|
 +
 +
|}
 +
 +
{| class="prettytable"
 +
| Symbol
 +
| Popis
 +
 +
|-
 +
| 0x01
 +
| Kód PLC 0x01h
 +
 +
|-
 +
| SIG0
 +
| Signatúra procesora
 +
 +
|-
 +
| SIG1
 +
| Signatúra procesora
 +
 +
|-
 +
| SIG2
 +
| Signatúra procesora
 +
 +
|-
 +
| RAM HIGHT
 +
| Horný byte adresy
 +
 +
|-
 +
| RAM LOW
 +
| Dolný byte adresy
 +
 +
|-
 +
| STATUS
 +
| Status plc
 +
 +
RUN
 +
 +
STOP
 +
 +
PAUSE
 +
 +
|-
 +
| ACK
 +
| Potvrdenie prenosu (0x0F)
 +
 +
|}
 +
=== 3.2.2 Štart PLC ===
 +
Spustí PLC (prepne do režimu RUN) pokiaľ bolo v stave STOP alebo PAUSE.
 +
 +
 +
{| class="prettytable"
 +
| PC
 +
|
 +
| 0x02
 +
|
 +
 +
|-
 +
| PLC
 +
|
 +
|
 +
| ACK
 +
 +
|}
 +
 +
{| class="prettytable"
 +
| Symbol
 +
| Popis
 +
 +
|-
 +
| 0x02
 +
| Kód PLC 0x02h
 +
 +
|-
 +
| ACK
 +
| Potvrdenie prenosu (0x0F)
 +
 +
|}
 +
=== 3.2.3 Stop PLC ===
 +
Zastaví PLC pokiaľ bolo v režime RUN alebo len zmení stav na STOP pokiaľ bolo PLC v režime PAUSE.
 +
 +
 +
{| class="prettytable"
 +
| PC
 +
|
 +
| 0x03
 +
|
 +
 +
|-
 +
| PLC
 +
|
 +
|
 +
| ACK
 +
 +
|}
 +
 +
{| class="prettytable"
 +
| Symbol
 +
| Popis
 +
 +
|-
 +
| 0x03
 +
| Kód PLC 0x03h
 +
 +
|-
 +
| ACK
 +
| Potvrdenie prenosu (0x0F)
 +
 +
|}
 +
=== 3.2.4 Upload PLC ===
 +
Príkaz na nahrávanie programu do PLC. Vstupom je sekvencia strojového kódu generovaná kompilátorom, rozdelená na 64 bytové bloky. Nekompletný blok musí byť doplnený nulami na svoju menovitú veľkosť. Koniec komunikácie musí byť potvrdený dvakrát.
 +
 +
 +
{| class="prettytable"
 +
| PC
 +
|
 +
| 0x04
 +
|
 +
| Prog 0-63
 +
|
 +
| Prog 64-128
 +
|
 +
| ACK
 +
| ACK
 +
 +
|-
 +
| PLC
 +
|
 +
|
 +
| ACK
 +
|
 +
| ACK
 +
|
 +
| ACK
 +
|
 +
|
 +
 +
|}
 +
 +
{| class="prettytable"
 +
| Symbol
 +
| Popis
 +
 +
|-
 +
| 0x04
 +
| Kód PLC 0x04h
 +
 +
|-
 +
| Prog 0-63
 +
| Program PLC 64 Bytov
 +
 +
|-
 +
| Prog 63-128
 +
| Program PLC 64 Bytov
 +
 +
|-
 +
| ACK
 +
| Potvrdenie prenosu (0x0F)
 +
 +
|}
 +
=== 3.2.5 Download PLC ===
 +
Príkaz na načítanie programu z PLC. Výstupom je sekvencia strojového kódu mikrokontroléra AVR. Je rozdelená na 64 bytové bloky. Koniec prenosu je signalizovaný dvojitým potvrdením.
 +
 +
 +
{| class="prettytable"
 +
| PC
 +
|
 +
| 0x05
 +
|
 +
| ACK
 +
|
 +
| ACK
 +
|
 +
|
 +
|
 +
 +
|-
 +
| PLC
 +
|
 +
|
 +
| Prog 0-63
 +
|
 +
| Prog 64-128
 +
|
 +
| ACK
 +
| ACK
 +
|
 +
 +
|}
 +
 +
{| class="prettytable"
 +
| Symbol
 +
| Popis
 +
 +
|-
 +
| 0x05
 +
| Kód PLC 0x05h
 +
 +
|-
 +
| Prog 0-63
 +
| Program PLC 64 Bytov
 +
 +
|-
 +
| Prog 63-128
 +
| Program PLC 64 Bytov
 +
 +
|-
 +
| ACK
 +
| Potvrdenie prenosu (0x0F)
 +
 +
|}
 +
=== 3.2.6 Read PLC ===
 +
Príkaz pre načítanie obsahu pamäťovej bunky PLC, definovanou 16 bitovou adresou.
 +
 +
 +
{| class="prettytable"
 +
| PC
 +
|
 +
| 0x06
 +
| ADR HIGH
 +
| ADR LOW
 +
|
 +
| ACK
 +
|
 +
|
 +
|
 +
 +
|-
 +
| PLC
 +
|
 +
|
 +
|
 +
|
 +
| DATA
 +
|
 +
|
 +
|
 +
|
 +
 +
|}
 +
 +
{| class="prettytable"
 +
| Symbol
 +
| Popis
 +
 +
|-
 +
| 0x06
 +
| Kód PLC 0x06h
 +
 +
|-
 +
| ADR HIGHT
 +
| Horný byte adresy
 +
 +
|-
 +
| ADR LOW
 +
| Dolný byte adresy
 +
 +
|-
 +
| DATA
 +
| Hodnota na adrese 1 byte
 +
 +
|-
 +
| ACK
 +
| Potvrdenie prenosu (0x0F)
 +
 +
|}
 +
=== 3.2.7 Write PLC config ===
 +
Príkaz pre zápis konfiguračného bloku do pamäte PLC. Konfiguračný blok tvorí 14 bytov reprezentujúcich stavy výstupných portov v režime STOP a smer dát pre dané porty.
 +
 +
 +
{| class="prettytable"
 +
| PC
 +
|
 +
| 0x08
 +
| PORT_ST
 +
| PORT_DIR
 +
|
 +
|
 +
|
 +
|
 +
|
 +
 +
|-
 +
| PLC
 +
|
 +
|
 +
|
 +
|
 +
| ACK
 +
|
 +
|
 +
|
 +
|
 +
 +
|}
 +
 +
{| class="prettytable"
 +
| Symbol
 +
| Popis
 +
 +
|-
 +
| 0x08
 +
| Kód PLC 0x08h
 +
 +
|-
 +
| PORT_ST
 +
| 7 bytov reprezentujúcich stav v stave STOP
 +
 +
|-
 +
| PORT_DIR
 +
| 7 bytov reprezentujúcich smer dát. Log. 1 = výstup.
 +
 +
|-
 +
| ACK
 +
| Potvrdenie prenosu (0x0F)
 +
 +
|}
 +
=== 3.2.8 Read PLC config ===
 +
Príkaz pre načítanie konfiguračného bloku s pamäte PLC. Konfiguračný blok tvorí 14 bytov reprezentujúcich stavy výstupných portov v režime STOP a smer dát pre dané porty.
 +
 +
 +
{| class="prettytable"
 +
| PC
 +
|
 +
| 0x09
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
 +
|-
 +
| PLC
 +
|
 +
|
 +
| PORT_ST
 +
| PORT_DIR
 +
|
 +
|
 +
|
 +
|
 +
|
 +
 +
|}
 +
 +
{| class="prettytable"
 +
| Symbol
 +
| Popis
 +
 +
|-
 +
| 0x09
 +
| Kód PLC 0x09h
 +
 +
|-
 +
| PORT_ST
 +
| 7 bytov reprezentujúcich stav v stave STOP
 +
 +
|-
 +
| PORT_DIR
 +
| 7 bytov reprezentujúcich smer dát. Log. 1 = výstup.
 +
 +
|}
 +
== 3.3 Komunikačný modul communication.py ==
 +
Tento modul zabezpečuje spojenie počítača s PLC. Využíva k tomu spomínaný modul pySerial (<tt>serial.py</tt>). Pri návrhu musíme počítať s tým, že modul musí bežať na systéme Windows a tiež Linux. Preto je importovaný štandardný modul <tt>platform</tt> ktorý slúži na identifikáciu OS.
 +
 +
Pred samotnou komunikáciou je nutné vytvoriť inštanciu triedy COM. Po úspešnom vytvorení môžeme inicializovať port <tt>COM.Set_port(Port).</tt> <tt>Port</tt> predstavuje reťazec symbolizujúci adresu portu. Pre systém Windows je to '''COMn''', naproti tomu system Linux používa '''dev/ttySn''' pre porty COM a '''dev/ttyUSBn''' pre porty USB.
 +
 +
Pre ľahšie identifikovanie prístupných portov je navrhnutá funkcia <tt>COM.Scan_port</tt>, navracajúca zoznám prístupných portov. Funkcia skenuje 256 COM adries pre Windows a 256 COM a 256 USB adries pre systém Linux.
 +
 +
Taktiež obsahuje príkazy komunikačného protokolu PLC. A to <tt>COM.Run_plc</tt>, <tt>COM.Stop_plc</tt> a <tt>COM.Pause_plc</tt>. Na nahrávanie programu slúži <tt>COM.Send_plc(data)</tt>, kde <tt>data</tt> predstavujú sekvenciu strojového kódu vytvorenej kompilátorom.
 +
 +
 +
= 4. Užívateľské prostredie =
 +
Cieľom tejto kapitoly je vytvoriť grafické užívateľské prostredie, ktoré bude využívať všetky možnosti predchádzajúcich modulov, (kompilátor, IIC, komunikácia). Pre tento účel som zvolil wxPython. Jedná sa o implementáciu knižnice wxWidgets pre pre jazyk python.
 +
 +
WxWidgets je povodne napísaný v jazyku C++ ako štruktúra zahŕňajúca nástroje na vytváranie GUI a iné nástroje, určené pre rôzne platformy. To znamená všetky verzie operačných systémov Windows, Unix s GTK+, Unix s Motif a MacOS. WxWidgets bol povodne vyvinutý v Artificial Intelligence Applications Institute, na univerzite v Edinburgu. Pôvodne určený pre vnútorné použitie, publikovaný bol v roku 1992.
 +
 +
== 4.1 Štruktúra užívateľského prostredia ==
 +
Užívateľské prostredie v sebe zahŕňa niekoľko modulov. Modul kompilátora STL a IIC, komunikácie, služieb a hlavný Main modul. V blokovej schéme je zreteľne vidieť, že všetky moduly sú prepojené s hlavným modulom. Ten uchováva a poskytuje informácie o projekte ostatným modulom a tiež vykonáva interakcie medzi modulmi.
 +
 +
<center>''Obrázok 4: Štruktúra programu užívateľského prostredia''</center>
 +
 +
== 4.2 Obsluha užívateľského prostredia ==
 +
Po spustení aplikácie vývojového prostredia sa nám ukáže hlavne formulárové okno obr. 4. V hornej časti sa nachádza nástrojová lišta. Obsahuje základné nástroje na prácu s projektom a PLC. Konkrétne, zľava vytvorenie nového projektu, otvorenie projektu, uloženie projektu, načítanie programu s pamäte PLC, nahratie programu do PLC, nahratie konfiguračného bloku, kompilácia zdrojového kódu, mapa pamäte, konfigurácia PLC, vytvorenie IIC datagramu, použitie IIC dtatgramu, spustenie a stop PLC.
 +
 +
Ľavú časť predstavuje okno projektu, kde môžeme vidieť a nastaviť parametre PLC a projektu samotného.
 +
 +
Pravá časť obsahuje editačné okno editora jazyka STL a okno pre výpis informačných správ.
 +
 +
=== [[Image:|thumb|<center>Obrázok 5: Okno užívateľského prostredia</center>]]4.2.1 Nastavenie konfiguračného bloku ===
 +
Konfiguračný blok PLC slúži na definovanie vstupno/výstupných portov a stavu jednotlivých pinov v režime stop.
 +
 +
[[Image:|thumb|<center>''Obrázok 6: Dialógové okno konfiguračného bloku''</center>]]Na dialógovom okne vidíme polia zaškrtávacích políčok reprezentujúcich piny príslušných portov. Podľa zvoleného typu PLC sú aktivované alebo deaktivované tie piny, ktoré PLC neobsahuje. Na pravej strane sa nachádza schéma zvoleného PLC s rozmiestnením portov. Zmeny v konfiguračnom bloku sa v PLC prejavia až po nahratí konfiguračného bloku.
 +
 +
 +
=== 4.2.2 Nastavenie typu PLC ===
 +
Na výber typu PLC slúži dialógové okno. Na ľavej strane sa nachádza list všetkých PLC ktorých konfiguračné súbory sa našli v zložke Config. Na pravej strane sa nachádza textový popis vybraného PLC. Tento popis je načítaný s XML konfiguračného súboru.
 +
 +
[[Image:|thumb|<center>''Obrázok 7: Dialógové okno výberu typu PLC''</center>]]Výber typu PLC je potrebný pre kompilátor STL a IIC, na identifikovanie podporovaných príkazov a rozsahu pamäti. Tiež ho vyžaduje modul komunikácie pre určenie veľkosti dátového bloku.
 +
 +
 +
=== 4.2.3 Nastavenie komunikačného portu PC/PLC ===
 +
Po otvorení okna s nastavením komunikácie stačí vybrať príslušný port so zoznamu a potvrdiť. V prípade neskoršieho pripojenia je funkcia scan ktorá prehľadá všetky prístupné sériové a USB porty na PC.
 +
 +
=== [[Image:|thumb|<center>Obrázok 8: Dialógové okno nastavenia komunikácie</center>]]4.2.4 Vytvorenie IIC ovládača zariadenia ===
 +
Tento formulár slúži na vytváranie konfiguračného súboru ovládačov pre IIC. Vyžaduje mena ovládača, adresy IIC, masky IIC a zoznamom všetkých príkazov IIC zariadenia. Výsledný ovládač je uložený vo formáte ini súboru. V prípade že chceme upravovať stávajúci ovládač použijeme funkciu load a nájdeme príslušný ovládač.
 +
 +
[[Image:|thumb|<center>''Obrázok 9: Dialógové okno vytvárania ovládačov IIC''</center>]]
 +
 +
=== 4.2.5 Použitie IIC ovládača zariadenia ===
 +
Ak chceme použiť IIC zariadenie musíme mať jeho ovládač v zložke Config/IIC. Pri otvorení dialógu sa automaticky vyhľadajú všetky ovládače a zobrazia sa v hornom zozname. Po pridaní ovládača do projektu Add, musíme vyplniť všetky premenné príkazov, ktoré sú definované.
 +
 +
[[Image:|thumb|<center>''Obrázok 10: Dialógové okno použitia ovládačov IIC''</center>]]
 +
 +
=== 4.2.6 Konfigurácia terminálového modulu ===
 +
Terminálový modul predstavuje zariadenie na vizualizácia, signalizáciu a získavanie údajov od užívateľa. Tento modul je štandardné IIC zariadenie v režime slave. Každá akcia ktorú modul vykonáva je závislá na požiadavke nadradeného zariadenia.
 +
 +
Úlohou nástroja na konfiguráciu terminálového modulu je vytvoriť IIC datagram pre konkrétny stav obrazovky, odoslanie premenných a načítanie stavu tlačítok. Taktiež treba generovať ST kód obsahujúci samotný obsah obrazovky a pomocne rutiny.
 +
 +
[[Image:|thumb|<center>''Obrázok 11: Dialógové okno nastavenia terminálového modulu''</center>]]Zoznam na pravej strane okna predstavuje všetky obrazovky ktoré máme pre dané PLC nakonfigurované. Pridávanie novej obrazovky sa vykoná tlačítkom Add a odstránenie tlačítkom Remove. Samotné telo správy sa vpisuje do stredného textového poľa. Zobrazenie premennej zabezpečujú formátovacie značky označené {premenná,adresa,počet znakov(,počet znakov desatinnej časti)}. Typ premennej je definovaný znakom B,W,F. Obrazovka ďalej umožňuje nastavenie signalizačného zvuku a povoľovacieho bitu ktorý zapíše obrazovku z PLC do terminálového modulu. Ak chceme použiť aj tlačidlá na terminále je potrebne v záložke Outputs definovať povoľovací bit a adresu kam sa majú uložiť 2 bajty predstavujúce stav tlačidiel.
 +
 +
Vygenerovaný ST kód je umiestnený na koniec zdrojového kódu a označený špeciálnym výrazom kvôli identifikácii.
 +
 +
 +
{| class="prettytable"
 +
|  <nowiki>#@Term@</nowiki>
 +
<nowiki># Nemazat tato cast kodu je generovana automaticky</nowiki>
 +
<nowiki>#-----Screen------</nowiki>
 +
ld        v100.0
 +
movb      v10,116
 +
movb      v11,101
 +
movb      v12,115
 +
movb      v13,116
 +
movb      v14,32
 +
movb      v15,37
 +
movb      v16,51
 +
movb      v17,100
 +
<nowiki>#--</nowiki><nowiki>-------</nowiki>- beep,var
 +
movb      v18,0
 +
movb      v19,2
 +
movb      v20,255
 +
<nowiki>#------Variable-----</nowiki>
 +
movb        v40,0
 +
movb    v0,0
 +
<nowiki>=</nowiki>        v0.0
 +
ld        sp0.0
 +
r        v0.1
 +
r        v0.2
 +
r        v0.3
 +
ld        sp0.0
 +
<nowiki>==b</nowiki>        v40,0
 +
movb        v1,2
 +
movd        v2, v105
 +
s        v0.3
 +
ld        sp0.0
 +
incb        v40
 +
<nowiki>==b</nowiki>        v40,1
 +
movb        v40,0
 +
 +
|}
 +
<center>''Ukážka 44: Automaticky generovaný kód terminálového modulu''</center>
 +
 +
Výraz <nowiki>#@Term@ </nowiki>je identifikačná značka určená pre ľahké rozpoznávanie generovaného kódu od užívateľského programu. Vygenerovaný kód pre terminálový modul pozostáva z dvoch častí.
 +
 +
V prvej časti sa uložia znaky formátovacieho reťazca a ukončia sa 0. pridá sa adresa premenných ktoré sú použité na obrazovke a dĺžka pípnutia. Dĺžka formátovacieho reťazca je obmedzená na 32 viditeľných znakov, vzhľadom na použitý modul znakového displeja 16x2. Dĺžka zvukovej signalizácie je voliteľná v 5 možnostiach (žiaden zvuk, krátke pípnutie, stredne dlhé pípnutie, dlhé a veľmi dlhé pípanie).
 +
 +
V druhej časti sa nachádza vynulovanie počítadiel a povoľovacích bitov pre odoslanie premenných a rutiny ktoré definujú zdrojovú a cieľovú adresu odoslanej premennej v pamäti terminálového modulu.
 +
 +
=== 4.2.7 Online sledovanie obsahu pamäte PLC ===
 +
Jedným z užitočných diagnostických nástrojov vývojového prostredia je Memorymap alebo tiež nástroj na online sledovanie obsahu pamäte PLC. Hlavný princíp nástroja spočíva v cyklickom načítavaní obsahu pamäte cez sériový port, dekódovaní a vypisovaní dát na obrazovku.
 +
 +
[[Image:|thumb|''Obrázok 12: Okno Memory map - online sledovania obsahu pamäte'']]
 +
 +
=== 4.2.8 Editor LAD ===
 +
Na tvorbu programu pre PLC je primárne určený jazyk STL. Ak užívateľ preferuje tvorbu programov pomocou rebríkových schém (LAD), stačí prepnúť záložku nad textovým editorom STL do režimu LAD. V tomto režime pracuje vývojové prostredie ako LAD editor.
 +
 +
[[Image:|thumb|<center>''Obrázok 13: LAD editor''</center>]]Na tvorbu programu teraz stačí kurzorom myši označiť pozíciu na ploche LAD editora a z panela na ľavej strane vybrať príslušnú schematickú značku. Po vytvorení schémy je program možné skompilovať ako STL kód. Pri tomto procese sa matica LAD schémy prevedie na postupnosť STL príkazov a spojí sa s kódom STL editora. Toto umožňuje spoluprácu nástroja na konfiguráciu terminálového modulu s editorom LAD aj STL. Pretože jazyky STL a LAD sú štrukturálne podobné, nieje potrebné písať zvlášť kompilátor na LAD a STL ale postačí prevodník z LAD do STL.
 +
 +
LAD schéma programu slúži nielen na programovanie ale využíva sa aj pri simulácii. V tomto režime sú schematické značky farebne označené pre jasnú identifikáciu aktuálneho stavu.
 +
 +
[[Image:|thumb|<center>''Obrázok 14: Editor LAD v režime simulácie''</center>]]Simulácia prebieha cyklicky a v každom cykle sa kontrolujú stavy vstupov a stav bitu ktorý značka predstavuje. Vstupom rozumieme stav výstupu predchádzajúcej značky. Zelenou sú potom označené tie značky ktorých vstup a vnútorný stav je logická 1 a červenou všetky ostaté značky. Ručné zmeny stavov sa dajú vykonať v okne Memory map kde prepísaním hodnoty na príslušnej adrese zmeníme aj hodnoty stavov príslušných LAD objektov.
 +
 +
 +
== 4.3 Štruktúra projektového súboru ==
 +
Projektový súbor ktorý užívateľ používa je klasický xml súbor. Na prácu s projektovými súbormi slúži modul <tt>Project.py</tt>. Modul sa stará o načítavanie a ukladanie projektov a serializáciu dátových štruktúr.
 +
 +
 +
{| class="prettytable"
 +
|  <nowiki><project></nowiki>
 +
      <nowiki><head author="" date="" description="" name="Olare" version="1.0" /></nowiki>
 +
      <nowiki><code></nowiki>
 +
          <nowiki><stlcode> ... </stlcode></nowiki>
 +
          <nowiki><ladcode> ... </ladcode></nowiki>
 +
      <nowiki></code></nowiki>
 +
      <nowiki><config config="myPLC32.xml" inputs="0 0 0 0 0 0 0 " programversion="1.0" state="0 0 0 0 0 0 0 " /></nowiki>
 +
      <nowiki><workspace> ... </workspace></nowiki>
 +
      <nowiki><iic>...</iic></nowiki>
 +
      <nowiki><terminal>...</terminal></nowiki>
 +
      <nowiki><terminaliic>...</terminaliic></nowiki>
 +
<nowiki></project></nowiki>
 +
 +
|}
 +
<center>''Ukážka 45: Štruktúra projektového xml súboru''</center>Projekt v hlavičke definuje základné informácie o projekte, ako autor, dátum vytvorenia, popis , názov a verziu projektu. Sekcia code obsahuje textovú podobu STL programu a serializované dáta matice LAD programu. V sekcii config definujeme typ PLC pre ktorý je projekt napísaný a stav konfiguračného bloku. Sekcia workspace obsahuje serializované dáta popisujúce rozloženie okien a panelov v projekte. Iic a terminaliic sú sekcie kde sa nachádzajú serializované IIC datagrami zariadení a terminálového modulu. Sekcia terminal predstavuje dáta pre konfiguráciu terminálového modulu.
 +
 +
 +
= Záver =
 +
Cieľom diplomovej práce bolo vytvoriť softvérové vybavenie pre jedončipové PLC, umožňujúce kompilovať, nahrávať a čítať programy pre toto PLC. Taktiež bolo potrebné umožniť užívateľovi prácu s IIC zariadeniami pomocou rôznych konfiguračných nástrojov.
 +
 +
Cieľ práce sa podarilo splniť. Bol vytvorený kompilátor jazyka STL s kontrolou syntaxe, kompilátor IIC datablokov a tiež modul na prevod schém jazyka LAD do kódu STL. Úspešne bol implementovaný komunikačný protokol a tiež samotná komunikácia cez modul pyserial. Podarilo sa vytvoriť základné užívateľské prostredie s využitím knižnice wxWidgets, pre jednoduchú prácu s uvedenými modulmi a tiež nástroje na diagnostiku a sledovanie PLC v reálnom čase. Do vývojového prostredia bola tiež úspešne implementovaná podpora IIC zariadení a nástroj na jednoduché konfigurovanie terminálového modulu.
 +
 +
Softvérové vybavenie bolo vytvorené ako program jazyka Python s využitím príslušných knižníc uvedených v prílohe. To umožňuje jeho použitie na rôznych operačných systémoch ako Windows, Linux a teoreticky MAC.
 +
 +
Program bol testovaný s verziou jednočipového PLC na báze ATMega 32 a ATMega 8 kde pracoval stabilne bez porúch. Pri testoch sme použili operačné systémy Windows XP a distribúciu Arch Linux. Kompilátor STL, komunikačný modul, IIC zariadenia, terminálová konfigurácia a prevodník LAD-STL pracovali správne.
 +
 +
Možnosti ďalšieho postupu pri zdokonaľovaní a vylepšovaní stávajúceho vývojového prostredia je niekoľko. Veľmi užitočná by bola podpora funkcií a kompozitných blokov v STL a LAD. Pre tento účel by bolo treba definovať nové gramatické pravidlá v syntaktickej analýze kompilátora. Ďalšia vec ktorá by zvýšila úroveň práce je lepšia podpora komunikácie medzi viacerými PLC a možnosť prepojenia celej siete zariadení.
 +
 +
 +
= Použitá literatúra =
 +
# Váňa, V.: Mikrokontroléry ATMEL AVR – Popis procesoru a instrukční soubor. BEN – technická literatúra, Praha, 2003. ISBN 80-7300-083-0
 +
# Harms, D. - Mcdonald, K.: - Začíname programovat v jazyce Python. Computer press, 2008. ISBN 978-80-2512-161-0
 +
# Van Rossum, G.: Python Library Reference, relase 2.5.2. 21. Február, 2008. [http://www.python.org/doc/ http://www.python.org/doc/]
 +
# Smart, J. - Roebling, R. - Zeitlin, V. - Dunn, R.: wxWidgets 2.8.4: A portable C++ and Python GUI toolkit, March, 2007, [http://www.wxpython.org/ http://www.wxpython.org]
 +
# Sova, M.: Návrh a realizácia jednočipového PLC, Diplomová práca, TNUAD v Trenčíne, 2010
 +
# Kloz, V.: Softwárové PLC, Diplomová práce, ČVUT v Prahe, 2003
 +
# A.M. Kuchling. Regular Expression HOWTO, posledná aktualizácia 3. 3. 2007 [http://www.amk.ca/python/howto/regex http://www.amk.ca/python/howto/regex]
 +
# Liechti C.: pySerial – Python Serial Port Extension, 2008, [http://pyserial.sf.net/ http://pyserial.sf.net]
 +
# Bazley M. D.: PLY (Python Lex – Yacc), PLY version 2.5, Máj, 2008, posledná aktualizácia 11. 5. 2008, [http://groups.google.com/group/ply-hack http://groups.google.com/group/ply-hack][http://groups.google.com/group/ply-hack  ]
 +
# Niemann T.: A Compact Guide To Lex&Yacc, ePaper Press
 +
# Siemens AG: Programovatelný automat s7-200 Systémový manuál, Jún, 2004
 +
# Julian Smart, Robert Roebling, Vadim Zeitlin, Robin Dunn, et al: wxWidgets 2.8.4: A portable C++ and Python GUI toolkit, Marec, 2007<br/>
 +
 +
 +
= Príloha A – CD  =
 +
* Aplikácia myPLC_Studio
 +
* Kópia diplomovej práce
 +
* Inštalačné programy
 +
* Ukážkové projekty

Verzia zo dňa a času 18:42, 10. máj 2010

Tnu wiki.png
Trenčianska Univerzita Alexandra Dubčeka v Trenčíne
Fakulta Mechatroniky
Fm wiki.png
Návrh a realizácia vývojového prostredia pre jednočipové PLC

zadanie práce
Diplomový projekt


Autor:
Pedagogický vedúci:

Ing. Viliam Šimovič, PhD.

Študijný odbor: Mechatronika

Akademický rok

2009/2010

Obsah

Abstrakt

Cieľom tejto diplomovej práce je vytvoriť softvérové vybavenie na prácu s jednočipovým PLC. Aplikácia bola vytvorená v jazyku Python s použitím API knižnice wxWidgets a pozostáva s niekoľkých modulov. Najdôležitejšou časťou aplikácie je prekladač jazyka STL. Výsledkom prekladu je strojový kód mikrokontroléra Atmel AVR.

Ďalej aplikácia dokáže zabezpečovať komunikáciu s PLC cez sériový alebo USB port, konfigurovať a používať ovládače IIC zariadení a terminálového modulu.

Súčasťou je aj editor a simulátor v jazyku LAD, nastroj na online sledovanie stavu pamäti.

Abstract

The intention of this thesis to realize software tool for work with single-chip PLC. Application was developed in Python programing language. It used API library wxWidgets and it consist of several modules. The most important part of application is STL compiler. The result of STL program compilation is Atmel AVR processor code.

Next, application can control serial or USB communication with PLC,it can configure or use IIC and terminal drivers.

Part of application is LAD editor, simulator and online memory watching tool.

Úvod

Komplilátor jazyka ST

Lexikálna analýza zdrojového kódu

Syntaktická analýza

Úvod

Cieľom práce Návrh a realizácia vývojového prostredia pre jednočipové PLC je vytvoriť užívateľský program na obsluhu, programovanie a debuggovanie jednočipových PLC. Táto práca úzko súvisí s prácou Bc. Mariána Sovu s názvom „Návrh a realizácia jednočipového PLC“, keďže sa tieto práce vzájomne dopĺňajú. Navrhovaný program by mal spĺňať niekoľko základných parametrov. Multiplatformovosť, intuitívne ovládanie, možnosť programovania v jazyku ST, LAD. Ďalej by mal obsahovať nástroj na odhaľovanie chýb, editor ovládačov externých IIC zariadení, nástroj na kontrolu stavu pamäte simuláciu a iné pokročilé možnosti pri projektovaní zariadenia s PLC.

V prvej kapitole sa zaoberám kompilátorom jazyka ST. Rozoberám štruktúru súborov lexikálnej a syntaktickej analýzy a tiež konfiguráciu rôznych typov PLC.

V druhej kapitole rozoberám realizáciu kompilátora IIC datablokov a spôsoby použitia v projekte.

V tretej kapitole sa zaoberám komunikáciou s PLC. Formátom odosielaných dát a tiež základnými pravidlami riadenia komunikácie medzi PLC a počítačom.

V poslednej, štvrtej kapitole opisujem užívateľské prostredie a konkrétne možnosti využitia modulov z predchádzajúcich kapitol.


1. Kompilátor jazyka ST

Účelom tejto kapitoly je vytvoriť prekladač zdrojového kódu jazyka ST. Prekladač alebo tiež kompilátor, je možné definovať prostredníctvom konečného stavového automatu. Pre jazyk Python je k dispozícii modul ply.py. Je to čisto Pytonovská implementácia nástrojov na vytváranie komilátora, LEX a YACC. Tieto moduly slúžia na vytvorenie takéhoto konečného stavového automatu. Súčasne musí výsledný kompilátor umožňovať užívateľskú konfiguráciu. Pre tento účel bol zvolený jednoduchý model konfiguračných súborov XML.

[[Image:|thumb|

Obrázok 1: Kompilačná sekvencia

]]

1.1 Lexikálna analýza zdrojového kódu

Modul lex.py slúži na spracovanie vstupného textu do kolekcie tokenov, vytvorenej prostredníctvom množiny regulárnych výrazov. Zjednodušene, lexikálna analýza tokenizuje vstupný reťazec. Informácie v tejto časti sú čerpané z [9],[10].

Vstupný reťazec 
    x = 3 + 42 * (s – t)

Tokenizér rozdelí na individuálne tokeny

    'x','=', '3', '+', '42', '*', '(', 's', '-', 't', ')'

Tokenom sú potom pridelené mená kvôli identifikácii

'ID','EQUALS','NUMBER','PLUS','NUMBER','TIMES',
'LPAREN','ID','MINUS','ID','RPAREN'

Nakoniec je vstup rozdelený do párov pozostávajúcich s typu tokenu a hodnoty.

('ID','x'), ('EQUALS','='), ('NUMBER','3'), 
('PLUS','+'), ('NUMBER','42'), ('TIMES','*'),
('LPAREN','('), ('ID','s'), ('MINUS','-'),
('ID','t'), ('RPAREN',')'

1.1.1 Štruktúra zdrojového kódu pre LEX

Implementované pravidlá lexikálnej analýzy tvoria samostatný modul ktorý používa knižnica LEX. Výstup tohto modulu, sled tokenov, využíva modul YACC pre syntaktickú analýzu. Syntax zápisu modulu pozostáva z niekoľkých častí.


import ply.lex as lex
# Zoznam mien tokenov
tokens = ('ID','ID2',...)
# Regulárne výrazy pre jednoduché tokeny
# 't_'+Meno_tokenu
t_ID = r'regulárny výraz' 
# Regulárny výraz so zdrojovým kódom 
def t_ID2(t):
        r'regulárny_výraz'
        t.value=10
        …
        return t
# Definovanie pravidla pre sledovanie počtu riadkov
def t_newline(t):
        r'\n+'
        t.lexer.lineno+=len(t.value)
# Ignorované reťazce
t_ignore=r' \t'
# Zachytávanie chýb
def t_error(t):
        print "Illegal character '%s'" % t.value[0]
        t.lexer.skip(1)
# Vytvoríme samotný lexer
lex.lex()
Ukážka 1: Štruktúra zdrojového kódu pre LEX


Prvou povinnou časťou je importovanie modulu LEX a definovanie listu tokenov. Tento list je takisto povinný a obsahuje všetky možne mená tokenov, ktoré môžu byť vytvorené lexerom. Tento list taktiež využíva modul yacc.py na identifikovanie výrazov.

Každý token je špecifikovaný regulárnym výrazom. Každé toto pravidlo je definované pomocou premennej s predponou t_ ktorá identifikuje premennú ako token. Pre jednoduché výrazy, definujeme regulárny výraz ako reťazec ktorý je obsahom premennej. Pre zložitejšie výrazy je token definovaný ako funkcia. Regulárny výraz je zadaný ako dokumentačný reťazec za hlavičkou funkcie. Funkcia vždy preberá jeden argument ktorý je inštancia LexTokenu. Tento objekt ma viacero atribútov, t.type typ tokenu (reťazec), t.value je lexovaný výraz, t.lineno je aktuálne číslo riadku, t.lexpos pozícia tokenu relatívne od začiatku vstupného textu, t.type meno tokenu.

Pretože lex.py nevie nič o počtu riadkov, je potrebné aktualizovať tieto informácie pomocou špeciálneho pravidla.

Špeciálne pravidlo t_ignore je rezervované modulom lex.py pre ignorované znaky. Najčastejšie sa používa pre „biele miesta“ vo vstupnom prúde.

Nakoniec t_error je funkcia na zachytávanie chýb v lexikálnej analýze. Táto funkcia je volaná zakaždým keď je detekovaný neprípustný reťazec.

1.1.2 Lexikálna analýza jazyka STL

Zoznam tokenov, alebo tiež zoznam príkazov jazyka STL, je rozdelený do štyroch skupín, podľa počtu parametrov s ktorými asociovaný príkaz pracuje. Toto delenie je dôležite pre následnú syntaktickú analýzu, kde slúži na odhaľovanie chýb. V spracovávanom texte sú vyhľadávané znaky a symboly definovane ako t_ pravidla. Ak pre daný reťazec nieje definovaný token, je vykonaná záverečná kontrola či sa nenachádza v niektorom zo štyroch zoznamov príkazov alebo nejde o definíciu adresy pamäti. V prípade úspechu je návratovou hodnotou príslušný token, v opačnom prípade navracia token error. Pre jazyk STL sme definovali tieto základné tipy tokenov:


t_ignore = ' \t\r'
Ukážka 2: Definícia tokenu (t_ignore)

ignore – pomocný token odstraňujúci zo spracovávaného textu znaky bez informačnej hodnoty. Tento token sa ďalej v syntaktickej analýze nepoužíva.

t_NUMBER = r'\d+'
Ukážka 3: Definícia tokenu (t_NUMBER)

NUMBER – token definujúci celočíselnú kladnú konštantu.

  1. PLUS – token znamienka (+).


t_PLUS = r'\+'
Ukážka 4: Definícia tokenu (t_PLUS)
  1. MINUS – token znamienka (-).
t_MINUS = r'-'
Ukážka 5: Definícia tokenu (t_MINUS)

DOT – token znamienka (.) .

t_DOT = r'\.'
Ukážka 6: Definícia tokenu (t_DOT)
def t_COMMA(t):
r'\,'
global mem
mem = False
return t
Ukážka 7: Definícia tokenu (t_COMMA)

COMMA – token znamienka (,). Veľmi často sa používa v syntaktickej analýze na identifikovanie príkazov, kde oddeľuje jednotlive parametre.

  1. BIT – token reprezentujúci bitovú časť adresy. Hodnota tokenu je číslo predstavujúce adresu bitu.
def t_BIT(t):
r'\.[0-7]'
global mem
mem = False
t.value = t.value[1]
return t
Ukážka 8: Definícia tokenu (t_BIT)

FLOAT – token reprezentujúci číselnú premennú typu float. Zápis tejto premennej je možný v rôznych tvaroch. Napr. (3.14 1e100 3.14e-10 0e0 -1.14e-3). Tento token sa ďalej v syntaktickej analýze nevyskytuje. Ak sa jedná o číselnú konštantu a nie adresu v pamäti, je hodnota float uložená ako token NUMBER a jeho hodnota je skutočný tvar premennej float. (tzn. bajtová reprezentácia čísla v pamäti)

def t_FLOAT(t):
r'[-+]?[0-9]*\.[0-9]+([eE][-+]?[0-9]+)?'
if mem:
global mem
mem = False
          t.type = 'FULLBIT'
return t
global mem
mem = False
t.value = exp(expf(float(t.value)))
t.type = 'NUMBER'
return t
Ukážka 9: Definícia tokenu (t_FLOAT)

ID – token symbolizujúci reťazec ktorý nebol doposiaľ identifikovaný ako token. Jedná sa o pomocný token, ktorý vyhodnocuje či ide o token COMM (command „príkaz“), alebo MEMO (memory „pamäť“).

def t_ID(t):
r'[a-zA-Z=<>][a-zA-Z=<>]*'
    if t.value.upper() in keywords:
global mem
mem = False
t.type = 'COMM'
t.value = t.value.upper()
elif t.value.upper() in memory:
t.type = 'MEMO'
global mem
mem = True
t.value = t.value.upper()
elif t.value == '=':
print mem
mem = False
t.type = 'COMM'
return t
Ukážka 10: Definícia tokenu (t_ID)

COMM – token príkazu ktorého meno je uložené v zozname keywords. Hodnota tokenu predstavuje jeho meno.

  1. MEMO – token špecifikujúci oblasť pamäti. Je súčasťou plnej adresy PLC. Jeho možné tvary sú definované v zozname memory.
  2. COMMENT – token poznámky alebo komentára. Slúži len pre potrebu programátora pracujúceho v STL kóde alebo pomôcka na identifikáciu vo vývojovom prostredí.
def t_COMMENT(t):
r'\#.*'
global mem
mem = False
Ukážka 11: Definícia tokenu (t_COMMENT)

NEWLINE – token nového riadku. Používa sa v dvoch prípadoch. Ako identifikátor nového riadku pre počítadlo a tiež ako ukončenie výrazu v syntaktickej analýze.

\r'
global mem
mem = False
if first:
t.lexer.lineno = 0
global first
first=0
t.lexer.lineno += len(t.value)
global size
size+=1
return t
Ukážka 12: Definícia tokenu (t_NEWLINE)
def t_error(t):
    print "Illegal character '%s' " % (t.value[0])
t.lexer.skip(1)
Ukážka 13: Definícia tokenu (t_ERROR)

ERROR – token chybového stavu. Je ním identifikovaný každý výraz ktorý nemá definovaný token. Ak je token ERROR identifikovaný, lexikálna analýza sa ukončí a program vypíše chybové hlásenie.

1.2 Syntaktická analýza

Nástrojom na syntaktickú analýzu je modul yacc.py. Tento modul umožňuje v spolupráci s modulom lex.py definovať pravidlá, ako má budúci jazyk vyzerať. Tzn. umožňuje vytvárať programátorské konštrukcie a zápisy. YACC využíva parsovacie techniky známe ako LR-parsing alebo shift-reduce parsing. Informácie v tejto časti sú čerpané z [9],[10].

1.2.1 Štruktúra zdrojového kódu pre YACC

Zdrojový kód pre YACC tvorí samostatný modul pozostávajúci z niekoľkých častí.


import ply.yacc as yacc
# List tokenov
from userlex import tokens
# Gramatické pravidlá
def p_expression(p):
    'expression : expression PLUS term'
    p[0] = p[1] + p[3]
def p_expression_term(p):
    'expression : term'
    p[0] = p[1]
def p_term_factor(p):
    'term : factor'
    p[0] = p[1]
def p_factor_id(p):
    'factor : ID'
    p[0] = p[1]
# Pravidlo pre chyby
def p_error(p):
    print "Syntax error in input!"
yacc.yacc()
Ukážka 14: Štruktúra zdrojového kódu pre YACC


Prvou povinnou časťou je importovanie modulu yacc.py a listu tokenov zo zdrojového súboru, modulu lexikálnej analýzy. 

Každé gramatické pravidlo je definované ako Pythonovská funkcia, kde dokumentačný reťazec obsahuje presnú gramatickú štruktúru daného pravidla. Každá funkcia preberá argument p ktorý je sekvencia obsahujúca hodnotu každého gramatického symbolu podľa odpovedajúceho pravidla.


def p_expression_plus(p):
    'expression : expression PLUS term'
    #   ^            ^        ^    ^
    #  p[0]         p[1]     p[2] p[3]
    p[0] = p[1] + p[3]
Ukážka 15: Definovanie gramatického pravidla


Pravidlo p_error(p) je definované pre zachytávanie syntaktických chýb. Keď sa vyskytne syntaktická chyba počas analýzy, je ihneď zachytená. Túto chybu je nutné ďalej spracovať kvôli debugging-u.

Na vytvorenie inštancie parseru, je nutné volať funkciu yacc.yacc(). Táto funkcia vytvorí LR parsovacie tabuľky podľa preddefinovanej gramatiky.


1.2.2 Syntaktická analýza jazyka STL

Syntax jazyka STL je definovaná veľmi jednoducho. Celý program pozostáva s príkazov a parametrov príkazu. Syntaktické pravidlo pre program je teda definované, ako kolekcia príkazov a ich parametrov. Výsledkom je list pevne usporiadaných príkazov a parametrov vhodných na spracovanie. Syntaktické pravidlo príkazu je definované odlišne. Počet parametrov ako aj ich typ, je závislý od príkazu. V tomto kroku používame štyri kategórie príkazov zadefinovaných v module lexikálnej analýzy. Podľa zoznamu v ktorom sa príkaz nachádza, sa k príkazu pripoja príslušné parametre. Parameter príkazu definuje číslo alebo adresa. Syntax adresy je dvojakého druhu. Adresa bitová a bajtová.

Modul syntaktickej analýzy STLParser.py obsahuje niekoľko gramatických pravidiel ktoré popisujú jazyk STL:

Adresy – Na opísanie adresy v pamäti PLC je definovaných niekoľko pravidiel, aby parser dokázal identifikovať všetky možné kombinácie a tvary adresného reťazca a tiež slúžia na odhaľovanie chybného tvaru adresy. *

def p_adress_bite(p):
adress : MEMO NUMBER BIT
p[0] = (p[1],int(p[2]),int(p[3]))
Ukážka 16: Definícia tokenu (adress : MEMO NUMBER BIT)

Adresa definovaná identifikátorom pamäti, bajtom a bitim

def p_adress_fullbite(p):
adress : MEMO FULLBIT
i = p[2].find('.')
p[0] = (p[1],int(p[2][:i]),int(p[2][i+1:]))
Ukážka 17: Definícia tokenu (adress : MEMO FULLBIT)

Adresa definovaná identifikátorom pamäti a desatinným číslom

def p_adress_byte(p):
adressb : MEMO NUMBER
#print p
p[0] = (p[1],int(p[2]),0)
Ukážka 18: Definícia tokenu (adressb : MEMO NUMBER)

Adresa definovaná ako identifikátor pamäti a číslo – bajtová adresa

def p_adress_byte_bad(p):
adressb : MEMO error
#print p
p[0]= '<ERROR> WRONG BYTE ADRESS IN LINE %d ' % (p[2].lineno-_LINES)
Ukážka 19: Definícia tokenu (adressb : MEMO error)

Chybne definovaná adresa s chybou v bajtovej časti adresy. Návratová hodnota je chybový reťazec s popisom chyby a jej umiestnením.

  • Chybne definovaná adresa s chybou v bitovej časti adresy. Návratová hodnota je chybový reťazec s popisom chyby a jej umiestnením.


def p_adress_bite_bad(p):
    adress : MEMO NUMBER error
    p[0]= '<ERROR> WRONG BITE OR BYTE ADRESS IN LINE %d ' % (p[3].lineno-_LINES)
Ukážka 20: Definícia tokenu (adress : MEMO NUMBER error)

Príkazy – Príkazy STL sú rozdelené do niekoľkých skupín podľa parametrov ktoré daný príkaz vyžaduje, preto aj gramatické pravidlá delíme na tieto skupiny. V každej definícii je urobená kontrola do ktorej skupiny identifikovaný príkaz patrí a skontroluje sa počet parametrov.

def p_command(p):
command : COMM
if p[1] in ONE:
p[0]=(p[1],None)
else: p[0] = '<ERROR> WRONG ARGUMENTS COUNT ET " %s " IN LINE %d'% (p[1],p.lineno(1)-_LINES)
Ukážka 21: Definícia tokenu (command : COMM)

Bezparametrový príkaz. Jediný token ktorý tvorý príkaz je samotný token COMM.

def p_command_byte(p):
command : COMM adressb
if isinstance(p[2],str):
p[0]=p[2]
elif p[1] in TWO:
p[0] = (p[1],p[2])
else: p[0] = '<ERROR> WRONG ARGUMENTS COUNT ET " %s " IN LINE %d'% (p[1],p.lineno(1)-_LINES)
Ukážka 22: Definícia tokenu (command : COMM adressb)

Jednoparametrový príkaz. Token je tvorený s kombinácie príkazu a adresy bajtu alebo bitu.

def p_command_bite(p):
command : COMM adress
if isinstance(p[2],str):
p[0]=p[2]
elif p[1] in TWO :
p[0] = (p[1],p[2])
else: p[0] = '<ERROR> WRONG ARGUMENTS COUNT ET " %s " IN LINE %d'% (p[1],p.lineno(1)-_LINES)
Ukážka 23: Definícia tokenu (command : COMM adress)

Chybný príkaz s jedným parametrom.

def p_command_bite_bad(p):
command : COMM error
#print p[0],p[1],p[2]
p[0] = '<ERROR> BAD ADRESS SYNTAX ET " %s " IN LINE %d ' % (p[1],p[2].lineno-_LINES)
Ukážka 24: Definícia tokenu (command : COMM error )

Dvojparametrový príkaz. Token tvorí identifikátor príkazu, adresa, čiarka a posledný parameter môže byť adresa alebo konštanta.

def p_command_byte_value_bad(p):
command : COMM adressb COMMA error
    p[0] = '<ERROR> BAD SYNTAX ET " %s " IN LINE %d ' % (p[1],p[4].lineno-_LINES)
Ukážka 27: Definícia tokenu ( command : COMM adressb COMMA error)
def p_command_byte_value(p):
command : COMM adressb COMMA NUMBER
#print p[1],THREE
if isinstance(p[2],str):
p[0]=p[2]
elif p[1] in THREE:
p[0] = (p[1],p[2],int(p[4]))
else: p[0] = '<ERROR> WRONG ARGUMENT COUNT IN LINE '+str(p.lineno(1))
Ukážka 26: Definícia tokenu ( command : COMM adressb COMMA NUMBER)
def p_command_byte_byte(p):
command : COMM adressb COMMA adressb
#print p[1],THREE
if isinstance(p[2],str):
p[0]=p[2]
elif isinstance(p[4],str):
p[0]=p[4]
elif p[1] in THREE:
p[0] = (p[1],p[2],p[4])
else: p[0] = '<ERROR> WRONG ARGUMENT COUNT IN LINE '+str(p.lineno(1))
Ukážka 25: Definícia tokenu ( command : COMM adressb COMMA adressb)

Chybný príkaz s dvoma parametrami. Ak nastane problém v prvom parametri zachytí sa táto chyba ako u jednoparametrového príkazu, preto stačí definovať chybný token pre druhý parameter.

def p_command_byte_value_bad_con(p):
command : COMM adressb error
    p[0] = '<ERROR> BAD SYNTAX ET " %s " IN LINE %d ' % (p[1],p[3].lineno-_LINES)
Ukážka 28: Definícia tokenu ( command : COMM adressb error)

Trojparametrový príkaz. Tvorí ho identifikátor príkazu, čiarka, adresa, čiarka, adresa a posledný parameter je konštanta alebo adresa.

def p_command_byte_byte_number(p):
command : COMM adressb COMMA adressb COMMA NUMBER
#print p[1],THREE
if isinstance(p[2],str):
p[0]=p[2]
elif isinstance(p[4],str):
p[0]=p[4]
elif p[1] in FOUR:
p[0] = (p[1],p[2],p[4],int(p[6]))
else: p[0] = '<ERROR> WRONG ARGUMENT COUNT IN LINE '+str(p.lineno(1))
Ukážka 29: Definícia tokenu ( command : COMM adressb COMMA adressb COMMA NUMBER)
def p_command_byte_byte_byte(p):
command : COMM adressb COMMA adressb COMMA adressb
#print p[1],THREE
if isinstance(p[2],str):
p[0]=p[2]
elif isinstance(p[4],str):
p[0]=p[4]
elif isinstance(p[6],str):
p[0]=p[6]
elif p[1] in FOUR:
p[0] = (p[1],p[2],p[4],p[6])
else: p[0] = '<ERROR> WRONG ARGUMENT COUNT IN LINE '+str(p.lineno(1))
Ukážka 30: Definícia tokenu ( command : COMM adressb COMMA adressb COMMA adressb)

Chybný príkaz s tromi parametrami, s chybou v poslednom parametre. Rovnako ako u dvojparametrového definovania chyby aj v tomto prípade zachytí chybu v prvom parametre jednoparametrová chyba a v druhom dvojparametrová chyba.


def p_command_byte_byte_value_bad(p):
    command : COMM adressb COMMA adressb COMMA error
    p[0] = '<ERROR> BAD SYNTAX ET " %s " IN LINE %d ' % (p[1],p[6].lineno-_LINES)
Ukážka 31: Definícia tokenu ( command : COMM adressb COMMA adressb COMMA error)


def p_command_byte_byte_value_bad(p):
    command : COMM adressb COMMA adressb COMMA error
    p[0] = '<ERROR> BAD SYNTAX ET " %s " IN LINE %d ' % (p[1],p[6].lineno-_LINES)
Ukážka 32: Definícia tokenu ( command : COMM adressb COMMA adressb COMMA error)

Výrazy – Pod pojmom výraz v STL parsere, rozumieme akýkoľvek príkaz alebo token ukončený enterom.


def p_statement(p):
    statement : command NEWLINE
command
    if isinstance(p[1],str):
        print p[1]
        p[0] = None
        p.parser.error = 1
    else:
        p[0] = (p[1])
Ukážka 33: Definícia tokenu ( statement : command NEWLINE | command)

==

def p_statement_bad(p):
    statement : error NEWLINE
    print "<ERROR> MALFORMED STATEMENT AT LINE:", p[1].lineno-_LINES
    p[0] = None
    p.parser.error = 1
Ukážka 35: Definícia tokenu ( statement : error NEWLINE)
def p_statement_newline(p):
    statement : NEWLINE
    p[0] = None
Ukážka 34: Definícia tokenu ( statement : NEWLINE)

==

Program – Program predstavuje kolekciu po sebe idúcich výrazov s ktorých žiaden nieje token error. Ide od výsledok parsovacieho procesu a vstup do záverečného modulu kompilátora.


def p_program(p):
    program : program statement
statement
    p.parser.lineno=0
    if len(p) == 2 and p[1]:
       p[0] = []
       p[0].append(p[1])
    elif len(p) ==3:
        p[0]=p[1]
        if not p[0]: p[0]=[]
        if p[2]:
            p[0].append(p[2])
Ukážka 36: Definícia tokenu ( program : program statement | statement)
def p_program_error(p):
    program : error
    p[0] = None
    p.parser.error = 1
Ukážka 37: Definícia tokenu ( program : error)

1.3 Definovanie konfiguračného súboru PLC

Kvôli miernej odlišnosti architektúry jednotlivých typov mikrokontrolérov AVR, je nutné definovať pre každý typ mikrokontroléra konfiguračný súbor. Tento súbor obsahuje špecifické informácie o pamäťových oblastiach, podporovaných príkazoch STL a pod..


1.3.1 Štruktúra konfiguračného súboru PLC

Konfiguračný súbor PLC je XML súbor s pevne definovanou stromovou štruktúrou. Jednoduchosť textového formátu a prehľadnosť zápisu, umožňuje rýchlo a flexibilne nakonfigurovať nový typ PLC, bez nutnosti prepisovania zdrojových kódov kompilátora.


<?xml version="1.0" encoding="UTF-8"?>
<MCU type="myPLC32" description="Zakladna verzia plc zalozena na ATMega32">
 <Adress>
  <P   count="4"   memory="0000" size="1" />
  <PA  count="16"  memory="0005" size="16" />
  <SP  count="10"  memory="0015" size="1" />
  <T   count="384" memory="0029" size="16" />
  <C   count="384" memory="01A9" size="16" />
  <V   count="377" memory="0329" size="1" />
 </Adress>
 <Command list="LD LDN A AN O ON ALD OLD LPR LPS LPP NOT S R PE NE TON TOFF = MOVB ADDB SUBB ==B <>B <B >B <=B >=B INCB DECB"/>
 <Config>
    <Datablock size="128"/>
    <Memory offset="006E"/>
    <Port list='FF FF BF B0 00 00 00'/>
 </Config>
</MCU>
Ukážka 38: Štruktúra konfiguračného súboru PLC

Prvou časťou súboru je hlavička xml s definovanou verziou xml a kódovaním znakovej sady. Nasleduje koreňová sekcia MCU s parametrami type definuje typ PLC a description so základným popisom PLC. Táto sekcia obsahuje vetvu Address ktorej podvetvy definuje adresný priestor PLC a vetvu Command s parametrom list, obsahujúcim príkazy jazyka ST ktoré PLC podporuje. Adresa je definovaná menom podvetvy, počtom bytov count, začiatočnou 16bitovou adresou v pamäti mikrokontroléru memory a veľkosťou jednej bunky definovaného adresného priestoru v bitoch size. Je dôležité spomenúť, že kompilátor umožňuje prekrývanie pamäťového priestoru, tzn. jedinečne adresované miesto mikrokontroléra môže byť adresované pomocou viacerých adries PLC. Vetva Config definuje špecifické parametre PLC, ako veľkosť dátového bloku odosielaného programu, offset pamäte a porty ktoré obsahuje PLC.


1.4 Spolupráca programov LEX a YACC

V tejto časti popisujem spoluprácu programových modulov lex.py a yacc.py pri vytvorení prekladača jazyka ST. Výsledný modul STL.py bude kompilovať zdrojový kód v jazyku ST na strojový kód mikrokontroléra Atmel AVR. Princíp činnosti je vysvetlený na obrázku 2.

Princíp spolupráce je možne opísať v niekoľkých bodoch:

  1. Nakonfigurovaný lexikálny analyzátor STLex.py vyhľadá v zdrojovom kóde tzv. Tokeny (definované kľúčové slová).
  2. Zadefinujeme syntaktický analyzátor STLparser.py (vyhľadá možné kombinácie tokenov a spracováva chybové stavy).
  3. Definujeme konfiguračný súbor PLC pre ktoré je program kompilovaný.
  4. Kompilačnému modulu STL.py načítame konfiguračný súbor a zdrojový kód jazyka ST.
  5. Skompilovaný program je sekvencia strojových kódov, určených pre zadefinované PLC.

[[Image:|thumb|

Obrázok 2: Princíp tvorby a funkcie prekladača jazyka definovaného pomocou programov LEX a YACC

]]

Spomenuté možnosti a využitie modulu ply.py a teda programov LEX a YACC nevysvetľuje všetky možnosti využitia ktoré tieto programy ponúkajú. Ide o zhrnutie využitých vlastností počas vývoja kompilátora. Podrobnejšie informácie nájdete v literatúre [9] a [10].


1.5 Generovanie strojového kódu

Vstupom generátora strojového kódu je výstupná sekvencia parseru jazyka ST. Generátor identifikuje prvky sekvencie podľa Id, ktoré je prvým prvkom každého člena sekvencie.


[('LD', ('P', 0, 0)), ('LPS', None), ('LD', ('P', 0, 5)), ('O', ('P', 0, 7)), ('LD', ('P', 2, 1)), ('O', ('P', 1, 3)), ('=', ('P', 6, 0)), ('=', ('P', 1, 1)), ('A', ('P', 1, 0)), ('=', ('P', 3, 0))]
Ukážka 39: Výstupná sekvencia parseru


Druhým prvkom je parameter funkcie, ktorá sa zavolá podľa Id. Týmto parametrom býva najčastejšie adresa PLC. Pre generovanie strojového kódu je nezbytné aby tejto adrese odpovedala adresa mikrokontroléru. Hodnota adresy PLC je rôzna, pre rôzne mikrokontroléry na ktorých je PLC postavené. Tieto adresy sú definované v konfiguračnom súbore aktualizovanom pred samotným generovaním.


def cmd_LD(adr):
    """ Prikaz jazyka STL - LD adr"""
    return adr_htoi(['00','91'])+adr_FlipSplit(adr_ADR(adr))+    [adr[2]]+adr_htoi(['FB','00','27','00','F9','0F','93'])
Ukážka 40: Definovanie funkcie generátora

Z ukážky je zrejmé ako je definovaný generátor strojového kódu, konkrétne príkazu LD. Parameter adr je adresa bitovej premennej. Návratovou hodnotou je list strojových kódov. Funkcie adr_htoi prevedú list čísel v hexadecimálnej sústave na list typu int. Funkcia adr_ADR prevádza adresu PLC na adresu mikrokontroléra a funkcia adr_FlipSplit rozdelí 16 bitovú adresu na dve 8 bitové a tie medzi sebou zamení.

1.6 Prevod programu LAD do STL

Program jazyka LAD je dátovo reprezentovaný ako matica zoznamov predstavujúcich jednotlivé LAD symboly.


[
[False,“LD”,['V',100,1],False],[False,“LD”,['V',200,1],False], ..   
[False,“LD”,['V',101,0],False],[False,“LD”,['V',201,0],False], ..   
..
]
Ukážka 41: LAD program

Elementom takejto matice je teda zoznam. Jeho obsah je definovaný ako:

  1. element – Udáva či je objekt vertikálne prepojený s objektom v riadku pod ním
  2. element – Identifikátor príkazu
  3. element – Parametre. Ich počet je variabilný a závisí od príkazu.
    n. element - Posledný element predstavuje logicky stav v ktorom sa LAD objekt nachádza. Je dôležitý iba počas simulácie

Pri prevode program prechádza po riadkoch maticu LAD a ukladá do poľa blokov všetkých sériovo usporiadaných objektov. Ak je program prepojený s riadkom pod ním, je celá prepojená skupina uložená ako jeden blok. Tento blok je vnútorne rozdelený na jednotlivé paralelné vetvy.

[[Image:|thumb|Obrázok 3: Princíp blokového rozdelenia LAD programu]]Rozdeľovanie na paralelné vetvy sa vykonáva rekurzívne a preto môžu vzniknúť mnohonásobné vnorené štruktúry. Takto rozdelené pole je už možné jednoduchým spôsobom previesť na STL kód, prechádzaním elementov poľa.

2. Kompilátor IIC modulov

V tejto kapitole vysvetlím princíp modulov IIC a spôsob akým sú IIC zariadenia definované a akým spôsobom sa používajú v PLC. Samotné IIC zariadenie je pripojené na zbernici IIC mikrokontroléra s jedinečnou adresou.


2.1 Štruktúra IIC datagramu

Nato aby sa dali vyžiť možnosti IIC zariadení, je potrebné mať v PLC zadefinované príkazy, ktorými sa zariadenie ovláda. Tieto príkazy sú definované podľa katalógových listov výrobcu. Výsledkom je datagram nasledovnej štruktúry:


Skok EBL EBH EBB ADR SZ R/W SZ2 DL DH ... DL DH Skok EBL EBH ...

Posledný blok je ukončený 0.


Symbol Popis
Skok Počet bajtov do ďalšieho bloku
EBL Spodný bajt adresy povoľovacieho bytu
EBH Horný bajt adresy povoľovacieho bytu
EBB Maska povoľovacieho bitu
ADR IIC adresa
SZ Počet zapisovacích a čítacích podprogramov
R/W Typ akcie, 0 čítanie, 1 zápis
SZ2 Počet bytov dát

Dátový blok predstavuje sled operácií a dát potrebných na vykonanie nejakej udalosti IIC zariadenia.


2.2 Kompilácia IIC datagramu

Nato aby sa vytvoril nový IIC blok nieje potrebné presne definovať byty datagramu ale stačí nám opísať IIC príkazy symbolicky.


EN_C,W,123,DATA1,DATA2,R,DATA3
Ukážka 42: Symbolické vyjadrenie príkazu IIC

Ako je zrejme z ukážky je popisovanie príkazov IIC veľmi jednoduché. Prvá premenná EN_C je adresa povoľovacieho bitu, nasleduje typ podprogramu a konštanty s premennými.

O spracovanie symbolického zápisu IIC príkazov sa stará modul IIC.py, ktorý je súčasťou modulu Compiler. Na kompilovanie symbolického zápisu do databloku slúži príkaz compile(data,value,config),kde data tvorí list symbolických výrazov a adries IIC, value je slovník aliasov premenných a config je cesta ku konfiguračnému súboru PLC. Príkaz compile rozseká reťazec symbolického vyjadrenia na jednotlivé časti oddelené čiarkou. Takto pripravený zoznam parsuje na konštanty a adresy, s ktorých vytvára výsledný dátový blok IIC. Tento blok sa zapisuje do PLC súčasne s programom a veľkosťou programu.

3. Komunikačný modul

Účelom tejto kapitoly je vytvoriť komunikačný modul na zabezpečenie výmeny informácií medzi počítačom a PLC. Komunikácia prebieha v dvoch režimoch. Na protokole RS232 alebo cez USB (pomocou prevodníka RS232-USB). Pre jazyk Python je vytvorený veľmi silný nástroj na zabezpečenie sériovej komunikácie, modul pySerial. Informácie v tejto časti sú čerpané z [8].

3.1 Modul pySerial

Jedná sa o Pythonovský modul ktorý v sebe združuje nástroje na prístup k sériovému portu. Výhodou tohto modulu je multiplatformovosť a jednoduchosť. Konkrétny modul beží na operačnom systéme Windows, Linux a každý iný POSIX-ový systém. Taktiež umožňuje prístup k sériovému portu pomocou Jython a IronPython, čo značne rozširuje možnosti použitia daného modulu.


>>> import serial
>>> ser = serial.Serial('/dev/ttyS1', 19200, timeout=1)
>>> ser.isOpen()          #kontrola portu
True
>>> x = ser.read()        #čítanie jedného bytu
>>> ser.write("hello")    #zápis reťazca
>>> s = ser.read(10)      #čítanie 10 bytov (časovo obmedzené)
>>> line = ser.readline() #čítanie riadku ukončeného '\n'
>>> ser.close()
Ukážka 43: Základné operácie so sériovým portom


Ako je patrné z ukážky práca so sériovým portom pomocou pySerial je jednoduchá. Po importovaní modulu seriál môžeme vytvoriť objekt seriál pomocou ktorého budeme odosielať alebo prijímať informácie cez sériový port, resp. USB port. Takisto je možné definovať špecifickejšie parametre sériového portu ako: baudrate prenosová rýchlosť, bytesyze počet dátových bitov, parity paritu, stopbits počet stopbitov, timeout čakací čas a ďaľšie. Podrobnejšie informácie o module pySerial nájdete v literatúre [8].


3.2 Komunikačný protokol PLC

Cieľom komunikačného protokolu je presne definovať priebeh komunikácie medzi komunikujúcimi zariadeniami. Protokol definuje základné príkazy na riadenie a identifikačné kódy jednotlivých operácii a samotné telo správy. Informácie v tejto časti sú čerpané z [5].

3.2.1 Identifikácia PLC

Identifikuje pripojené PLC. Slúži na presné určenie konfigurácie pre kompilátor.


PC 0x01 ACK
PLC SIG0 SIG1 SIG2 RAM HIGHT RAM LOW STATUS
Symbol Popis
0x01 Kód PLC 0x01h
SIG0 Signatúra procesora
SIG1 Signatúra procesora
SIG2 Signatúra procesora
RAM HIGHT Horný byte adresy
RAM LOW Dolný byte adresy
STATUS Status plc

RUN

STOP

PAUSE

ACK Potvrdenie prenosu (0x0F)

3.2.2 Štart PLC

Spustí PLC (prepne do režimu RUN) pokiaľ bolo v stave STOP alebo PAUSE.


PC 0x02
PLC ACK
Symbol Popis
0x02 Kód PLC 0x02h
ACK Potvrdenie prenosu (0x0F)

3.2.3 Stop PLC

Zastaví PLC pokiaľ bolo v režime RUN alebo len zmení stav na STOP pokiaľ bolo PLC v režime PAUSE.


PC 0x03
PLC ACK
Symbol Popis
0x03 Kód PLC 0x03h
ACK Potvrdenie prenosu (0x0F)

3.2.4 Upload PLC

Príkaz na nahrávanie programu do PLC. Vstupom je sekvencia strojového kódu generovaná kompilátorom, rozdelená na 64 bytové bloky. Nekompletný blok musí byť doplnený nulami na svoju menovitú veľkosť. Koniec komunikácie musí byť potvrdený dvakrát.


PC 0x04 Prog 0-63 Prog 64-128 ACK ACK
PLC ACK ACK ACK
Symbol Popis
0x04 Kód PLC 0x04h
Prog 0-63 Program PLC 64 Bytov
Prog 63-128 Program PLC 64 Bytov
ACK Potvrdenie prenosu (0x0F)

3.2.5 Download PLC

Príkaz na načítanie programu z PLC. Výstupom je sekvencia strojového kódu mikrokontroléra AVR. Je rozdelená na 64 bytové bloky. Koniec prenosu je signalizovaný dvojitým potvrdením.


PC 0x05 ACK ACK
PLC Prog 0-63 Prog 64-128 ACK ACK
Symbol Popis
0x05 Kód PLC 0x05h
Prog 0-63 Program PLC 64 Bytov
Prog 63-128 Program PLC 64 Bytov
ACK Potvrdenie prenosu (0x0F)

3.2.6 Read PLC

Príkaz pre načítanie obsahu pamäťovej bunky PLC, definovanou 16 bitovou adresou.


PC 0x06 ADR HIGH ADR LOW ACK
PLC DATA
Symbol Popis
0x06 Kód PLC 0x06h
ADR HIGHT Horný byte adresy
ADR LOW Dolný byte adresy
DATA Hodnota na adrese 1 byte
ACK Potvrdenie prenosu (0x0F)

3.2.7 Write PLC config

Príkaz pre zápis konfiguračného bloku do pamäte PLC. Konfiguračný blok tvorí 14 bytov reprezentujúcich stavy výstupných portov v režime STOP a smer dát pre dané porty.


PC 0x08 PORT_ST PORT_DIR
PLC ACK
Symbol Popis
0x08 Kód PLC 0x08h
PORT_ST 7 bytov reprezentujúcich stav v stave STOP
PORT_DIR 7 bytov reprezentujúcich smer dát. Log. 1 = výstup.
ACK Potvrdenie prenosu (0x0F)

3.2.8 Read PLC config

Príkaz pre načítanie konfiguračného bloku s pamäte PLC. Konfiguračný blok tvorí 14 bytov reprezentujúcich stavy výstupných portov v režime STOP a smer dát pre dané porty.


PC 0x09
PLC PORT_ST PORT_DIR
Symbol Popis
0x09 Kód PLC 0x09h
PORT_ST 7 bytov reprezentujúcich stav v stave STOP
PORT_DIR 7 bytov reprezentujúcich smer dát. Log. 1 = výstup.

3.3 Komunikačný modul communication.py

Tento modul zabezpečuje spojenie počítača s PLC. Využíva k tomu spomínaný modul pySerial (serial.py). Pri návrhu musíme počítať s tým, že modul musí bežať na systéme Windows a tiež Linux. Preto je importovaný štandardný modul platform ktorý slúži na identifikáciu OS.

Pred samotnou komunikáciou je nutné vytvoriť inštanciu triedy COM. Po úspešnom vytvorení môžeme inicializovať port COM.Set_port(Port). Port predstavuje reťazec symbolizujúci adresu portu. Pre systém Windows je to COMn, naproti tomu system Linux používa dev/ttySn pre porty COM a dev/ttyUSBn pre porty USB.

Pre ľahšie identifikovanie prístupných portov je navrhnutá funkcia COM.Scan_port, navracajúca zoznám prístupných portov. Funkcia skenuje 256 COM adries pre Windows a 256 COM a 256 USB adries pre systém Linux.

Taktiež obsahuje príkazy komunikačného protokolu PLC. A to COM.Run_plc, COM.Stop_plc a COM.Pause_plc. Na nahrávanie programu slúži COM.Send_plc(data), kde data predstavujú sekvenciu strojového kódu vytvorenej kompilátorom.


4. Užívateľské prostredie

Cieľom tejto kapitoly je vytvoriť grafické užívateľské prostredie, ktoré bude využívať všetky možnosti predchádzajúcich modulov, (kompilátor, IIC, komunikácia). Pre tento účel som zvolil wxPython. Jedná sa o implementáciu knižnice wxWidgets pre pre jazyk python.

WxWidgets je povodne napísaný v jazyku C++ ako štruktúra zahŕňajúca nástroje na vytváranie GUI a iné nástroje, určené pre rôzne platformy. To znamená všetky verzie operačných systémov Windows, Unix s GTK+, Unix s Motif a MacOS. WxWidgets bol povodne vyvinutý v Artificial Intelligence Applications Institute, na univerzite v Edinburgu. Pôvodne určený pre vnútorné použitie, publikovaný bol v roku 1992.

4.1 Štruktúra užívateľského prostredia

Užívateľské prostredie v sebe zahŕňa niekoľko modulov. Modul kompilátora STL a IIC, komunikácie, služieb a hlavný Main modul. V blokovej schéme je zreteľne vidieť, že všetky moduly sú prepojené s hlavným modulom. Ten uchováva a poskytuje informácie o projekte ostatným modulom a tiež vykonáva interakcie medzi modulmi.

Obrázok 4: Štruktúra programu užívateľského prostredia

4.2 Obsluha užívateľského prostredia

Po spustení aplikácie vývojového prostredia sa nám ukáže hlavne formulárové okno obr. 4. V hornej časti sa nachádza nástrojová lišta. Obsahuje základné nástroje na prácu s projektom a PLC. Konkrétne, zľava vytvorenie nového projektu, otvorenie projektu, uloženie projektu, načítanie programu s pamäte PLC, nahratie programu do PLC, nahratie konfiguračného bloku, kompilácia zdrojového kódu, mapa pamäte, konfigurácia PLC, vytvorenie IIC datagramu, použitie IIC dtatgramu, spustenie a stop PLC.

Ľavú časť predstavuje okno projektu, kde môžeme vidieť a nastaviť parametre PLC a projektu samotného.

Pravá časť obsahuje editačné okno editora jazyka STL a okno pre výpis informačných správ.

[[Image:|thumb|
Obrázok 5: Okno užívateľského prostredia
]]4.2.1 Nastavenie konfiguračného bloku

Konfiguračný blok PLC slúži na definovanie vstupno/výstupných portov a stavu jednotlivých pinov v režime stop.

[[Image:|thumb|

Obrázok 6: Dialógové okno konfiguračného bloku

]]Na dialógovom okne vidíme polia zaškrtávacích políčok reprezentujúcich piny príslušných portov. Podľa zvoleného typu PLC sú aktivované alebo deaktivované tie piny, ktoré PLC neobsahuje. Na pravej strane sa nachádza schéma zvoleného PLC s rozmiestnením portov. Zmeny v konfiguračnom bloku sa v PLC prejavia až po nahratí konfiguračného bloku.


4.2.2 Nastavenie typu PLC

Na výber typu PLC slúži dialógové okno. Na ľavej strane sa nachádza list všetkých PLC ktorých konfiguračné súbory sa našli v zložke Config. Na pravej strane sa nachádza textový popis vybraného PLC. Tento popis je načítaný s XML konfiguračného súboru.

[[Image:|thumb|

Obrázok 7: Dialógové okno výberu typu PLC

]]Výber typu PLC je potrebný pre kompilátor STL a IIC, na identifikovanie podporovaných príkazov a rozsahu pamäti. Tiež ho vyžaduje modul komunikácie pre určenie veľkosti dátového bloku.


4.2.3 Nastavenie komunikačného portu PC/PLC

Po otvorení okna s nastavením komunikácie stačí vybrať príslušný port so zoznamu a potvrdiť. V prípade neskoršieho pripojenia je funkcia scan ktorá prehľadá všetky prístupné sériové a USB porty na PC.

[[Image:|thumb|
Obrázok 8: Dialógové okno nastavenia komunikácie
]]4.2.4 Vytvorenie IIC ovládača zariadenia

Tento formulár slúži na vytváranie konfiguračného súboru ovládačov pre IIC. Vyžaduje mena ovládača, adresy IIC, masky IIC a zoznamom všetkých príkazov IIC zariadenia. Výsledný ovládač je uložený vo formáte ini súboru. V prípade že chceme upravovať stávajúci ovládač použijeme funkciu load a nájdeme príslušný ovládač.

[[Image:|thumb|

Obrázok 9: Dialógové okno vytvárania ovládačov IIC

]]

4.2.5 Použitie IIC ovládača zariadenia

Ak chceme použiť IIC zariadenie musíme mať jeho ovládač v zložke Config/IIC. Pri otvorení dialógu sa automaticky vyhľadajú všetky ovládače a zobrazia sa v hornom zozname. Po pridaní ovládača do projektu Add, musíme vyplniť všetky premenné príkazov, ktoré sú definované.

[[Image:|thumb|

Obrázok 10: Dialógové okno použitia ovládačov IIC

]]

4.2.6 Konfigurácia terminálového modulu

Terminálový modul predstavuje zariadenie na vizualizácia, signalizáciu a získavanie údajov od užívateľa. Tento modul je štandardné IIC zariadenie v režime slave. Každá akcia ktorú modul vykonáva je závislá na požiadavke nadradeného zariadenia.

Úlohou nástroja na konfiguráciu terminálového modulu je vytvoriť IIC datagram pre konkrétny stav obrazovky, odoslanie premenných a načítanie stavu tlačítok. Taktiež treba generovať ST kód obsahujúci samotný obsah obrazovky a pomocne rutiny.

[[Image:|thumb|

Obrázok 11: Dialógové okno nastavenia terminálového modulu

]]Zoznam na pravej strane okna predstavuje všetky obrazovky ktoré máme pre dané PLC nakonfigurované. Pridávanie novej obrazovky sa vykoná tlačítkom Add a odstránenie tlačítkom Remove. Samotné telo správy sa vpisuje do stredného textového poľa. Zobrazenie premennej zabezpečujú formátovacie značky označené {premenná,adresa,počet znakov(,počet znakov desatinnej časti)}. Typ premennej je definovaný znakom B,W,F. Obrazovka ďalej umožňuje nastavenie signalizačného zvuku a povoľovacieho bitu ktorý zapíše obrazovku z PLC do terminálového modulu. Ak chceme použiť aj tlačidlá na terminále je potrebne v záložke Outputs definovať povoľovací bit a adresu kam sa majú uložiť 2 bajty predstavujúce stav tlačidiel.

Vygenerovaný ST kód je umiestnený na koniec zdrojového kódu a označený špeciálnym výrazom kvôli identifikácii.


#@Term@
# Nemazat tato cast kodu je generovana automaticky
#-----Screen------
ld        v100.0
movb      v10,116
movb      v11,101
movb      v12,115
movb      v13,116
movb      v14,32
movb      v15,37
movb      v16,51
movb      v17,100
#---------- beep,var
movb      v18,0
movb      v19,2
movb      v20,255
#------Variable-----
movb        v40,0
movb     v0,0
=        v0.0
ld        sp0.0
r        v0.1
r        v0.2
r        v0.3
ld        sp0.0
==b        v40,0
movb        v1,2
movd        v2, v105
s        v0.3
ld        sp0.0
incb        v40
==b        v40,1
movb        v40,0
Ukážka 44: Automaticky generovaný kód terminálového modulu
Výraz #@Term@ je identifikačná značka určená pre ľahké rozpoznávanie generovaného kódu od užívateľského programu. Vygenerovaný kód pre terminálový modul pozostáva z dvoch častí. 

V prvej časti sa uložia znaky formátovacieho reťazca a ukončia sa 0. pridá sa adresa premenných ktoré sú použité na obrazovke a dĺžka pípnutia. Dĺžka formátovacieho reťazca je obmedzená na 32 viditeľných znakov, vzhľadom na použitý modul znakového displeja 16x2. Dĺžka zvukovej signalizácie je voliteľná v 5 možnostiach (žiaden zvuk, krátke pípnutie, stredne dlhé pípnutie, dlhé a veľmi dlhé pípanie).

V druhej časti sa nachádza vynulovanie počítadiel a povoľovacích bitov pre odoslanie premenných a rutiny ktoré definujú zdrojovú a cieľovú adresu odoslanej premennej v pamäti terminálového modulu.

4.2.7 Online sledovanie obsahu pamäte PLC

Jedným z užitočných diagnostických nástrojov vývojového prostredia je Memorymap alebo tiež nástroj na online sledovanie obsahu pamäte PLC. Hlavný princíp nástroja spočíva v cyklickom načítavaní obsahu pamäte cez sériový port, dekódovaní a vypisovaní dát na obrazovku. 

[[Image:|thumb|Obrázok 12: Okno Memory map - online sledovania obsahu pamäte]]

4.2.8 Editor LAD

Na tvorbu programu pre PLC je primárne určený jazyk STL. Ak užívateľ preferuje tvorbu programov pomocou rebríkových schém (LAD), stačí prepnúť záložku nad textovým editorom STL do režimu LAD. V tomto režime pracuje vývojové prostredie ako LAD editor. 

[[Image:|thumb|

Obrázok 13: LAD editor

]]Na tvorbu programu teraz stačí kurzorom myši označiť pozíciu na ploche LAD editora a z panela na ľavej strane vybrať príslušnú schematickú značku. Po vytvorení schémy je program možné skompilovať ako STL kód. Pri tomto procese sa matica LAD schémy prevedie na postupnosť STL príkazov a spojí sa s kódom STL editora. Toto umožňuje spoluprácu nástroja na konfiguráciu terminálového modulu s editorom LAD aj STL. Pretože jazyky STL a LAD sú štrukturálne podobné, nieje potrebné písať zvlášť kompilátor na LAD a STL ale postačí prevodník z LAD do STL.

LAD schéma programu slúži nielen na programovanie ale využíva sa aj pri simulácii. V tomto režime sú schematické značky farebne označené pre jasnú identifikáciu aktuálneho stavu.

[[Image:|thumb|

Obrázok 14: Editor LAD v režime simulácie

]]Simulácia prebieha cyklicky a v každom cykle sa kontrolujú stavy vstupov a stav bitu ktorý značka predstavuje. Vstupom rozumieme stav výstupu predchádzajúcej značky. Zelenou sú potom označené tie značky ktorých vstup a vnútorný stav je logická 1 a červenou všetky ostaté značky. Ručné zmeny stavov sa dajú vykonať v okne Memory map kde prepísaním hodnoty na príslušnej adrese zmeníme aj hodnoty stavov príslušných LAD objektov.


4.3 Štruktúra projektového súboru

Projektový súbor ktorý užívateľ používa je klasický xml súbor. Na prácu s projektovými súbormi slúži modul Project.py. Modul sa stará o načítavanie a ukladanie projektov a serializáciu dátových štruktúr.


<project>
     <head author="" date="" description="" name="Olare" version="1.0" />
     <code>
          <stlcode> ... </stlcode>
          <ladcode> ... </ladcode>
     </code>
     <config config="myPLC32.xml" inputs="0 0 0 0 0 0 0 " programversion="1.0" state="0 0 0 0 0 0 0 " />
     <workspace> ... </workspace>
     <iic>...</iic>
     <terminal>...</terminal>
     <terminaliic>...</terminaliic>
</project>
Ukážka 45: Štruktúra projektového xml súboru

Projekt v hlavičke definuje základné informácie o projekte, ako autor, dátum vytvorenia, popis , názov a verziu projektu. Sekcia code obsahuje textovú podobu STL programu a serializované dáta matice LAD programu. V sekcii config definujeme typ PLC pre ktorý je projekt napísaný a stav konfiguračného bloku. Sekcia workspace obsahuje serializované dáta popisujúce rozloženie okien a panelov v projekte. Iic a terminaliic sú sekcie kde sa nachádzajú serializované IIC datagrami zariadení a terminálového modulu. Sekcia terminal predstavuje dáta pre konfiguráciu terminálového modulu.


Záver

Cieľom diplomovej práce bolo vytvoriť softvérové vybavenie pre jedončipové PLC, umožňujúce kompilovať, nahrávať a čítať programy pre toto PLC. Taktiež bolo potrebné umožniť užívateľovi prácu s IIC zariadeniami pomocou rôznych konfiguračných nástrojov.

Cieľ práce sa podarilo splniť. Bol vytvorený kompilátor jazyka STL s kontrolou syntaxe, kompilátor IIC datablokov a tiež modul na prevod schém jazyka LAD do kódu STL. Úspešne bol implementovaný komunikačný protokol a tiež samotná komunikácia cez modul pyserial. Podarilo sa vytvoriť základné užívateľské prostredie s využitím knižnice wxWidgets, pre jednoduchú prácu s uvedenými modulmi a tiež nástroje na diagnostiku a sledovanie PLC v reálnom čase. Do vývojového prostredia bola tiež úspešne implementovaná podpora IIC zariadení a nástroj na jednoduché konfigurovanie terminálového modulu.

Softvérové vybavenie bolo vytvorené ako program jazyka Python s využitím príslušných knižníc uvedených v prílohe. To umožňuje jeho použitie na rôznych operačných systémoch ako Windows, Linux a teoreticky MAC. 

Program bol testovaný s verziou jednočipového PLC na báze ATMega 32 a ATMega 8 kde pracoval stabilne bez porúch. Pri testoch sme použili operačné systémy Windows XP a distribúciu Arch Linux. Kompilátor STL, komunikačný modul, IIC zariadenia, terminálová konfigurácia a prevodník LAD-STL pracovali správne.

Možnosti ďalšieho postupu pri zdokonaľovaní a vylepšovaní stávajúceho vývojového prostredia je niekoľko. Veľmi užitočná by bola podpora funkcií a kompozitných blokov v STL a LAD. Pre tento účel by bolo treba definovať nové gramatické pravidlá v syntaktickej analýze kompilátora. Ďalšia vec ktorá by zvýšila úroveň práce je lepšia podpora komunikácie medzi viacerými PLC a možnosť prepojenia celej siete zariadení.


Použitá literatúra

  1. Váňa, V.: Mikrokontroléry ATMEL AVR – Popis procesoru a instrukční soubor. BEN – technická literatúra, Praha, 2003. ISBN 80-7300-083-0
  2. Harms, D. - Mcdonald, K.: - Začíname programovat v jazyce Python. Computer press, 2008. ISBN 978-80-2512-161-0
  3. Van Rossum, G.: Python Library Reference, relase 2.5.2. 21. Február, 2008. http://www.python.org/doc/
  4. Smart, J. - Roebling, R. - Zeitlin, V. - Dunn, R.: wxWidgets 2.8.4: A portable C++ and Python GUI toolkit, March, 2007, http://www.wxpython.org
  5. Sova, M.: Návrh a realizácia jednočipového PLC, Diplomová práca, TNUAD v Trenčíne, 2010
  6. Kloz, V.: Softwárové PLC, Diplomová práce, ČVUT v Prahe, 2003
  7. A.M. Kuchling. Regular Expression HOWTO, posledná aktualizácia 3. 3. 2007 http://www.amk.ca/python/howto/regex
  8. Liechti C.: pySerial – Python Serial Port Extension, 2008, http://pyserial.sf.net
  9. Bazley M. D.: PLY (Python Lex – Yacc), PLY version 2.5, Máj, 2008, posledná aktualizácia 11. 5. 2008, http://groups.google.com/group/ply-hack[1]
  10. Niemann T.: A Compact Guide To Lex&Yacc, ePaper Press
  11. Siemens AG: Programovatelný automat s7-200 Systémový manuál, Jún, 2004
  12. Julian Smart, Robert Roebling, Vadim Zeitlin, Robin Dunn, et al: wxWidgets 2.8.4: A portable C++ and Python GUI toolkit, Marec, 2007


Príloha A – CD

  • Aplikácia myPLC_Studio
  • Kópia diplomovej práce
  • Inštalačné programy
  • Ukážkové projekty